Respond to Embedded YouTube Video Events

By Rob Gravelle

Respond to Embedded YouTube Video Events

There are certain video events that you can respond to such as when the video starts, stops, is paused, or is buffering. There's only so much you can do using an embed URL or the YouTube Video Editor. For more fine-grained control over events and all aspects concerning playback you can't do better than the YouTube JavaScript Player API. In today's article we'll learn how to configure a video to use the API to respond to events.

Initializing the YouTube Player API

The designers of the API faced the challenge of making the API player agnostic so that it would work for any player type and generation style (markup vs. script code). The solution they came up with was to add a query parameter to the URL called "enablejsapi". Setting it to 1 turns on the JavaScript API.

For example, to enable the API in a chromeless player so that you can build your own custom player controls, modify the URL as follows:

http://www.youtube.com/apiplayer?enablejsapi=1&version=3

Here's a URL that loads an embedded video player. Note that the last part before the question mark is the VIDEO_ID:

http://www.youtube.com/v/5EnL2WXsxNQ?version=3&enablejsapi=1

You'll also need to reference the API script itself. Include a script tag in your document and point the src to "the http://www.youtube.com/iframe_api" and you're done.

The onYouTubeIframeAPIReady() Event: Where It All Begins

As soon as the API is done loading and ready to receive calls it invokes a JavaScript function named onYouTubePlayerReady. But that's the only named event. To be notified of other video events, you have to add event listeners yourself.

As a simple example, let's suppose that you have the following embedded video in your web page:

<iframe id="ik_player_iframe" frameborder="0" height="315" src="http://www.youtube.com/embed/5EnL2WXsxNQ?enablejsapi=1" width="560"></iframe>

Take note of the iFrame id, because that is what we use to instantiate the YouTube Player object. We can then add event listeners to it. In the example below, onYouTubeIframeAPIReady() will be called first, followed by onYouTubePlayerReady() and onYouTubePlayerStateChange():

//Holds a reference to the YouTube player
var ik_player;

//this function is called by the API
function onYouTubeIframeAPIReady() {
  //creates the player object
  ik_player = new YT.Player('ik_player_iframe');
       
  console.log('Video API is loaded');
       
  //subscribe to events
  ik_player.addEventListener("onReady",       "onYouTubePlayerReady");
  ik_player.addEventListener("onStateChange", "onYouTubePlayerStateChange");
}

function onYouTubePlayerReady() {
  console.log('Video is ready to play');
}

function onYouTubePlayerStateChange(event) {
  console.log('Video state changed');
}

Coding the onStateChange Event Handler

The onStateChange event is a special case because it can (and does) fire several times. It passes an object to your event listener function that contains an integer constant that corresponds to the new player state. Values include:

  1. unstarted
  2. ended
  3. playing
  4. paused
  5. buffering
  6. video cued

(You read right; there is no 4!)

You'll always get the unstarted (-1) value first, when the player first loads a video. Once the video is cued and ready to play, the API will call your handler again with a video cued event number of 5. Rather than try to remember what event each number corresponds to, you can use one of the following special namespace-prefixed variables:

  • YT.PlayerState.UNSTARTED
  • YT.PlayerState.ENDED
  • YT.PlayerState.PLAYING
  • YT.PlayerState.PAUSED
  • YT.PlayerState.BUFFERING
  • YT.PlayerState.CUED

Here is a more fleshed-out version of our onPlayerStateChange() event handler using the constants to determine the new state:

function onPlayerStateChange(event) {
  switch (event.data) {
    case YT.PlayerState.UNSTARTED:
      console.log('unstarted');
      break;
    case YT.PlayerState.ENDED:
      console.log('ended');
      break;
    case YT.PlayerState.PLAYING:
      console.log('playing');
      break;
    case YT.PlayerState.PAUSED:
      console.log('paused');
      break;
    case YT.PlayerState.BUFFERING:
      console.log('buffering');
      break;
    case YT.PlayerState.CUED:
      console.log('video cued');
      break;
  }
}

Other Events

There are a few other events that you can listen for including:

  • onPlaybackQualityChange: This event fires whenever the video playback quality changes, i.e. going to fullscreen.
  • onPlaybackRateChange: Fires whenever the video playback rate changes.
  • onError: Fires if an error occurs in the player. The API passes an integer to the event listener function that identifies the type of error that occurred.
  • onApiChange: Indicates that the player has loaded or unloaded a module with exposed API methods. Your script can listen for this event and then poll the player to determine which options the recently loaded module exposes.

To gain a better understanding of when each of the above events fire, insert a DIV element with an ID of "ik_player" and paste the following code into a script at the bottom of the page.

//This code loads the IFrame Player API code asynchronously.
var tag = document.createElement('script');
tag.src = "https://www.youtube.com/iframe_api";
var firstScriptTag = document.getElementsByTagName('script')[0];
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);

// This function creates an iframe and YouTube player
// after the API code downloads.
var ik_player;
function onYouTubeIframeAPIReady() {
  player = new YT.Player('ik_player', {
    height: '390',
    width: '640',
    videoId: '5EnL2WXsxNQ',
    events: {
      'onReady': onPlayerReady,
      'onStateChange': onPlayerStateChange,
      'onPlaybackQualityChange': onPlayerPlaybackQualityChange,
      'onPlaybackRateChange': onPlayerPlaybackRateChange,
      'onError': onPlayerError,
      'onApiChange': onPlayerApiChange
    }
  });
}

// The API will call this function when the video player is ready.
function onPlayerReady(event) {
  console.log('player is ready');
}

// The API calls this function when the player's state changes.
function onPlayerStateChange(event) {
  switch (event.data) {
    case YT.PlayerState.UNSTARTED:
      console.log('unstarted');
      break;
    case YT.PlayerState.ENDED:
      console.log('ended');
      break;
    case YT.PlayerState.PLAYING:
      console.log('playing');
      break;
    case YT.PlayerState.PAUSED:
      console.log('paused');
      break;
    case YT.PlayerState.BUFFERING:
      console.log('buffering');
      break;
    case YT.PlayerState.CUED:
      console.log('video cued');
      break;
  }
}

function onPlayerPlaybackQualityChange(playbackQuality) {
 console.log('playback quality changed to ' + playbackQuality.data);
}

function onPlayerPlaybackRateChange(playbackRate) {
 console.log('playback rate changed to ' + playbackRate.data);
}

function onPlayerError(e) {
 console.log('An error occurred: ' + e.data);
}

function onPlayerApiChange() {
 console.log('The player API changed');
}

Each time an event fires, a console message will alert you.

Conclusion

Now that we know more about YouTube Video Player Events, the next step is to use them to trigger specific actions. We'll look at how to do that next time.



Rob Gravelle

Rob Gravelle resides in Ottawa, Canada, and is the founder of GravelleWebDesign.com. Rob has built systems for Intelligence-related organizations such as Canada Border Services, CSIS as well as for numerous commercial businesses.

In his spare time, Rob has become an accomplished guitar player, and has released several CDs. His band, Ivory Knight, was rated as one of Canada's top hard rock and metal groups by Brave Words magazine (issue #92) and reached the #1 spot in the National Heavy Metal charts on Reverb Nation.



Make a Comment

Loading Comments...

  • Web Development Newsletter Signup

    Invalid email
    You have successfuly registered to our newsletter.
  •  
  •  
  •  
Thanks for your registration, follow us on our social networks to keep up-to-date