Embed HLS adaptive streaming video 8.x

Updated 10 May 2017. HLS adaptive streaming requires various playlists (m3u8 manifests) to serve various bandwidth versions depending on the internet connection of the visitor. These manifests are created via the Elastic Transcoder service in the AWS console or via a video editor. for this reason, the manifests are static files, therefore, you can normally only create public video's as opposed to the other formats.
However, there is a small loophole we found: You can keep the bucket and the files private and only make the distribution public. In the distribution set up, you can force all links from the bucket to use the distribution link. That way the files remain safe in the bucket, although they are accessible via the web distribution.
Because HLS exists of video segments of 10 seconds each, illegally downloading them is quite a job, therefore the risk of stealing is somewhat diminished even if the web distribution is public.
Although HLS can be set up to play in Flash mode, it is best to serve it via HTML5 using CORS headers because Flash will be deprecated by most browsers quite soon.

Contrary to the other video formats, HLS is quite complicated to set up. For that reason we have created a HLS adaptive setup service to publish up to 10 videos for you. However, if you want to give it a go yourself, proceed with this tutorial.  If you run into trouble, support isn't far away. 🙂

Setting up CORS Headers

The fist thing you need to do is to follow this tutorial to set CORS headers in your bucket and web distribution in order to make the HLS segments HTML5 compatible.
When you have done that, come back here and proceed.

How to create manifests and video segments using Elastic transcoder

Although you can create video segments with a video editor, Elastic transcoder makes life easy for you by creating the segments and the relevant manifests in one go. It also goes exceptionally quickly.
So, we thought it would be worthwhile to explain how it works:

What you need to start with is to have 2 buckets:

  1. A private bucket that contains the master video you want to process.
  2. A private bucket for the output of the video in segments and manifests.

Creating the buckets

Whether you have already created buckets or not, it is best to have separate buckets for HLS adaptive streaming for organizational reasons as this media type requires quite a few files. So for those of you new to AWS, here is how you do this:

Go to the AWS console and select the S3 service:

AWS S3 Service

To make it easy to recognize buckets later on, best use a naming convention like this:

  1. mybucket-input (private) > used for master video's.
  2. mybucket-hls (public) > used for video segments and m3u8 manifests.

Creating buckets in S3 is easy. Once you are in the S3 service, click on Create bucket:

Create a bucket

Give a bucket name and select the Region closest to you:

Bucket region

Repeat this with the other bucket. 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.    You should have something like this now:

AWS bucket list

Upload the master video

We are going to upload a video now.  This should be a MP4, codec H264, AAC audio. It can be a 360 VR video as well. 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. We we are going to use Elastic Transcoder of AWS to convert that video in chunks of 10 seconds which will be placed in the other bucket.

Creating a M3u8 manifest and process the video

Elastic Transcoder is an online video and audio converter with many options. Although you can use your own video editor, Elastic transcoder is very fast and creates the m3u8 manifests for you.
What is involves:

  1. Create a Pipeline, which determines the input and output buckets and the Preset to use.
  2. 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):

Elastic Transcoder service

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.

The next step is not strictly necessary. But if you want Elastic Transcoder 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:

Add playlist

In the following part you get the following fields:

Create playlist

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:

Job details panel

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.  Since we have setup the bucket and web distribution with CORS headers, we don't have to rely on Flash, hence we don't need to create a crossdomain file.

We are ready now to embed the HLS adaptive streaming video.

Embed HLS adaptive streaming video

There are two ways to insert a progressive download video in your posts and pages.  Either use the wizard or write shortcode. We recommend to start with the wizard since it generates the shortcode automatically on the spot where your cursor is currently located. From there you can customize the shortcode if you like.

To start, go to the page or post where you want to place the progressive download video.
Click on the add S3Media Stream content button, located above the editor of your post or page:


Wizard interface

Click image to enlarge

This brings up the Wizard with a whole range of options.  (Click on the image at the left for a full overview of the options).
Every option has a handy hint reminder when you hover over the label of a field.

Depending on the media type, some fields may be grayed out as they have no use for that particular media type. If you have already set default options, you can use these and only fill in the fields which are needed for this instance.

For an HLS adaptive streamong video, you need to set the Media Type to Video. Locate this type in the dropdown list:

Shortcode: mediatype="video"

This will show at the top of the video area. Although optional, it is good for SEO.
Leave Title empty if you do not want this.

Shortcode: title="any value"

Media File

This is the index.m3u8 manifest file preceded by the folder name, like:


Fill in the name of the index manifest, preceded by the folder name, like myfolder/index.m3u8

Shortcode: file="myfolder/index.m3u8"

Web distribution
Fill in the web distribution (also called web distribution).This is generally constructed like this: https://yourcloudfrontdistribution.cloudfront.net
BUT we make it easy for you. Just fill in the red part, it consists of lowercase alpha characters and number and is unique for every streaming distribution.
You can find out the CloudFront distribution name in the AWS console under the CloudFront service. Open it in a new tab/window to switch easily between your admin section and the AWS console:


