RTMP streaming is obsolete as of end December 2020 but we keep it posted as a piece of history.
In this tutorial we embed RTMP streaming with HLS adaptive streaming fall-back using JW Player 7.9.3 This tutorial is a follow-up of RTMP with HLS adaptive streaming fall-back on AWS – Part 1 which explains the preparations to set up a video for both HLS adaptive streaming and RTMP streaming.
To recapitulate: I’ve set up my art site with HLS adaptive streaming in HTML5 mode. This works wonderfully on all browsers that support HTML5. But on browsers that do not support HLS adaptive streaming without Flash (like IExplorer), I’ve got a problem. So, I worked out this rather unusual combination of methods which works excellent.
Installing JW Player
It is possible that later versions of JW Player will discard support for Flash and since we use RTMP to support browsers that can’t play HLS in HTML5 mode, we need a version that supports RTMP, which are all versions from 7.0 to 7.9.3.
Get JW Player now if you haven’t already. Select the Premium license because this is required for HLS adaptive streaming. See https://www.miracletutorials.com/embed-hls-adaptive-streaming-video/ under section Placing Embedding using the standalone JW Player, method 2 for instructions to download and install the standalone version if you haven’t done this already. Don’t read further until JW Player is installed.
Embedding the video
With JW Player installed, we now need to link to the jwplayer.js script in the header of the page. That is to say, between the <head></head> tags. In the body is possible as well, but it’s not ideal. Never place it below the player embedding code. You only need to adapt the red parts:
<script type='text/javascript' src='folder-jwplayer/jwplayer.js'></script>
Replace folder-jwplayer with the folder you used to store JW Player. Although you can use a full URL, a relative URL will be easier to deal. Especially when you later on install an SSL certificate or change the domain name.
In order for the player to work, you also need to place the license key into the header below the jwplayer.js:
<script type='text/javascript' src='folder-jwplayer/jwplayer.js'></script> <script type='text/javascript'>jwplayer.key="YOUR_PREMIUM_LICENSE_KEY";</script>
Replace YOUR_PREMIUM_LICENSE_KEY with your own premium license key. If you don’t know how to get it, see https://www.miracletutorials.com/embed-hls-adaptive-streaming-video/ under section Placing Embedding using the standalone JW Player, method 2.
With this done, below you find the complete embedding code for HLS combined with RTMP.
For those of you well acquainted with JW Player and AWS, it is probably quite clear when you analyze it, although some of you may raise your eyebrows at some settings. I’ll explain all that, step by step.
For beginners, the code below must look quite complicated, but you actually only have to copy this and adapt the red parts:
<div id="video1">Loading the player...</div> <script type="text/javascript"> var playerInstance = jwplayer("video1");playerInstance.setup({ width:'100%', aspectratio:'16:9', stretching: 'uniform', playlist: [{ image: 'https://dxxxxxx.cloudfront.net/posterimage.jpg', title: '', sources: [ {file: 'rtmpe://sxxxxxxx.cloudfront.net/cfx/st/_definst_/mp4:myvideo.mp4'}, {file: 'https://dxxxxxxx.cloudfront.net/presentation/index.m3u8'} ] }] }) </script> </div>
To help you quickly on your way already, the first thing you need to adapt is the poster image:
image: 'https://dxxxxxx.cloudfront.net/posterimage.jpg',
This displays an image when the video player is loaded and ready to play. Otherwise, you would get a black square with a play button. Images can reside on any server you have access to, be it AWS or your own site. If you link to a poster image on AWS, you need to set up a crossdomain.xml file which will assure that your player gets access to the image. For now, it is probably easier to link to a poster image on your own site. But for completeness sake, here is how a crossdomain.xml looks like:
<?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="*.yourdomain.com"/>
</cross-domain-policy>
It needs to be placed in the bucket where the image resides and it must be public.
Next, we need to link to our RTMP straming video:
sources: [ {file: 'rtmpe://sxxxxxxx.cloudfront.net/cfx/st/_definst_/mp4:myvideo.mp4'},
The sxxxxxxx part is the Domain Name of the RTMP distribution which you can find in Services > CloudFront in the AWS console:
RTMP distributions always start with an ‘s’.
And you replace myvideo.mp4 with the name of your RTMP streaming video. If you placed it in a folder within the bucket, this would become myfolder/myvideo.mp4.
sources: [ {file: 'rtmpe://sxxxxxxx.cloudfront.net/cfx/st/_definst_/mp4:myfolder/yvideo.mp4'}, {file: 'https://dxxxxxxx.cloudfront.net/presentation/index.m3u8'} ]
Now we have to locate the domain name of the web distribution dxxxxxxx for the HLS master manifest m3u8. You will find it in the same way as for the RTMP distribution, the difference is that web distribution domain names always start with a ‘d’.
And presentation/index.m3u8 has to be replaced by the folder name and name of the master manifest you created previously (see https://www.miracletutorials.com/hls-adaptive-streaming-tutorial-with-cloudfront-jw-player/ if you haven’t set up a HLS adaptive streaming video yet).
Once this is adapted, you can copy the embedding code and place it in your page and test it. Be warned that some CMS strip javascript from the page editor. In that case, create a separate html page and call it in an iframe.
To demonstrate how this embedding code works, have a look at my test page: https://www.raboo.info/test/test-rtmp-fallback/ where I show one video with only HLS adaptive streaming and one with RTMP streaming with HLS adaptive streaming as fall-back. Test in various browsers with Flash enabled and disabled. If Flash is disabled on IExplorer, then play-back will fail. Nothing can be done about that, unless you would provide a third option, progressive download but just ot please IExplorer fans, that goes a bit too far for me. 🙂
Advanced break down of the embedding code
Let’s again consider the complete embedding code:
<div id="video1">Loading the player...</div> <script type="text/javascript"> var playerInstance = jwplayer("video1");playerInstance.setup({ width:'100%', aspectratio:'16:9', stretching: 'uniform', playlist: [{ image: 'https://df59gl8unq2ou.cloudfront.net/experiments/close-up-research/close-up-research.jpg', title: '', sources: [ {file: 'rtmpe://sxxxxxxx.cloudfront.net/cfx/st/_definst_/mp4:myvideo.mp4'}, {file: 'https://dxxxxxxx.cloudfront.net/presentation/index.m3u8'} ] }] }) </script> </div>
Now let’s discuss this line by line. For instance:
<div id="video1">Loading the player...</div>
video1 is an unique identifier for each player. Because it is possible to add more hen one player on a page, each player needs to have an unique ID.
And this ID needs to be repeated in this part:
<script type="text/javascript">
var playerInstance = jwplayer("video1");playerInstance.setup({
If a player doesn’t show up, it is often because you didn’t use the same ID.
width:'100%', aspectratio:'16:9',
width and aspectratio assure that the player is responsive. It is possible to set the width in pixels but it is seldom a good idea. The aspectratio is the relationship between width and height of the video. For HD, this is usually 16:9, for SD video 4:3
stretching: 'uniform',
stretching is best set to uniform as this guarantees that the video doesn’t deform.
fill is useful if you want to avoid black banding but it literally stretches the video. It is often better to adapt the aspectratio and use uniform There is also exactfit, but I never understood what the point is of that stretching option. It is seldom useful.
Now, why do I use the playlist method?
playlist: [{ image: 'https://df59gl8unq2ou.cloudfront.net/experiments/close-up-research/close-up-research.jpg', title: '', sources: [ {file: 'rtmpe://sxxxxxxx.cloudfront.net/cfx/st/_definst_/mp4:myvideo.mp4'}, {file: 'https://dxxxxxxx.cloudfront.net/presentation/index.m3u8'} ] }]
I could work directly with the sources attribute which makes the embedding code a bit smaller. With the playlist method, you can add multilingual subtitles and I have found that this is in general the most versatile method.
You may notice, that while I talk about RTMP, I use the protocol rtmpe:
sources: [ {file: 'rtmpe://sxxxxxxx.cloudfront.net/cfx/st/_definst_/mp4:myvideo.mp4'}, {file: 'https://dxxxxxxx.cloudfront.net/presentation/index.m3u8'} ]
This adds a layer of security because the stream is encrypted between the Flash server software and the player. Not that this will stop advanced users from intercepting the video if they really want to, but we shouldn’t make it too easy for them, right?
Why not set RTMP as the second source?
I have tested with rtmp set as the last option, like:
sources: [ {file: 'https://dxxxxxxx.cloudfront.net/presentation/index.m3u8'}, {file: 'rtmpe://sxxxxxxx.cloudfront.net/cfx/st/_definst_/mp4:myvideo.mp4'} ]
But that doesn’t work at all. It works fine when the first source is rtmp.
Why is this set up better then the standard methods?
Normally, with JW Player 7.8, primary is default set to html5., but we don’t need to set that attribute to flash because the player is intelligent enough to find out whether a Flash plugin is available or not and serves the media accordingly. You could ask, why didn’t I set HLS adaptive streaming for Flash and selected progressive download as HTML5 fall-back?
Because in order to be prepared for the near future, I decided for me that HTML5 is the default and Flash only the fall-up, so to speak. If later in time Flash and IExplorer 11 are dead, I only need to remove this line (in red):
sources: [
{file: 'rtmpe://sxxxxxxx.cloudfront.net/cfx/st/_definst_/mp4:myvideo.mp4'},
{file: 'https://dxxxxxxx.cloudfront.net/presentation/index.m3u8'}
]
This won’t break anything in my site, so even if I have hundreds of videos, I can adapt it at leisure, knowing that HLS adaptive streaming will keep working with the best possible option, namely adaptive bitrate.
And that concludes this tutorial. I hope it will be useful to you. If you have any questions, let me know in the comments box.