A step-by-step HLS adaptive streaming tutorial with CloudFront & JW Player in two parts. It is easier than you think. This tutorial presumes you have already an Amazon Web Services account (AWS) and a premium license of JW Player 6 or 7.
The advantage of HLS adaptive streaming is that you can serve videos according to the bandwidth and screen resolution of the visitor to provide a smooth playback experience. View our example.
For HLS adaptive streaming, you use a M3U8 manifest file which contains so-called variant playlists, JW Player automatically starts playing the highest quality stream that fits the bandwidth and the screen size. It automatically adjusts the stream if the bandwidth increases or decreases during playback.
The manifests are created for you in the AWS console, you just have to follow a certain procedure.
HLS involves a bit of work, but once you have setup the presets in AWS, the next video setup is much easier. Let’s jump into it right now.
Creating your buckets
What you need to start with is to create 3 buckets:
- A bucket that contains the video you want to process.
- A bucket for the output of the video in segments
- Optional, a bucket for preview images.
Go to the AWS console and select the S3 service:
To make it easy to recognize buckets later on, best use a naming convention like this:
Creating buckets in S3 is easy. Once you are in the S3 service, click on Create bucket:
Give a bucket name. Note that special characters are prohibited in buckets names and they have to be unique across the AWS network. If a name is already taken, change it. Then, select the Region closest to you:
Repeat this with the other two buckets. For this tutorial we work with public videos, but we leave the buckets themselves private, so that no one can read what is in them. It is not a huge safety measure, but it helps prevent automated scripts from listing objects. You should have something like this now:
Uploading a video
We are going to upload a video now. This should be a MP4, codec H264, AAC audio. Best use a video with minimal compression, because once we start processing the video for HLS streaming, more compression will be applied and this seldom gives good results.
Select the mybucket-input bucket in that list. Your bucket has of course another name, but to keep it simple, we refer to the naming convention outlined above.
Since this is a new bucket, no files are to be found yet:
Click the Upload button and locate your video. Just follow the instructions in the upload panel, it is easy. Depending on the weight (MB’s), this may take a while:
Don’t navigate away from the page until it is done, although you can do other stuff on your computer in the meanwhile.
Once the video is uploaded, it is automatically listed on the left. This video does not need to be public, because we are going to use Elastic Transcoder of AWS to convert the video in chunks of 10 seconds.
Creating a M3u8 manifest and process the video
Elastic Transcoder is an online video and audio converter with many options. We use it to do the following:
- Create a Pipeline, which determines the input and output buckets and the Preset to use.
- Create a Job, to break up the video in segments and create the m3u8 manifest in one go.
If that sounds like Chinese to you, don’t worry, all will be explained.
Creating a Pipeline
Select the Elastic Transcoder service (you don’t need to sign up for this):
On the left, you see links to the Pipeline, Jobs and Presets:
Possibly, you have already Pipelines setup, which are listed on the right. But for HLS Streaming, we need to setup a new one. Click the Create New Pipeline button.
In the following screen, fill in the details as described below:
Pipeline Name: Give this a convenient name to remember.
Input Bucket: When you click in the field, you get a dropdown with buckets. Select the input bucket which contains your video.
IAM Role: Leave as is. If you don’t have one already, it will be created for you.
Bucket: is where the converted segments of the video and the m3u8 manifests are placed. In our example mybucket-hls.
Storage class: Standard. Other options are not useful in this case.
Click the +Add Permission link, to make the files public in the output bucket, so that the manifests have access to them:
Grantee Type: Select Amazon S3 Group
Grantee: All Users
Access: Only select Open/Download, nothing else.
The next step is not strictly necessary. But if you want Elastic Trascoder to create a thumbnail for you to use as a poster image (the preview image in the player), then scroll down to designate the bucket for poster images:
This follows the same rules as previously described, except that you select the mybucket-thumbs bucket.
To be honest, it is often better to create a poster image by hand and upload it to any bucket you like (as long as the image itself is made public). But the method above may speed up things for you.
Scroll down and on the bottom right, click on the blue Create Pipeline button.
The next thing we have to do is create a Job.
Create a Job
This is where everything is going to happen. With a Job, you create the video segments and the m3u8 manifests.
Click on the link Job on the left and click on the Create Job button:
In the following panel, fill in the first group of details:
Pipeline: Slect the one you just created.
Input Key: Select the video by clicking in that field to open the dropdown box with existing videos in the mybucket-input bucket.
Output Key Prefix: This is used to organize the video segments and manifests in its own folder. Note the slash at the end.
Scroll down to Output Details:
Preset: The system HLS presets are fine. Select first System preset: HLS 400k.
Segment duration: Apple recommends segments of 10 seconds. You can change that if you like, but this is the ideal length.
Output Key: Give a prefix for each segment. Since you chose the 400 kbs bitrate preset, indicate it more or less as shown.
Segment Filename Preview: is a preview of the segment names influenced by the previous field.
Create Thumbnails: Leave it to No, this resolution is not good enough to create a poster image.
Ouput Rotation: Auto.
Now, we setup a preset for 600kbs, 1MBs, 2MBs, 4MBs. Scroll a little down until you see the +Add Another Output link:
A new group of Output Details shows up. Repeat the same as previously, but this time select System Preset HLS 600k, Segmentation: 10, Output Key: something similar like hls_600k.
Add another one and select System Preset HLS 1M, after that create the last one with System Preset HLS 2M.
With this done, we create 4 formats in one go, respectively 400k, 600k, 1MB and 2MB bitrate segments, all neatly named according to the Output key prefixes. But we are not done yet with this Job. We have to create the manifests as well.
Scroll down to where you see a button Add Playlist:
In the following part you get the following fields:
Master Playlist Name: Usually we call this index since it is the master manifest which will call the others.
Playlist Format: Select HLSv3
Outputs in Master Playlist: Select first the 400k version.
Now click the + sign next to that field to add the following Output:
This time, select hls_600k, then repeat this until all 4 formats are included. This will create separate manifests for each bitrate version.
Then scroll down until you see the blue Create Job button. Click on it.
Elastic Transcoder now processes everything for you. It shows a status of the job and all the details involved:
With the example video I used, which is 7 minutes in length, it took about 5 minutes. You can refresh the screen from time to time to see if it is finished yet. If the status is Complete, the job is done.
You can check the bucket, to see everything is there. Go to the S3 service and select the bucket which should contain the video segments, in this example mybucket-hls. You will notice that there is a folder with the name you designated in the Output Key Prefix. Click on the folder to open it.
There should be a a whole range of .ts files and .m3u8 manifests. The one we will need is the index. m3u8 manifest to load into the player. But before we can do that, we have to create a crossdomain.xml file, so that we can give the Flash player permission to access the files. This is important because we will call video segments that are located on another server within our website which is hosted elsewhere.
Create and upload a crossdomain.xml
A crossdomain file indicates the domain(s) you want to give permission to access the content, in your case, this is your website domain. The file looks like this:
<?xml version="1.0"?> <!DOCTYPE cross-domain-policy SYSTEM "http://www.adobe.com/xml/dtds/cross-domain-policy.dtd"> <cross-domain-policy> <site-control permitted-cross-domain-policies="all"/> <allow-access-from domain="*.miracletutorials.com"/> </cross-domain-policy>
Where *.miracletutorials.com is the domain we will use to test the HLS adaptive streaming video. You will replace this with your own domain. Copy the example above and open a non-formatting text editor (Notepad.exe for PC, SimpleText for Mac).
Paste the code into the file. Then change the domain name. the *. part guarantees access to all eventual subdomains you may want to use.
When done, safe it as crossdomain.xml (case sensitive).
Go to your bucket in the AWS. Then, click the Upload button. Locate the crossdomain.xml file and upload it there.
When uploaded, click that file in the left hand list because we have to make it public, otherwise, it won’t work.
Click the Properties button on the top right:
2. Click on the Permissions link:
This shows the existing permissions. In this example, we see the owner of the account who has all the rights.
We add now a public grantee.
3. Create a new Grantee by clicking Add more permissions link and select Everyone:
Also make sure you only tick the List checkbox, nothing else.
When done, Save.
Now open the folder which contains the video segments (in our example presentations) in the bucket and repeat this process, because we also need the crossdomain.xml file there. In theory, a crossdomain.xml in the root of the bucket should suffice, but occasionally, we had problems when we did not place a crossdomain.xml in folders we wanted to embed videos from, so it cuts out frustration upfront when you follow this strategy.
When done, we have everything in place and we can finally display the video on the site.
View the Embedding an HLS adaptive streaming tutorial to proceed.