Since AWS often changes the interface, it may look a little different

When you click on the CloudFront link, you get a list of the distributions you made. If you haven't done already, check the Install & preparations tutorial.
In the list, select the Web distribution and copy only the distribution name and copy it:

Web (download) distributions always start with a 'd'. A common mistake is to fill in the streaming distribution which always stats with a 's'. This is how it should look more or less:

Web distribution setting

Note that in the screenshot above, you see (Default: dxxxxxxxx) next to the Web distribution field. This is because I have set a default value in the Default options. I could leave this field therefore empty, but it can be overridden as I did here.

Shortcode: html5="dxxxxxxxxx"
Note that this attribute is called HTML5, which relates to its previous function as a HTML5 fallback when Flash was predominant.

Source 2 and Source 3
Are two new fields which can be used as a fallback method for HLS and MPEG-DASH. Fill in the full path to the alternative video or audio, like https://dxxxxx.cloudfront.net/myfolder2/myvideo.mp4
For instance, if a device doesn't understand the primary media, the player will serve the second one.  If the second one doesn't work, the last one is tried, for instance, https://dxxxxx.cloudfront.net/myfolder2/myvideo.webm
Generally, you want to use another bucket with full private web distribution for those fallbacks.
Thus we get:

Shortcode: source2="https://dxxxxx.cloudfront.net/myfolder2/myvideo.mp4"
Shortcode: source3="https://dxxxxx.cloudfront.net/myfolder2/myvideo.webm"

Url expires(seconds)
Not strictly required if you only use the media file only,  although it will still play with an expiring URL.
When you se the source2 and source3 fields, this field is required!
URL expires(seconds) is expressed in seconds.
Thus: 10minutes = 600, 1 hour = 3600, a day = 86400, ...

Shortcode:  expires="700"

Encrypt paths
In general, it is a good idea to turn encrypting (which is more like obfuscation) on, especially for progressive download- and HLS videos. It serves two purposes:

  1. The URL is unreadable to human eyes (although easy to revert with a tool like Firebug)
  2. Some themes and plugins translate special characters in all URLs automatically to be in order with html validation tools.  If that happens, the expiring URL is invalid because JWplayer tries to load the media via the translated URL . Encryption prevents this from happening.

It is recommended to set this as a default option.  If you have problems with your video, turn it off on the particular video item when you ask support, so that we can read the source code to check where the problem is. You can override the default setting per item even after the shortcode is generated. Simply add secure="no" to the shortcode.

Shortcode: secure="yes/no"

Poster image
The extension presumes you uploaded the poster image to your domain. Only add the name of the image in this field, unless you placed it in a sub folder. If so, add the sub folder as well. You can override the domain setting by using an absolute path starting with http://... if the poster image is located somewhere else. In that case, you need to place a crossdomain.xml file in the folder where the poster image is located on the external domain or a bucket in AWS.
Example: myposterimage.jpg is the image and images is the sub folder, this becomes: images/myposterimage.jpg.


Images can be .PNG, .GIF or .JPG. Use .GIF or .PNG or flat colored graphics and desktop screenshots. Use JPG for photos or artwork with many gradients.

Be creative, a poster image can be anything you want it to be. With regular embedding from YouTube for instance, you only get frozen image from the video. It can be much more then that.

Automatically play the video when the page loads. Default set to No. Be careful, setting video or audio to Autoplay is generally regarded as user unfriendly. Only use this feature if you are sure your visitors expect this sort of behavior.

Since JWplayer version 6, the video player is responsive, meaning that it shrinks and enlarges depending on the screen of the user. This behavior works only with a responsive theme. The Width works in conjunction with the Aspect ratio field. As you can see from the screenshot above, the Height is grayed out, meaning not available for videos, only for audios.
In general, it is best to set the width to 100% unless your theme is not responsive. You may want to set this as a default option.


Then select the Aspect ratio. If it is a widescreen video, select 16:9, otherwise, select 4:3
If you have another format used sidewide, let us know and we will adapt the extension for you. This is free of charge. Otherwise, adapt the shortcode.

Shortcode: aspectratio="16:9/4:3/other"

Video stretching is set default to Uniform. This gives the best result.  But if you need it, you can set it to Fill if the video does not fill the video area completely. The video will then stretch to fit exactly into the video player. None is a rather useless option but we added it for completeness.

Shortcode: stretching="uniform/fill/none"

Standard set to Show. Contrary to JWplayer 5.10, the controlbar can not be made sticky to the video player.  It behaves in the same way as on YouTube now. If set to Show, the controlbar shows when the user moves his mouse over the video area. It will disappear after a few seconds.
It is possible to hide the controlbar permanently.  This may be useful if Autostart is set to yes but generally, this is not a good idea because other features, like the CC button will remain hidden as well.

Shortcode: controlbar="yes/no"

Repeat media
Standard set to None. If working with a single video, you can set it to repeat indefinitely by selecting Repeat forever.  Please note: With an external playlist, it will play all videos in the list in the order you placed the video, just once if set to Repeat forever. Standard this is set to None (recommended in most cases).

