2
votes

I receive h.264/aac encoded mp4 video files and I want to play them back. Some of my video files have multiple audio streams or tracks within them (eg an english stream and a spanish stream). I want to allow the user to switch between the two audio tracks. I've tried video.js, which will play the video and default audio stream just fine, but I don't see any way to change audio tracks within the UI, and videojs.audioTracks() always returns an empty array (I'm using Chrome and I only need to support Chrome).

var video = document.getElementById("video");
video.audioTracks; // <-- undefined

AND

let video = videojs('video');
let audioTrackList = video.audioTracks();
audioTrackList.tracks; // <-- [] empty array

Does anyone know of a solution, whether it be something I'm doing wrong or missing in video.js, a plugin/extension for video.js, or a different player altogether?

EDIT:

Here's a basic example html file:

<html>
<head>
  <link href="https://vjs.zencdn.net/7.7.5/video-js.css" rel="stylesheet" />

<body>
  <video
    id="my-video"
    class="video-js"
    controls
    preload="auto"
    width="640"
    height="264"
    data-setup="{}"
  >
    <source src="http://clips.vorwaerts-gmbh.de/VfE_html5.mp4" type="video/mp4" />
    <p class="vjs-no-js">
      To view this video please enable JavaScript, and consider upgrading to a
      web browser that
      <a href="https://videojs.com/html5-video-support/" target="_blank"
        >supports HTML5 video</a
      >
    </p>
  </video>

  <script src="https://vjs.zencdn.net/7.7.5/video.js"></script>
<script>
var vid = document.getElementById("my-video");
vid.onloadeddata = function() {

    // get the current players AudioTrackList object
    var player = videojs('my-video')
    let tracks = player.audioTracks();

    alert(tracks.length);

    for (let i = 0; i < tracks.length; i++) {
        let track = tracks[i];
        console.log(track);
        alert(track.language);
    }
};
</script>
</body>
</html>

And it only ever alerts "0". No subsequent alerts and console logs. Tested in Chrome, Firefox, and Edge.

UPDATE: I finally discovered that enabling the flag, "enable-experimental-web-platform-features" in chrome://flags (https://caniuse.com/#feat=audiotracks) lets this method work.

Here's some basic html code:

<html>
<head>
    <link href="https://vjs.zencdn.net/7.7.5/video-js.css" rel="stylesheet"/>
<body>
<video
        id="my-video"
        class="video-js"
        controls
        preload="auto"
        width="640"
        height="264"
        data-setup="{}">
    <source src="http://clips.vorwaerts-gmbh.de/VfE_html5.mp4" type="video/mp4"/>
    <p class="vjs-no-js">
        To view this video please enable JavaScript, and consider upgrading to a
        web browser that
        <a href="https://videojs.com/html5-video-support/" target="_blank"
        >supports HTML5 video</a
        >
    </p>
</video>

<button onclick="onClick()">Toggle Audio</button>
<script src="https://vjs.zencdn.net/7.7.5/video.js"></script>
<script>
    var VIDEO_JS = videojs('my-video');

    function onClick() {
        let tracks = VIDEO_JS.audioTracks();

        tracks.tracks_[0].enabled = !tracks.tracks_[0].enabled;
        tracks.tracks_[1].enabled = !tracks.tracks_[1].enabled;
    }
</script>
</body>
</html>

But toggling the audio back and forth doesn't work well. The audio instantly toggles, but the video freezes until it catches up or something, but everything gets out of sync.

2

2 Answers

1
votes

You should convert your videos to HLS. Video.js supports multiple audio tracks automatically with HLS.

0
votes

Audio track user switching is not currently supported by video.js according to the video.js documentation (https://docs.videojs.com/docs/guides/audio-tracks.html):

Missing Funtionality

It is currently impossible to add AudioTracks in a non-programtic way Literal switching of AudioTracks for playback is not handled by video.js and must be handled by something else. video.js only stores the track representation

You can add, remove and enable tracks programatically - the doucmetaion for this is included in the link above.

To see all the audio tracks in a video:

player.audioTracks() -> AudioTrackList

This is the main interface into the audio tracks of the player. It returns an AudioTrackList which is an array like object that contains all the AudioTrack on the player.

If you look at the snippet below, it shows a video starting and the audio tracks being listed using the method above. Look at the alerts and the console output (there appears to be an error in the console from the latest video.js distribution at the time of writing, but you can ignore this and scroll down and you will see the audio track listing) .

This is based on the video.js start guide and you can substitute any video URL you have to check your own video.

var vid = document.getElementById("my-video");
vid.onloadeddata = function() {
        
    // get the current players AudioTrackList object
    var player = videojs('my-video')
    let tracks = player.audioTracks();
    
    alert(tracks.length);
    
    for (let i = 0; i < tracks.length; i++) {
        let track = tracks[i];
        console.log(track);
        alert(track.language);
    }
};
<head>
  <link href="https://vjs.zencdn.net/7.7.5/video-js.css" rel="stylesheet" />

<body>
  <video
    id="my-video"
    class="video-js"
    controls
    preload="auto"
    width="640"
    height="264"
    data-setup="{}"
  >
    <source src="http://clips.vorwaerts-gmbh.de/VfE_html5.mp4" type="video/mp4" />
    <p class="vjs-no-js">
      To view this video please enable JavaScript, and consider upgrading to a
      web browser that
      <a href="https://videojs.com/html5-video-support/" target="_blank"
        >supports HTML5 video</a
      >
    </p>
  </video>
  
  <script src="https://vjs.zencdn.net/7.7.5/video.js"></script>

</body>