Skip welcome & menu and move to editor
Welcome to JS Bin
Load cached copy from
 
<html lang="en">
<head>
  <meta charset=utf-8>
  <title>Video player with clickable transcript</title>
</head>
<body>
  <section id="all">
    <h1>Using the track API to extract the content of webVTT files in <code>&lt;track&gt;</code> elements</h1>
    <p>Click on the buttons under the video to extract the english or german subtitles, or to display the chapter markers (english).
    </p>
    <p>Look at the HTML and JS code.</p>
    <p>
      <button disabled id="buttonEnglish" onclick="loadTranscript('en', 'subtitles');">Display English transcript</button>
      <button disabled id="buttonDeutsch" onclick="loadTranscript('de', 'subtitles');">Display Deutsch transcript</button>
            <button disabled id="buttonEnglishChapters" onclick="loadTranscript('en', 'chapters');">Display English chapter markers</button>
    </p>
    <video id="myVideo" preload="metadata" controls crossOrigin="anonymous">
      <source src="https://mainline.i3s.unice.fr/mooc/elephants-dream-medium.mp4" type="video/mp4">
      <source src="https://mainline.i3s.unice.fr/mooc/elephants-dream-medium.webm" type="video/webm">
      <track label="English subtitles" kind="subtitles" srclang="en" src="http://mainline.i3s.unice.fr/mooc/elephants-dream-subtitles-en.vtt" >
        <track label="Deutsch subtitles" kind="subtitles" srclang="de" src="https://mainline.i3s.unice.fr/mooc/elephants-dream-subtitles-de.vtt" default>
          <track label="English chapters" kind="chapters" srclang="en" src="https://mainline.i3s.unice.fr/mooc/elephants-dream-chapters-en.vtt">
    </video>
    <div id="transcript"></div>
  </section>
</body>
</html>
 
var video, transcriptDiv;
var tracks, trackElems, tracksURLs = [];
var buttonEnglish, buttonDeutsch, buttonEnglishChapters;
window.onload = function() {
  console.log("init");
  // when the page is loaded
  video = document.querySelector("#myVideo");
  transcriptDiv = document.querySelector("#transcript");
  
  // The tracks as HTML elements
  trackElems = document.querySelectorAll("track");
  for(var i = 0; i < trackElems.length; i++) {
    var currentTrackElem = trackElems[i];
    tracksURLs[i] = currentTrackElem.src;
  }
  
  buttonEnglish = document.querySelector("#buttonEnglish");
  buttonDeutsch = document.querySelector("#buttonDeutsch");
  buttonEnglishChapters = document.querySelector("#buttonEnglishChapters");
  
  // we enable the buttons and show transcript
  buttonEnglish.disabled = false;
  buttonDeutsch.disabled = false;
    buttonEnglishChapters.disabled = false;
  // The tracks as JS objects
  tracks = video.textTracks;
};
function loadTranscript(lang, kind) {
  // clear current transcript
  clearTranscriptDiv();
  
  // set all track mode to disabled. We will only activate the
  // one whose content will be displayed as transcript
  if(kind !== 'chapters')
      disableAllTracks(); // if displaying chapters, do not
                          // disable all tracks
  
  // Locate the track with language = lang
  for(var i = 0; i < tracks.length; i++) {
    // current track
    var track = tracks[i];
    var trackAsHtmlElem = trackElems[i];
  
    if((track.language === lang) && (track.kind === kind)) {
      track.mode="showing";
      if(trackAsHtmlElem.readyState === 2) {
        // the track has already been loaded
        displayCues(track);
      } else {
        displayCuesAfterTrackLoaded(trackAsHtmlElem, track);
      }
      
/*      track.addEventListener("cuechange", function(e) {
        var cue = this.activeCues[0];
        console.log("cue change");
        var transcriptText = document.getElementById(cue.id);
        transcriptText.classList.add("current");
      });
      */
    }
  } 
}
  
function displayCuesAfterTrackLoaded(trackElem, track) {
  // Create a listener that will be called only when the track has
  // been loaded
  trackElem.addEventListener('load', function(e) {
      console.log("track loaded");
      displayCues(track);
   });
}
function disableAllTracks() {
    for(var i = 0; i < tracks.length; i++) 
      tracks[i].mode = "disabled";
}
function displayCues(track) {
    var cues = track.cues;
    
    //append all the subtitle texts to 
      for(var i=0, len = cues.length; i < len; i++) {
        var cue = cues[i];
        addCueListeners(cue);
        var voices = getVoices(cue.text);
        var transText="";
        if (voices.length > 0) {
            for (var j = 0; j < voices.length; j++) { // how many voices ?
                transText += voices[j].voice + ': ' + removeHTML(voices[j].text);
            }
          } else 
             transText = cue.text; // not a voice text
        var clickableTransText = "<li class='cues' id=" + cue.id +  " onclick='jumpTo(" + cue.startTime + ");'" + ">" + transText + "</li>";
        addToTranscriptDiv(clickableTransText);
      }
  }
function getVoices(speech) {  // takes a text content and check if there are voices 
  var voices = [];            // inside
  var pos = speech.indexOf('<v'); // voices are like <v michel> ....
  while (pos != -1) {
    endVoice = speech.indexOf('>');
    var voice = speech.substring(pos + 2, endVoice).trim();
    var endSpeech = speech.indexOf('</v>');
    var text = speech.substring(endVoice + 1, endSpeech);
    voices.push({
       'voice': voice,
       'text': text
    });
    speech = speech.substring(endSpeech + 4);
    pos = speech.indexOf('<v');
  }
  return voices;
}
function removeHTML(text) {
  var div = document.createElement('div');
  div.innerHTML = text;
  return div.textContent || div.innerText || '';
}
function jumpTo(time) {
  video.currentTime = time;
  video.play();
}
function clearTranscriptDiv() {
  transcriptDiv.innerHTML = "";
}
function addToTranscriptDiv(htmlText) {
  transcriptDiv.innerHTML += htmlText;
}
function addCueListeners(cue) {
  cue.onenter = function(){
    console.log('enter id=' + this.id);
    var transcriptText = document.getElementById(this.id);
    transcriptText.classList.add("current");
  };
  cue.onexit = function(){
    console.log('exit id=' + cue.id);
   var transcriptText = document.getElementById(this.id); transcriptText.classList.remove("current");
  };
}
Output

You can jump to the latest bin by adding /latest to your URL

Dismiss x
public
Bin info
AuroreDechampspro
0viewers