Example 2: Captions, Descriptions, Chapters, and MetaData

Example 2: showing video description while playing, listening to events, changing the mode of a track

Each track has a mode property (and a mode attribute) that can be: “disabled”“hidden” or “showing”. More than one track at a time can be in any of these states.  The difference between “hidden” and “disabled” is that hidden tracks can fire events (more on that at the end of the first example) whereas disabled tracks do not fire events.

Here is an example at JSBin that shows the use of the mode property, and how to listen for cue events in order to capture the current subtitle/caption from JavaScript. You can change the mode of each track in the video element by clicking on its button. This will toggle the mode of that track. All tracks with mode=”showing” or mode=”hidden” will have the content of their cues displayed in real time in a small area below the video.

In the screen-capture below, we have a WebVTT file displaying a scene’s captions and descriptions.

Example that shows how to toggle track modes and listen to events

Extract from HTML code:

  1. <html lang=”en”>
  2. <body onload=”init();”>
  3. <p>
  4.   <video id=”myVideo” preload=”metadata”
  5.         poster =”https://&#8230;../sintel.jpg”
  6.         crossorigin=”anonymous”
  7.         controls=”controls”
  8.         width=”640″ height=”272″>
  9.     <source src=”https://&#8230;../sintel.mp4″
  10.             type=”video/mp4″ />
  11.     <source src=”https://&#8230;../sintel.webm”
  12.             type=”video/webm” />
  13.     <track src=”https://&#8230;../sintel-captions.vtt”
  14.            kind=”captions”
  15.            label=”English Captions”
  16.            default/>
  17.     <track src=”https://&#8230;../sintel-descriptions.vtt”
  18.            kind=”descriptions”
  19.            label=”Audio Descriptions” />
  20.     <track src=”https://&#8230;../sintel-chapters.vtt”
  21.            kind=”chapters”
  22.            label=”Chapter Markers” />
  23.     <track src=”https://&#8230;../sintel-thumbs.vtt”
  24.            kind=”metadata”
  25.            label=”Preview Thumbs” />
  26.   </video>
  27. </p>
  28. <p>
  29.    
  30. <p>
  31. <p>
  32.    
  33. </p>
  34. <p>
  35.    <button onclick=”clearSubtitlesCaptions();”>
  36.       Clear subtitles/captions log
  37.    </button>
  38. </p>
  39.  
  40. <p>Click one of these buttons to toggle the mode of each track:</p>

  41. <button onclick=”toggleTrack(0);”>
  42.      Toggle english caption track mode
  43.  </button>
  44.  <br>
  45. <button onclick=”toggleTrack(1);”>
  46.      Toggle audio description track mode
  47. </button>
  48. <br>
  49. <button onclick=”toggleTrack(2);”>
  50.      Toggle chapter track mode
  51. </button>
  52. <br>
  53. <button onclick=”toggleTrack(3);”>
  54.      Toggle preview thumbnail track modes
  55. </button>
  56.  
  57. </body>
  58. </html>

JavaScript code:

  1. var tracks, video, statusDiv, subtitlesCaptionsDiv;
  2.  
  3. function init() {
  4.    video = document.querySelector(“#myVideo”);
  5.    statusDiv = document.querySelector(“#currentTrackStatuses”);
  6.    subtitlesCaptionsDiv = document.querySelector(“#subtitlesCaptions”);
  7.    tracks = document.querySelectorAll(“track”);
  8.    video.addEventListener(‘loadedmetadata’, function() {
  9.       console.log(“metadata loaded”);
  10.       // defines cue listeners for the active track; we can do this only after the video metadata have been loaded
  11.       for(var i=0; i<tracks.length; i++) {
  12.          var t = tracks[i].track;
  13.          if(t.mode === “showing”) {
  14.             t.addEventListener(‘cuechange’, logCue, false);
  15.          }
  16.        }
  17.        // display in a div the list of tracks and their status/mode value
  18.        displayTrackStatus();  
  19.     });
  20. }
  21.  
  22. function displayTrackStatus() {
  23.     // display the status / mode value of each track.
  24.     // In red if disabled, in green if showing
  25.     for(var i=0; i<tracks.length; i++) {
  26.        var t = tracks[i].track;
  27.        var mode = t.mode;
  28.        if(mode === “disabled”) {
  29.           mode = “<span style=’color:red’>” + t.mode + “</span>”;
  30.        } else if(mode === “showing”) {
  31.           mode = “<span style=’color:green’>” + t.mode + “</span>”;
  32.        }
  33.        appendToScrollableDiv(statusDiv, “track ” + i + “: ” + t.label
  34.                                         + ” ” + t.kind+” in “
  35.                                         + mode + ” mode”);
  36.     }
  37. }
  38. function appendToScrollableDiv(div, text) {
  39.    // we’ve got two scrollable divs. This function
  40.    // appends text to the div passed as a parameter
  41.    // The div is scrollable (thanks to CSS overflow:auto)
  42.    var inner = div.innerHTML;
  43.    div.innerHTML = inner + text + “<br/>”;
  44.    // Make it display the last line appended
  45.    div.scrollTop = div.scrollHeight;
  46. }
  47.  
  48. function clearDiv(div) {
  49.    div.innerHTML = ”;
  50. }
  51.  
  52. function clearSubtitlesCaptions() {
  53.    clearDiv(subtitlesCaptionsDiv);
  54. }
  55. function toggleTrack(i) {
  56.    // toggles the mode of track i, removes the cue listener
  57.    // if its mode becomes “disabled”
  58.    // adds a cue listener if its mode was “disabled”
  59.    // and becomes “hidden”
  60.    var t = tracks[i].track;
  61.    switch (t.mode) {
  62.       case “disabled”:
  63.          t.addEventListener(‘cuechange’, logCue, false);
  64.          t.mode = “hidden”;
  65.          break;
  66.       case “hidden”:
  67.          t.mode = “showing”;
  68.          break;
  69.       case “showing”:
  70.          t.removeEventListener(‘cuechange’, logCue, false);
  71.          t.mode = “disabled”;
  72.          break;
  73.     }
  74.     // updates the status
  75.     clearDiv(statusDiv);
  76.     displayTrackStatus();
  77.     appendToScrollableDiv(statusDiv,”<br>” + t.label+” are now ” +t.mode);
  78. }
  79.  
  80. function logCue() {
  81.    // callback for the cue event
  82.    if(this.activeCues && this.activeCues.length) {
  83.       var t = this.activeCues[0].text; // text of current cue
  84.       appendToScrollableDiv(subtitlesCaptionsDiv, “Active “
  85.                                           + this.kind + ” changed to: ” + t);
  86.    }
  87. }

Leave a comment