Search code examples
javascriptyoutube-javascript-api

How to play multiple videos back to back in the same embedded player with the YouTube js API?


So far I have a YouTube player embedded, which I can control via the YouTube API, and I also get the callbacks properly and everything.

So whenever I call loadVideoById on my player object to load another video, while the current one is still playing, it works just fine. However, if I call it after a video has stopped, it doesn't do anything.

I have a pre-defined set of YouTube video IDs, that I wish to play one after another in the same embedded player. So what I want, is that once one video stopped, the API issues a callback, so I get notified about it, then I order the player to load another video and play it. Here's the relevant part of the code:

this.playNextVideo = function playNextVideo() {
    if (this.playlist.length > 0) {
        yt_embedded_player.loadVideoById(this.nextId(), 0);
        yt_embedded_player.playVideo();
    }
}

this.onPlayerStateChange = function onPlayerStateChange(_event) {
    if (_event.data == YT.PlayerState.ENDED) this.playNextVideo();
}
  • yt_embedded_player is my embedded player, as returned by the iFrame API
  • playlist is the array that contains the video IDs
  • nextId() is a function that supplies the video IDs one after another (from playlist)

Is there any method to load and play a video after the previous one reached the end?


Solution

  • So there were two problems actually. One is that when I specified the callback functions to the YouTube API like this:

    yt_embedded_player = new YT.Player(this.e_id, {
        height: this.player_h,
        width: this.player_w,
        videoId: /* default video id */,
        events: {
            'onReady': this.onPlayerReady.bind(this),
            'onStateChange': this.onPlayerStateChange.bind(this)
        }
    });
    

    I had to use .bind(this) (as you can see) to give meaning to the "this" context within those functions (this is kind of a dumb mistake, but I'm new to javascript, so excuse me for it).

    But even so, the argument that is passed to onPlayerStateChange was undefined for some reason. That would be that data that describes the current state of the player. So even though the callbacks were dispatched just fine when the player changed state, but the actual state was not passed properly to the function. So what I did is this:

    this.onPlayerStateChange = function(_event) {
        if (yt_embedded_player.getPlayerState() == YT.PlayerState.ENDED) {
            this.playNextVideo();
        }
    }
    

    Instead of relying on the argument, I manually fetch the player's state with the getPlayerState() call. This might not be the most optimal, but definitely works.