Thursday, 3 November 2011

secure streaming of media on your site

I am a web developer and was assigned the task of developing a section where logged in users could watch media uploaded on site, it also included a forum and a newsletter section. The media would be displayed on a page which would list 2 media files and their description at a time.

The page would show a thumbnail on one side and some description of the media on the right. For audio i would show a static thumbnail. Each media displayed on that page had a thumbnail as i said and a title for that media. Now my client also wanted that the media should open in lightbox and be played there.

Lightbox would open on click of the thumbnail or the title. All this was easy but client also requested that the users should not be able to download the media files. Now this took a lot of time, so i researched a lot on the web for an answer.

I used flowplayer at first, on the flowplayer they also included a link for secure streaming.
It involved installing a module on the server and some configuration in the code. Sometime later i changed my player to jwplayer which seemed simple and easy to configure and it also supported more formats and so i stuck with it.

There were 2 major steps to be done
1) install the mod on the server
2) configure the code

The module to be installed is called lighttpd. It was installed by the server guys and configured. 
The above link was given to the server guys and they configured it right 

What lighttpd mod basically does for this task is to create a hashed link like for e.g.

The server guys returned me this:
  $secret = "some secret code";
  $uri_prefix = "/";

  # filename
  # please note file name starts with "/"
  $f = "/folder for media files/" . $video;

  # current timestamp
  $t = time();

  $t_hex = sprintf("%08x", $t);
  $m = md5($secret.$f.$t_hex);

They also gave me a link format to follow, 
I program in php, so is the below code<?=$uri_prefix?><?=$m?>/<?=$t_hex?><?=$f?> 

So the jwplayer would be installed in the div in the following way

  var so = new SWFObject('../jwplayer/player.swf','ply<?=$subi?>','820','500','9');
  so.write('the id of the div to install the media into the player');

The way it was configured was that the hashed link would
1) be unique each time requested
2) could be used only once
3) expires or does timeout after a certain amount of time 30 secs after creation

The steps
1) Taking care of the timeout
- if this was not done, each time the page loads, the hashed links would not work and so the videos/audio would not play at all, as the hash had expired and server would not recognize it
- the 30 secs configured by the server guys start from the time the code to generate the link is run and not once the the page is completed loaded which is much later.
- so i had to generate a new hash after a certain amount of time which was much less than the 30 secs
- i ran an ajax code inside a timer function for that, i ran the code after 10 secs
setInterval("function to generate the new hashed url", 10000)
- the Ajax would create a new hash and changed the link to the media file
- so that took care of timeout of the hashed links

2) Only one use of the hashed link
- as mentioned above, the media would open in a lightbox on click of thumbnail or the title and the hashed link can be used only once
- so each time the thumb or the title was clicked the media would open in a lightbox on the first use and it was played
- after the lightbox was closed, i would have used up the link once so i would require a new link in case the user wants to view the video again
- so then i would run a Ajax similar to timeout Ajax and generate a new hashed link and replace link with the new hashed link to the media file each time the lightbox was closed for any media file on the page
- now if the user wants to view the audio/video again, he would be able to

3) Auto-refresh of the video when playing
- after 1 and 2 points are done, there was a problem that as the media was being played, after a certain amount of time, the lightbox would sort of refresh and start playing again
- this was because as i was playing the video, because of the timeout Ajax i was generating a new link and so the player would recognize this change and refresh the player with the new link
- to overcome this i would not run the timeout Ajax for the video that was playing
- this was done by detecting the click of the user on the thumb or the media title, once this was detected for a particular media i would not be generating a new link for that media

4) one last thing
- it is a must to put the media in a separate folder under your root folder, i say this as someone who reads the source could find the link and remove the hashed parts from the URL and paste the link and download the media
- inside the folder where the media files are present you would have to place a .htaccess file in it so that the media could not download by directly posting the link in the browser

For all i have written above, i would say that it is not possible to prevent the downloading of any media from any site, even YouTube cannot, a good download plugin can download them 
but the above procedure makes it a lot lot lot harder, hope you agree


  1. nice blog dude..................

  2. but the way gets more harder to download contents media..
    From Chile Country
    Juan Pablo

  3. This comment has been removed by the author.

  4. how about browser cachedata if our flv streaming data transport by pseudo streaming under http request
    I'm thinking about youtobe , they likely to tear up the streaming data by auto redirection ,so if you want to download a video for other purpose,you may only find out that there are more than single file that you want,but several files; anyway you can combine them ,it raised your costs