Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Youtube iframe javascript, track percentage of video watched?

I am trying to get an accurate calculation of how much time a user has spent watching a video. The time they spent watching it should not include skipping forward or when the video is paused. The code I have now is giving me a different percentage each time (I'm using an interval). I don't know how else to go about this?

function onPlayerStateChange(event) {
    if (event.data == YT.PlayerState.PLAYING && !done) {
      clicked_video = true; 
      arr.length = (player.getDuration()-1).toFixed(0);
      done = true;

    }if(event.data === YT.PlayerState.PLAYING){

       id = setInterval(check, 1000);

   }if(event.data == YT.PlayerState.PAUSED || event.data == YT.PlayerState.BUFFERING){

        clearInterval(id);
        var percent = 0;
        for(var i=0;i<arr.length;i++){
          if(arr[i] == "x"){
          percent++;
          console.log(percent);
          }

       }

    percent = (percent / arr.length) * 100;
    alert(percent + "%");
    }
}
function check(){

      arr[Math.floor(player.getCurrentTime())] = "x";
}
like image 649
dantheman Avatar asked Feb 26 '15 19:02

dantheman


3 Answers

Here is a demo, I think the variables and functions have names explicit enough to understand everything, but if you have any question or problem, go ahead and ask.

One thing I have to mention is that it won't be exact. If your interval gets executed once per second and the user skips a part in the middle of a second, that one might not be counted. To have a more accurate percentage, you can execute your interval more often (100ms here, I got 97% when watching the video back and forth), but be careful not to use too much resources.

var player, timer, timeSpent = [], display = document.getElementById('display');

function onYouTubeIframeAPIReady() {
    player = new YT.Player( 'player', {
        events: { 'onStateChange': onPlayerStateChange }
    });
}

function onPlayerStateChange(event) {
    if(event.data === 1) { // Started playing
        if(!timeSpent.length){
            timeSpent = new Array( parseInt(player.getDuration()) );
        }
        timer = setInterval(record,100);
    } else {
        clearInterval(timer);
    }
}

function record(){
    timeSpent[ parseInt(player.getCurrentTime()) ] = true;
    showPercentage();
}

function showPercentage(){
    var percent = 0;
    for(var i=0, l=timeSpent.length; i<l; i++){
        if(timeSpent[i]) percent++;
    }
    percent = Math.round(percent / timeSpent.length * 100);
    display.innerHTML = percent + "%";
}

JS Fiddle Demo

like image 64
blex Avatar answered Nov 11 '22 05:11

blex


Here's a way to get a frame-perfect precision of how much of the video the user has watched:

The recipe

  • Get a reference to the HTML5 video player
  • Grab the played property off the video object, which returns a TimeRanges object (see https://developer.mozilla.org/en-US/docs/Web/API/TimeRanges)
  • Iterate over the played object, and add up all the ranges

Example

/**
 *
 * @param {HTMLVideoElement} video
 * @returns {{total: number, percent: number}}
 */
function getPlayedTime(video) {
    var totalPlayed = 0;
    var played = video.played;

    for (var i = 0; i < played.length; i++) {
        totalPlayed += played.end(i) - played.start(i);
    }

    return {
        total: totalPlayed,
        percent: totalPlayed / video.duration * 100
    };
}

By calling the above helper function and passing it your video object, you'll get back an object with two properties: the total length (in seconds) that the user actually watched, and the percentage of the video's duration that this represents.

The cool thing about this approach is that it is 100% accurate. If the user watches the first 5 seconds of the video over and over, it'll still register that only 5 seconds were watched. The browser itself keeps track of this, so you don't need to set intervals, listen for events, etc.

like image 7
rodrigo-silveira Avatar answered Nov 11 '22 07:11

rodrigo-silveira


Youtube iframe player api provide a function to turn the current played time of the video player.getCurrentTime():Number. That can be used to track how much the user watched the video.

You can also make use of player.getDuration() api to get the total video time and calculate the percentage of the progress

here is the alternation of the exampled shared by first answer http://jsfiddle.net/ndbseftp/

like image 1
cubbuk Avatar answered Nov 11 '22 05:11

cubbuk