2

I'm beginning to write a web app that will allow users to annotate embedded YouTube videos with certain events. I'd like the user to be able to pause the video, pull up a menu of candidate events (say, as a modal), and save the selected event along with the associated time in the video that the event occurred to a database.

I don't know how to retrieve the time at which the pause button was pressed.

I'm assuming that the YouTube API would be the place to go for this, but I've spent about two hours exploring and finding no leads. Any advice for approach? Good accessible tutorials/examples of this suitable for beginners?

Atticus29
  • 4,190
  • 18
  • 47
  • 84

1 Answers1

3

You can use Youtube iframe API to get the current time on state PAUSED using player.getCurrentTime() :

HTML :

<iframe id="video" src="https://www.youtube.com/embed/CaksNlNniis?enablejsapi=1&html5=1&" frameborder="0" allowfullscreen="0"></iframe>
<input id="pause" type="submit" value="pause" />
<input id="play" type="submit" value="play" />

Javascript :

var player;

function onYouTubeIframeAPIReady() {
  player = new YT.Player('video', {
    events: {
      'onReady': onPlayerReady,
      'onStateChange': onPlayerStateChange
    }
  });
}

function onPlayerStateChange(event) {
  if (event.data == YT.PlayerState.PAUSED) {
    console.log(player.getCurrentTime());
  }
}

function onPlayerReady(event) {
  document.getElementById("pause").addEventListener("click", function() {
    player.pauseVideo();
  });
  document.getElementById("play").addEventListener("click", function() {
    player.playVideo();
  });
}

var tag = document.createElement('script');
tag.src = "//www.youtube.com/player_api";
var firstScriptTag = document.getElementsByTagName('script')[0];
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);

You can find a working jsfiddle here

As the PAUSED state can also be triggered independently from your button click, you can also store the currentTime before you call player.pauseVideo() :

HTML :

<iframe id="video" src="https://www.youtube.com/embed/CaksNlNniis?enablejsapi=1&html5=1&" frameborder="0" allowfullscreen="0"></iframe>
<input id="pause" type="submit" value="pause" />
<input id="play" type="submit" value="play" />
<ul id="timing"></ul>

Javascript :

var player;
var timeList;
var count = 0;

function onYouTubeIframeAPIReady() {
  player = new YT.Player('video', {
    events: {
      'onReady': onPlayerReady,
      'onStateChange': onPlayerStateChange
    }
  });
}

function onPlayerStateChange(event) {}

function onPlayerReady(event) {
  document.getElementById("pause").addEventListener("click", function() {
    logTime();
    player.pauseVideo();
  });
  document.getElementById("play").addEventListener("click", function() {
    player.playVideo();
  });
}

document.addEventListener("DOMContentLoaded", function(event) {
  timeList = document.getElementById("timing");
});

function logTime() {
  count++;
  var time = player.getCurrentTime();
  var newTime = document.createElement('li');
  var textNode = document.createTextNode('pause ' + count + ' - ' + time + " ");
  var buttonNode = document.createElement('button');
  buttonNode.addEventListener("click", function() {
    console.log("go to " + time);
    player.seekTo(time);
    player.playVideo();
  });
  var btnText = document.createTextNode("go back");
  buttonNode.appendChild(btnText);
  newTime.appendChild(textNode);
  newTime.appendChild(buttonNode);
  buttonNode.appendChild(btnText);
  timeList.appendChild(newTime);
}

var tag = document.createElement('script');
tag.src = "//www.youtube.com/player_api";
var firstScriptTag = document.getElementsByTagName('script')[0];
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);

Check this fiddle

Bertrand Martel
  • 42,756
  • 16
  • 135
  • 159
  • Thanks, @Bertrand Martel. I'm getting the following error: "Cannot find name 'YT' ". Any advice? – Atticus29 Dec 01 '17 at 18:08
  • @Atticus29 Do you have a fiddle that repoduce this error ? Do you include `https://www.youtube.com/player_api` like specified [here](https://developers.google.com/youtube/player_parameters) and in the fiddle as well. – Bertrand Martel Dec 01 '17 at 18:39
  • I literally just copied your html into my angular component's html file and your js into my component's typescript file. Incidentally, I don't see inclusion of https://www.youtube.com/player_api in your fiddle. Pretty new to fiddle, though; perhaps I'm not looking in the right place for it? – Atticus29 Dec 01 '17 at 18:45
  • I stand, corrected. I see it now. But yes, it's there in my code as well. – Atticus29 Dec 01 '17 at 18:50
  • The problem is the line, "player = new YT.Player('video', {..." Is there something I should be importing? – Atticus29 Dec 01 '17 at 18:55
  • Maybe same problem [here](https://stackoverflow.com/questions/45811033/onyoutubeiframeapiready-on-angular2-cant-find-name-yt) – Bertrand Martel Dec 01 '17 at 18:56
  • From the previous link, this [post](https://stackoverflow.com/questions/42868225/onyoutubeiframeapiready-not-firing-on-angular2-web-app#) way help – Bertrand Martel Dec 01 '17 at 19:05
  • I've made onYouTubeIframeAPIReady available globally using (window as any).onYouTubeIframeAPIReady. Now there's this error: Argument of type '{events: {'onReady':(event:any) => void; 'onStateChange': (event:any)=>void;};}' is not assignable to parameter of type 'PlayerOptions'. Thanks for this additional assistance, @Bertrand Martel! Definitely not as straightforward as it could be. – Atticus29 Dec 01 '17 at 19:31