Dong Hyun Koo Dong Hyun Koo - 1 month ago 12
Javascript Question

Youtube Iframe API loadVideoById() skips the video

Problem



I'm using Youtube Iframe API, And I need to use the API's startSeconds and endSeconds option of each video.

But here's the problem: the loadVideoById function skips the video.
In my example code, the first, third, fifth video is only played.

Here's the code. It's just simplified version of my application.

Source Code



<!DOCTYPE html>
<html>
<body>
<!-- 1. The <iframe> (and video player) will replace this <div> tag. -->
<div id="player"></div>

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

// 3. This function creates an <iframe> (and YouTube player)
// after the API code downloads.
var player;
function onYouTubeIframeAPIReady() {
player = new YT.Player('player', {
height: '390',
width: '640',
events: {
'onReady': onPlayerReady,
'onStateChange': onPlayerStateChange
}
});
}

var videos = [
{
vid: 'nbCqWMIT-Pk',
startSeconds: 10,
endSeconds: 15
},
{
vid: 'sAoJGNF_laA',
startSeconds: 10,
endSeconds: 15
},
{
vid: 'kF_23_XxaHQ',
startSeconds: 10,
endSeconds: 15
},
{
vid: 'zxYp3I0Gyrg',
startSeconds: 10,
endSeconds: 15
},
{
vid: 'U_gA99OQwO4',
startSeconds: 10,
endSeconds: 15
}
];
var index = 0;
// 4. The API will call this function when the video player is ready.
function onPlayerReady(event) {
event.target.cueVideoById({
videoId: videos[index].vid,
startSeconds: videos[index].startSeconds,
endSeconds: videos[index].endSeconds
});
event.target.playVideo();
}

function onPlayerStateChange(event) {
if (event.data === YT.PlayerState.ENDED) {
console.log(index);
if (index < videos.length - 1) {
index++;
event.target.loadVideoById({
videoId: videos[index].vid,
startSeconds: videos[index].startSeconds,
endSeconds: videos[index].endSeconds
});
}
}
}

</script>
</body>
</html>


Simple explanation for the source code



The videos array is assigned for test of my own. ( It's all Faker's highlights because I'm a big fan of him :) )

I made the player plays the videos in the list. If the player emits the "ENDED" event, then change the index and play the next video.

But when the time second and fourth video is to be played, This video isn't played. Only the ENDED event comes.

It seems like that the loaded video's endSeconds value isn't equal to video's total duration, It skips next video.

How can I solve this situation? Is it Youtube API's bug?

Answer Source

I found your problem it's in the function onPlayerStateChange() incrementation should be at the end (after loading your video ):

function onPlayerStateChange(event) {
        if (event.data === YT.PlayerState.ENDED) {
          console.log(index);
          if (index < videos.length - 1) {

            event.target.loadVideoById({
              videoId: videos[index].vid,
              startSeconds: videos[index].startSeconds,
              endSeconds: videos[index].endSeconds
            });
            index++;
        }
    }
}