Shortcode: repeat="yes/no"

Select skin
Standard set to default skin. S3Media Stream Enterprise comes with 12 version 7 skins whch are not fully compatible with version 8.  You may want to adapt those or create your own and place them into wp-content/plugins/s3mediastream-video/assets/skins
The plugin will automatically list your new skin

Shortcode: skin="hector_video" (whereas hector_video is one of the possible skins).

The player accepts .vtt and .srt timedtext files. Since multilingual subtitles are now possible with JWplayer 6, this has advantages and disadvantages:

  • The advantage is that you can serve various languages in one go and when you place them in the same folder, the plugin will pîck them all up and display them via the CC button:
  • The disadvantage is that you need to create a folder for each video on your domain whereas in the past, you could simply link to a single subtitle file from anywhere.

In short, the subtitles need to organized within a main folder like for example "subtitles" and then for each video, you create a subfolder so that only the relevant subtitle files are listed for a particular item.
Therefore, if you have a folder subtitles in the root of your domain and the subfolder which contains the subtitles for this particular video is called video1, then you fill in the Captions/subtitles field like this: subtitles/video1

The plugin adds the domain name automatically for you.


Enforce background is standard set no No. Sets a dark background behind the subtitles in case the text is difficult to read. Captions behavior determines whether the subtitles show up automatically or should be triggered by the user via the CC button in the controlbar.
Subtitles shows the subtitles automatically whereas Closed captions needs action from the user. Note that Closed caption files are meant for the hearing impaired. They require that you also add an equivalent in text format for background noises.

If Captions/subtitles is not filled in, the two other settings are ignored.

Note: Upload these files with an FTP application because WordPress regards this type of files as suspicious.
View the tutorial How to create captions/subtitles for video and audio in WebVTT, SRT, DFXP format

Shortcode captions="folder" capback="yes/no" capstate="yes/no"

Standard set to No. Sharing places an icon in the video area to share the page to the video via social media. It is not available when you have no valid JWplayer license.

Sharing video

When the visitor clicks on the share icon, he gets the option to share the page, it does not link to the video directly, so there is no problem with expiring links:

The optional field Heading.This field is useful if you want to translate the standard heading "Share video" into another language or customize that text. In the example above, we filled in "Share audio" since the screenshot comes from an audio. Leave empty if you want to use the default.

Shortcode: sharing="yes/no " shareheading="Whatever you like"

Logo/watermark (Pro/Premium license only)
watermark-example2Usually a logo in .GIF or .PNG format. You are not restricted to logos. This can be any sort of image, but keep in mind that if you want it to show up semi-transparant, you need to use css, either in your custom skin or the theme css of your site.

The extension presumes you uploaded the watermark on this domain. Only add the name of the watermark in this field, unless you placed it in a sub folder. If so, add the sub folder as well.
Example: myWatermark.png is the image and tutorials is the sub folder, this becomes: tutorials/myWatermark.png. .PNG and SVG tends to give the best results. You can override the domain setting by using an absolute path starting with https://... if the watermark is located somewhere else. In this case, you need to place a crossdomain.xml file where the watermark is located.
You can also use the watermark to discourage screen capturing, if your server supports it:
Prevent screen capturing. Tests with subdomains on our server failed and we couldn't find the reason for this yet.

Watermark position
streaming-video10This is either Top-left, Top-right, Bottom-left(default) and Bottom-right. Bottom-right is often the place to expect a watermark, but it is often taken already by YouTube, for instance. In my experience, it is best set at Top-left or Top-right.

Logo link
An absolute path to any page you like, being it local, external or even een anker. Examples: https://www.wp21century.com, #top (an anker which would go to the top of the page where the module is placed), a page: http://yourdomain.com/my-sales-page. The last example could be used in video tutorials to send the visitor to a sale page to buy a related product. We are sure you can find good use for this.
If the Logo link is not filled in, the watermark feature is ignored.

Shortcode: logo="watermark.png" logopos="top-left/top-right/bottom-left/bottom-right" logolink="http://...."

Inserting the code

If you are ready, click the Insert code button. Save the page or post as a draft and test the Preview.
Does it work as you expected? Congratulations! If you place a lot of videos in the same bucket, you can copy the shortcode from your page/post, change the name of the video, while leaving the rest as is and put it into another post/page.  That way you can work even quicker.


If you have problems, check that the shortcode does not contain formatting code or has an active link. Sometimes, an absolute URL turns into a link. Unlink it, otherwise it will not work.
Be sure you filled in the correct JW Player license key in the settings of the plugin or it won't work.
Still problems? Check out the FAQ first.  If that does not help you, contact us here. Please let us know which software version you use, the WordPress version and a description of the problem. Providing a published page/post with the video would be a good idea as well.

On some WordPress configurations, the wizard doesn't show up. In that case, refer to the Shortcode list or ask us to prepare a sample shortcode for you.

Your feedback on this manual is always welcome!

Leave a Reply

Your email address will not be published. Required fields are marked *

Updated: December 15, 2017