Wednesday, December 3, 2014

Streaming encrypted hls using Amazon cloudfront with signed urls


Most of the sites today will have one or more videos in their web pages. Streaming media content via web is very popular these days. This popularity increased the importance of content delivery networks(cdn) also. With the cdn like Amazon cloudfront, streaming videos have become easier as you can configure everything with a few clicks.

HLS is one of the commonly used streaming method nowadays. Amazon cloudfront supports hls streaming also.

Streaming a mp4 file :

1. create an amazon s3 bucket
2. store the video to be streamed in the bucket. ie the test.mp4 file.
3 create a cloudfront distribution. In the source, select the bucket created in the above step as origin bucket. You will get a domain name for your cloudfront distribution. something like
4. Put the url in your vlc and play the content. Make sure you have given global read permissions on you s3 object.
Thats it you are done.

As we discussed above, the hls streams also similarly played. The difference between a single .mp4 video and hls stream is that,
hls will have extension of .m3u8
hls will have a main manifest file and sub manifest files
hls will have .ts files for each sub manifest files.

So if it is a hls stream, in the url we will give the name as follows,

vlc player will check the main manifest file film_main.m3u8 and finds out that it has sub manifest files like film_sub_480.m3u8,film_sub_720.m3u8 and film_sub_1080.m3u8.

With the screen resolution and network bandwidth, vlc will chose one of the sub manifest file for playing and will request for the .ts chunks of the corresponding sub manifest files.

The problem with the above mentioned mp4 or hls streaming is that, if the url ends up with a third party, they will be able to download the content! and if you haven't used any drm technologies, you will be screwed.

Even if you have encrypted your content, how you can prevent people from downloading it? Thats where we use the signed url. Read this for How to serve the private content using amazon signed url.

So, when you enabled signing, before you request the url of mp4 video, you sign the url and requests it. It will play smoothly.

But what will happen in the case of hls or encrypted hls video? It will fail. But why?

Because we will sign and request the main manifest file of the hls stream. The player will get the main manifest file but inside the main manifest file there is no videos. It has just the information of the sub manifest files.

When the player request for the sub manifest files, the request will be rejected because the request is not signed. We wont be able to sign the request programmatically because the request will happen internally from the player.

What is the solution for this?

The solution is to create different cache behaviour for different types of files.
We will create different cache behaviour for .m3u8 and .ts  files.
.m3u8 files will be marked as private.
.ts files are stored as normal files.
So when we request the url, we are requesting .m3u8 files. Which needs to be signed. The calls to the .ts files will not need to be signed. They can be called internally through native media player.

The problem here is there are sub m3u8 files also. So if we create cache behaviour for m3u8 files native player will not be able to get the sub manifest files.

So we have to create cache behaviour only for "main.m3u8" requests. So other m3u8 files will be accessible to the native player.

You will have to do some edits in your distribution default settings. Please see the below notes:

Origin Settings

Restrict Bucket Access : If you want to require that users always access your Amazon S3 content using CloudFront URLs, not Amazon S3 URLs, click Yes. This is useful when you’re using signed URLs to restrict access to your content. In the Help, see “Serving Private Content through CloudFront.”      Give  Yes here.

Origin Access Identity : To require that users always access your Amazon S3 content using CloudFront URLs, you assign a special CloudFront user—an origin access identity—to your origin. You can either create a new origin access identity or reuse an existing one (Reusing an existing identity is recommended for the common use case). Additional configuration is required. In the Help, see “Serving Private Content through CloudFront.”   Select and existing origin identity. If you dont have any then create one.

Default Cache Behaviour Settings

Restrict Viewer Access : Choose whether you want CloudFront to require users to access your content using a signed URL. If you choose to restrict viewer access, users must use signed URLs to access your content. Additional configuration is required. In the Help, see “Serving Private Content through CloudFront.”      Select option No.

Create different cache behaviour for the patterns. If you want to enable signing for a particular pattern, then enabled it else disable it. After the configuration save the settings and test it. The video should play.

If you have any doubts on this please comment on this post or mail me. Thanks.

Best Reads:
1. Amazon Web Services For Dummies 
2. AWS System Administration: Best Practices for Sysadmins in the Amazon Cloud
3. Content Delivery Networks: Web Switching for Security, Availability, and Speed 
4. A Practical Guide to Content Delivery Networks, Second Edition  

No comments:

Post a Comment

Be nice. That's all.