Question

I'm having problems enqueuing a playlist using the YouTube IFrame API. (https://developers.google.com/youtube/iframe_api_reference#Queueing_Functions)

I'm using flash to show the youtube videos. Using HTML5 shows another issue where the videoplayback call is called multiple times before the video loads.

On loading the playlist, the video itself doesn't load. It shows up in the network tab as a call to videoplayback that is 'pending' until it times out after 7.5 minutes at which point it tries again and everything works. The playlist, incidentally, has loaded successfully - mousing over the youtube iframe shows a loaded playlist.

The code to replicate this is below, and the issue is found following these steps: 1. Click a channel 2. If channel loads, goto 1, else check network tab.

I know the method of replication is contrived, however I'm seeing this 'sometimes' on first load.

The playing channel isn't at fault - this has been seen with many different channels.

Is it my code? Is there a work around? Is there a fix?

Tested on Windows 7 32bit using Chrome 28, Firefox 22.0 and IE 10

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
    <head>
        <meta content="text/html;charset=utf-8" http-equiv="Content-Type">
        <title>
            Youtube Test
        </title>
        <script src="//ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
        <script type='text/javascript'>
var collection = [];
var player = null;
var playlistEnqueued = false;

function clear() {
    // Removes the iframe.
    if (player !== null) {
        player.destroy();
    }

    collection = [];
    playlistEnqueued = false;
    player = null;
}

function createYT(videoId) {
    // Clear anything that's up currently
    clear();

    // Yes, this could be $.ajax, however this way reduces the dependency on jQuery
    // further for the purposes of this test.
    var xmlhttp = new XMLHttpRequest();
    xmlhttp.onreadystatechange = function() {
        if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
            parseJSONResponse(JSON.parse(xmlhttp.responseText));
        }
    }
    xmlhttp.open("GET", "https://gdata.youtube.com/feeds/users/" + videoId + "/uploads?alt=json", true);
    xmlhttp.send();
}

function parseJSONResponse(data) {
    var feed = data.feed;
    $.each(feed.entry, function(index, entry, list) {
        collection.push(entry.id.$t.match('[^/]*$')[0]);
    });
    playVideo();
}

function playVideo(videoId) {
    try {
        if (videoId === undefined || videoId === null) {
            videoId = collection[0];
        }
        if (typeof(YT) == 'undefined' || typeof(YT.Player) == 'undefined') {
            window.onYouTubeIframeAPIReady = function() {
                playVideo(videoId);
            };
            $.getScript('//www.youtube.com/iframe_api');
        } else {
            if (playlistEnqueued === true) {
                player.playVideoAt(0);
            } else {
                player = new YT.Player('video', {
                    events: {
                        'onReady':function(event) {
                            try {
                                player.cuePlaylist(collection);
                            } catch (e) {
                                console.error(e);
                            }
                        },
                        'onError':function(error) {
                            console.error(error);
                        }
                    },
                    videoId: videoId,
                    width: 425,
                    height: 356,
                    playerVars: {
                        autoplay: 1,
                    }
                });

                // Attaching event listener after object creation due to
                // http://stackoverflow.com/questions/17078094/youtube-iframe-player-api-onstatechange-not-firing
                player.addEventListener('onStateChange', function(state) {
                    try {
                        stateChanged(state);
                    } catch (e) {
                        console.error(e);
                    }
                });
            }
        }
    } catch (e) {
        console.error(e);
    }
}

function stateChanged(state) {
    // This state will be called on enqueueing a playlist
    if (state.data == 5) {
        playlistEnqueued = true;

        playVideo();
    }
}

$(document).on('ready', function() {
    var player = $(document).find("#player");

    $("a").on('click', function() {
        var channel = $(this).attr('data-channel');
        createYT(channel);
        return false;
    });
});

        </script>
    </head>
    <body>
        <div class='test'>
            <div id='video'>
            </div>
            <a href='#' data-channel='mit'>MIT</a>
            <a href='#' data-channel='tedtalksdirector'>TED</a>
            <a href='#' data-channel='minutephysics'>Minute Physics</a>
        </div>
    </body>
</html>

When using flash, and on waiting for the video connection to timeout and try again the following is seen in the network tab. As you can see it's 'pending', failed, and then tried again after 7.5 minutes.

Chrome network tab once the video starts playing: Chrome network tab on video playback

More images when I get past 10 reputation...

Was it helpful?

Solution

I've got this up and running on jsFiddle (http://jsfiddle.net/3Bm2V/5/) and it seems to be working ok. I did have to change the

$(document).on('ready', function () {

to

$(function() {

to get it to work in jsFiddle, so try the link above and see if it works for you now?

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top