Sunday, August 18, 2013

Multi bit rate video streaming with Cloudfront and Flow player


Sometime back I was trying to get multi-bit rate streaming working with Cloudfront, but could not find a working sample online. The reason why you need this is that all your users do not have the same bandwidth and even for those with high bandwidth the ACTUAL bandwidth might fluctuate as your packets have to travel over the internet which your ISP  does not control.

The way this works with Cloudfront is that you need to have the same video encoded at different bit rates present in your S3 bucket. Flowplayer (or any other player supporting multi bit rate), keeps switching between the different bit rate videos depending upon the ACTUAL bandwidth. The users would definitely feel the quality of video changing but that is better than showing the dreaded "Buffering" wheel :)

So first thing that you need is your video encoded at different bit rates. I used ffmpeg to do the same, but you are free to try something else.

 ffmpeg -i <input_file> -b <bit_rate> -r 30 -ab 384k -ar 44100 -s 624x256 -ac 2 -y sample_2200k.flv

bit_rate : This is the target bit rate, example : 2200k
output_file : This is the output file name, example : sample_2200k.flv

In this example lets create two files one with 200 kbps and one with 1000 kbps bit rate. Lets name them multi_bit_rate_200k.flv and multi_bit_rate_1000k.flv .

Now create a bucket (lets call it videostreamingakash) in S3 and put both the files there.

We now need to create a streaming distribution for serving these video. Go here for steps to create the same. While creating the distribution pick the bucket that we had created earlier as the origin.


Now we need to have an HTML file with the following content:

<html>
<body>
<div class="box black"><a
    href=""
    style="display:block;width:640px;height:360px;"
    id="player">
</a></body>
</html>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js" type="text/javascript" charset="utf-8"></script>
<script src="flowplayer-3.2.11.min.js"></script>
<script>
flowplayer("player", "http://releases.flowplayer.org/swf/flowplayer-3.2.16.swf", {
    clip: {

       urlResolvers: 'bwcheck',
       provider: 'rtmp',
       autoPlay: false,
       scaling: 'fit',

       // available bitrates and the corresponding files. We specify also the video width
       // here, so that the player does not use a too large file. It switches to a
       // file/stream with larger dimensions when going fullscreen if the available bandwidth permits.
       bitrates: [
         {
            url: "flv:multi_bit_rate_200k", width: 720, bitrate: 200,
            // this is the default bitrate, the playback kicks off with this and after that
            // Quality Of Service monitoring adjusts to the most appropriate bitrate
            isDefault: true
         },
         { url: "flv:multi_bit_rate_1000k", width: 720, bitrate: 1000 }
       ]
    },
    plugins: {

        // bandwidth check plugin
        bwcheck: {
            url: "flowplayer.bwcheck-3.2.12.swf",

            // CloudFront uses Adobe FMS servers
            serverType: 'fms',

            // we use dynamic switching, the appropriate bitrate is switched on the fly
            dynamic: true,

            netConnectionUrl: 'rtmp://s3ht5aoild7wia.cloudfront.net/cfx/st',

            // show the selected file in the content box. This is not used in real installations.
            onStreamSwitchBegin: function (newItem, currentItem) {alert("here");
               $f().getPlugin('content').setHtml("Will switch to: " + newItem.streamName +
                " from " + currentItem.streamName);
   $('#stream_data').text("Will switch to: " + newItem.streamName +
                " from " + currentItem.streamName);
            },
            onStreamSwitch: function (newItem) {
               $f().getPlugin('content').setHtml("Switched to: " + newItem.streamName);
               $('#stream_data').text("Switched to: " + newItem.streamName);
            }
        },

        // RTMP streaming plugin
        rtmp: {
            url: "http://releases.flowplayer.org/swf/flowplayer.rtmp-3.2.12.swf",
            netConnectionUrl: 'rtmp://s3ht5aoild7wia.cloudfront.net/cfx/st'        },

        // a content box so that we can see the selected video dimensions. This is not used in real
        // installations.
        content: {
            url: "http://releases.flowplayer.org/swf/flowplayer.content-3.2.8.swf",
            top: 0, left: 0, width: 250, height: 150,
            backgroundColor: 'transparent', backgroundGradient: 'none', border: 0,
            textDecoration: 'outline',
            style: {
                body: {
                    fontSize: 14,
                    fontFamily: 'Arial',
                    textAlign: 'center',
                    color: '#ffffff'
                }
            }
        }
    }
});
</script> 

Replace  netConnectionUrl with you STREAMING distribution. Also you need to download flowplayer-3.2.11.min.js from the flow player website to make the above work.

If you look at  the block:
  bitrates: [
         {
            url: "flv:multi_bit_rate_200k", width: 720, bitrate: 200,
            // this is the default bitrate, the playback kicks off with this and after that
            // Quality Of Service monitoring adjusts to the most appropriate bitrate
            isDefault: true
         },
         { url: "flv:multi_bit_rate_1000k", width: 720, bitrate: 1000 }
       
We have declared the two videos with their bitrates. Flowplayer uses this for switching the streams.

Just open the HTML in the browser of your choice and you are done :) .