Detect when YouTube video ends using Youtube Player API not working properly

Viewed 482

I successfully load multiple Youtube videos using Youtube PlayerAPI and I tried to detect if one of the video ends and then i can do some action,for now i'm just throwing an alert. The code looks like this:

    // 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);

    // Creates an <iframe> (and YouTube player)
    //    after the API code downloads.
    var players = new Array();
    var playerInfoList = [{"video_id":"SMKPKGW083c","start_seconds":"130","end_seconds":"140","autoplay":"1","mute":"1"},{"video_id":"ianb7qAGd9I","start_seconds":"1","end_seconds":"5","autoplay":"0","mute":"0"}];

    function onYouTubeIframeAPIReady() {
        for (var i = 0; i < playerInfoList.length; i++) { 
            var curplayer = createPlayer(playerInfoList[i]);
            players[playerInfoList[i].video_id] = new Array();
            players[playerInfoList[i].video_id]['player'] = curplayer;
            players[playerInfoList[i].video_id]['data'] = playerInfoList[i];
        }
    }

    function createPlayer(playerInfo) {
        return  new YT.Player(playerInfo.video_id, {
            height: '100%',
            width: '100%', 
            videoId: playerInfo.video_id,
            host: window.location.protocol+'//www.youtube.com',
            playerVars: { autoplay: playerInfo.autoplay,mute: playerInfo.mute},
            events: {
                'onReady': onPlayerReady,
                'onStateChange': onPlayerStateChange
            }
        }); 
    }

    // 4. The API will call this function when the video player is ready.
    function onPlayerReady(event) {
        var videoId = event.target.getIframe().id;
        event.target.playVideo();
        if(players[videoId]['player']){
            var player = players[videoId]['player'];
            var data = players[videoId]['data'];
            player.loadVideoById({'videoId': videoId,
            'startSeconds': data.start_seconds,
            'endSeconds': data.end_seconds});
        }

    } 

    // when video ends
    function onPlayerStateChange(event) { 
        var videoId = event.target.getIframe().id;
        if(event.data == YT.PlayerState.ENDED) {
            alert('done') 
        }  else{ 

        }
        
    }

    function stopVideo() {
        player.stopVideo();
    } 

I set the start seconds and end seconds for the youtube player API, and when the end seconds reached it supposed to invoke the alert function. However most of the time the alert function does not show up , I tried to delete the browser's cookie and refresh the browser it works sometimes and then after a while it wont work again

Edit: i can constantly make the alert function works by going to incognito mode

1 Answers

It seems like the browser's cache or cookie is causes the event not triggered after the first or second time we the youtube video is played, but if we clear the browser cache and cookie it the event will be triggered again. My temporary solution for this issue is by using setInterval function to observe the youtube player state for every X seconds.

    function onPlayerReady(event) {
        var videoId = event.target.getIframe().id;
         if(players[videoId]['player']){ 
            var player = players[videoId]['player'];
            var data = players[videoId]['data'];
            player.loadVideoById({'videoId': videoId,
            'startSeconds': data.start_seconds,
            'endSeconds': data.end_seconds});
            //run every 0.2 seconds to check the youtube state
            setInterval(function() {
                if(videoId){
                    var id = "overlay-content-"+videoId;
                    if(player.getPlayerState() == YT.PlayerState.ENDED) {
                        document.getElementById(id).style.display = 'block';
                    }  else{
                        document.getElementById(id).style.display = 'none';
                        }
                }
            }, 200) 
        }
    }
Related