Q:

Adding a video to a playlist using the Youtube Player IFrame API

I'm working on some kind of Youtube remote web application using the Youtube Player IFrame API and got stuck when I tried to use the built-in playlist system as the queue for the application.
Using the API, you are able to load a specific list of videos as a playlist with e.g.:
player.loadPlaylist({playlist: ['_9IBbMW2o_o']})`

But there is no function such as:
player.addVideoToPlaylist('_9IBbMW2o_o')

What I'm trying to do is adding a video without stopping or reloading the current playlist.
Is there a workaround or am I missing something?

A:

By getting a little creative, we can actually use loadPlaylist() without causing any interruption. The API provides events, one of which will reveal itself to be useful to our purpose: onStateChange.

onStateChange
This event fires whenever the player's state changes. The data property of the event object that the API passes to your event listener function will specify an integer that corresponds to the new player state. Possible values are:

-1 (unstarted)
0 (ended)
1 (playing)
2 (paused)
3 (buffering)
5 (video cued)

Some observation shows that the -1 event fires when a playlist transitions from one video to another. This is our opportunity. By updating the playlist only when a transition happen, there is no (well, a barely) noticeable interruption.
The idea is to maintain a separate playlist, that we can manipulate. It's a simple array of Youtube videos identifiers, in which we can push new data whenever we want.
Everytime a video transition happens, we check the length of our playlist against the length of the player's playlist. If they do no match, we update the player's playlist.
We also keep track of the index, within the player's playlist, of the last video played before the transition. When loading the new playlist, we provide previous index + 1, as to play the next video in the playlist rather than start from the beginning.
The reason we use previous index + 1 is because using the current index would return 0 if we updated while playing the last video, since the player would loop back to the first video.
I must point out this is designed purely for the case of appending new videos to the playlist. Editing the playlist in other ways would require more logic.
The working demo on JSFiddle.
HTML
<div id="player"></div>
<button id="button">queue 2 more videos</button>

CSS
div {
    width:300px;
    height:240px;
    background-color: yellow;
}

JavaScript
var player;
var playlist = ['b_XKnkQZkOM','dnNt78eGjSM'];
var previousIndex = 0;

$(window).load(function(){
    
    player = new YT.Player('player', {
        height: '240',
        width: '300',
        playerVars : {
            playlist: playlist.join(','),
        },
        events: {
            onStateChange: function(event) {  
        
                /*
                the video has changed
                seize the opportunity to update the playlist without interruption
                */
                if(event.data == -1 || event.data == 0) {
                    
                    // get current video index
                    var index = player.getPlaylistIndex();
                    
                    // update when playlists do not match
                    if(player.getPlaylist().length != playlist.length) {
                        
                        // update playlist and start playing at the proper index
                        player.loadPlaylist(playlist, previousIndex+1);
                    }
                    
                    /*
                    keep track of the last index we got
                    if videos are added while the last playlist item is playing,
                    the next index will be zero and skip the new videos
                    to make sure we play the proper video, we use "last index + 1"
                    */
                    previousIndex = index;
                }
            }
        }
    });
});

$(document).ready(function() {   
    $('#button').click(function(){
        playlist.push('ZVeaEl7nMWM');
        playlist.push('YRBwXHowb6I');
    });
});

Note that if you block youtube.com/api/stats (Adblock, etc), the event 0 is not fired at the end of a video.

