2012-09-26

JWPlayer: remembering position in video, to resume playback later

As part of my recent developments on my upload site Filetrip.net, which comes with interesting video playback capabilities, I've added the possibility for visitors who watch a video once and interrupt playback to return to the video later on and resume where they left off.

In short: you are watching a video, you suddenly or accidentally close the tab or visit another site. When you go back to the video page and start playing again, the video will resume where you left off.

I was wrong to assume that this was an upcoming feature for JwPlayer, seeing as one of the authors stated that they "don't support this explicitely". So I designed it myself with minimal coding. Note that this has been tested on JWPlayer 5 and above, but I cannot guarantee that it will always work in the future.

Here is how I am going to detail this tweak:
1. Introduction and requirements
2. Remembering the position
3. Setting the starting offset
4. Cookie data limitations

Introduction and requirements

Let me explain how I got this to work: the solution is really very simple.
First, I set a javascript timer that makes an API call to the player asking for the current position in the video. Then, I save that position in a cookie. Finally, when the visitor reloads the page, the backend (example: a PHP page) tells the player the starting offset. Note that this third step could be done in Javascript, client side, but it's really up to you.

If you have read and understood the above correctly, the requirements are:
- cookies, being able to store them somehow. I will provide a javascript function for setting cookies.
- JWPlayer 5 or above, with its javascript API

Remembering the position

Somewhere in your page, insert that bit of code:

<script type="text/javascript">
function setCookie(c_name,value,expiredays) {
var exdate=new Date();
exdate.setDate(exdate.getDate()+expiredays);
document.cookie=c_name+ "=" +escape(value)+ ((expiredays==null) ? "" : ";expires="+exdate.toUTCString());
}
</script>

This is a function that will allow you to store some data on the visitor's computer. We will be using it to remember the position in videos.

Now, below that function (before the </script> closing tag), insert the following lines of code:
jwplayer().onPlay(function() { setTimeout("rememberPosition()", 5000); });
jwplayer().onComplete(function() { setCookie("mv_{$pid}", 0,-1); });
function rememberPosition() {
  if (jwplayer().getState() == "IDLE") {
    setCookie("mv_{$pid}", 0,-1);
  } else {
    setCookie("mv_{$pid}", Math.round(jwplayer().getPosition()),7);
    setTimeout("rememberPosition()", 5000); 
  }
}

  • The first line tells the player to call the "rememberPosition" function five seconds after the playback starts.
  • The second line tells the player to remove the cookie when the video playback is complete.
  • The "rememberPosition" function saves the position in the cookie for 7 days, and calls itself again in five seconds. If the user stops the video somehow or the playback finishes without triggering the onComplete event, the cookie is removed all the same.
  • Note: regarding the jwplayer().getState() == "IDLE" part, the IDLE state means "video stopped" or "playback complete". But it is different from the PAUSED state: in fact it is important to remember the position when the visitor paused the video. However once the visitor finished watching the video, we can delete the cookie permanently.
Now, if you've noticed, the name of the cookie value is mv_{$id}. The {$id} part means you should insert the ID of your video, or something that uniquely identifies your video, so that when your visitor plays another video the playback doesn't resume at the offset saved from another completely different video. You can also change the frequency (here, 5000 miliseconds) and the number of days the cookie should exist, 7 days in my example.

Setting the starting offset

Now, we have to tell JWPlayer to start the playback where the visitor left off - that is, in the value stored in the visitor's cookie. I realize that this could easily be done in Javascript with a getCookie function (you can find that on the web) and call that when the page loads or something. For some reason it was easier for me to do it with PHP.

From within the player page, find the javascript declaration of your JWPlayer instance. Here is mine:
  jwplayer('container').setup({
    'flashplayer': '/js/player59.swf',
    'id': 'playerID',
    'width': '100%',
    'height': '100%',
    'file': '<?= $path ?>',
    'image': '<?= $path ?>.jpg',
    'controlbar': 'over',
    'start': '<?= intval($_COOKIE['mv_'.$id]) ?>',
    'skin': '/js/beelden.zip',
    'backcolor': '#000000',
    'screencolor': '#000000',
    'provider': 'http'
  });

Note the <?= ?> PHP tags to insert the file path, and more importantly the 'start' parameter, which will indicate the starting offset for the video. 

Cookie data limitations

If your visitors are going to be watching a lot of videos, you might want to avoid using cookies for remembering positions. Remember:
1) cookie data is sent in every request to your HTTP server, even images, CSS, javascript and all. So it does take a bit of bandwidth.
2) there is usually a server-defined limit on the size of cookies. Things get big... You might want to keep the expiration date for your cookies as low as possible so that it doesn't accumulate over time.
3) if the visitor's cookie gets too big, you might get one of those Error 400 - Bad Request on your web server.

I hope you enjoyed my little tweak, feel free to post your own contribution in the comments!

Search This Blog