This guide discusses and provides an overview on RTMP video streaming with the JW Player for Flash v5.
RTMP (Real Time Messaging Protocol) is a system for delivering on-demand and live media to Adobe Flash applications (like the JW Player). RTMP supports video in FLV and H.264 (MP4/MOV/F4V) formats and audio in MP3 and AAC (M4A) formats. RTMP offers several advantages over regular HTTP video downloads:
However, do note that RTMP has its disadvantages too. Especially since the introduction of HTTP Pseudostreaming (used by e.g. Youtube), RTMP is not the only option for efficient video delivery. Some drawbacks to be aware of:
The JW Player supports a wide array of features of the RTMP protocol, listed below.
In order to use RTMP, your webhoster or CDN needs to have a dedicated RTMP webserver installed. There are two major offerings, both supported by the JW Player:
RTMP servers are not solely used for one-to-many media streaming. They include support for such functionalities as video conferencing, document sharing and multiplayer games. Each of these functionalities is separately set up on the server in what is called an application. Every application has its own URL (typically a subfolder of the root). For example, these might be the path to both an on-demand streaming and live streaming application on your webserver:
rtmp://www.myserver.com/ondemand/
rtmp://www.myserver.com/live/
The JW Player solely supports the basic live, on-demand and dvr streaming applications. There's no support for such things as webcasting, videochat or screen sharing.
To play an RTMP stream in the player, both the streamer and file options must be set. The streamer is set to the server + path of your RTMP application. The file is set to the internal URL of video or audio file you want to stream. Here is an example embed code:
<div id='container'>The player will be placed here</div>
<script type="text/javascript">
var flashvars = {
file:'library/clip.mp4',
streamer:'rtmp://www.myserver.com/ondemand/'
};
swfobject.embedSWF('player.swf','container','480','270','9.0.115','false', flashvars,
{allowfullscreen:'true',allowscriptaccess:'always'},
{id:'jwplayer',name:'jwplayer'}
);
</script>
Note that the documentation of RTMP servers tell you to set the file option in players like this:
You do not have to do this with the JW Player, since the player takes care of stripping the extension and/or adding the prefix. If you do add the prefix yourself, the player will recognize it and not modify the URL.
Additionally, the player will leave querystring variables (e.g. for certain CDN security mechanisms) untouched. It basically ignores everything after the ? character. However, because of the way options are loaded into Flash, it is not possible to plainly use querystring delimiters (?, =, &) inside the file or streamer option. This issue can be circumvented by URL encoding these characters.
Note: Amazon Cloudfront's private streaming protocol is an example in which the MP4 URL should be URL Encoded, since the long security hash appended to the video URL can contain special characters.
RTMP streams can also be included in playlists, by leveraging the JWPlayer namespace. The streamer option should be set for every RTMP entry in a playlist. You don't have to set them in the embed code (just point the file option to your playlist).
Here's an example, an RSS feed with an RTMP video and audio clip:
<rss version="2.0" xmlns:jwplayer="http://developer.longtailvideo.com/">
<channel>
<title>Playlist with RTMP streams</title>
<item>
<title>Big Buck Bunny</title>
<description>Big Buck Bunny is a short animated film by the Blender Institute,
part of the Blender Foundation.</description>
<enclosure url="files/bbb.mp4" type="video/mp4" length="3192846" />
<jwplayer:streamer>rtmp://myserver.com/ondemand</jwplayer:streamer>
</item>
<item>
<title>Big Buck Bunny (podcast)</title>
<description>Big Buck Bunny is a short animated film by the Blender Institute,
part of the Blender Foundation.</description>
<enclosure url="files/bbb.mp3" type="audio/mp3" length="3192846" />
<jwplayer:streamer>rtmp://myserver.com/ondemand</jwplayer:streamer>
</item>
</channel>
</rss>
Instead of the enclosure element, you can also use the media:content or jwplayer:file element. You could even set the enclosure to a regular http download of the video ánd jwplayer:file to the RTMP stream. That way, this single feed is useful for both regular RSS readers and the JW Player. More info in XML Playlist Support.
Note: Do not forget the xmlns at the top of the feed. It is needed by the player (and any other feed reader you might use) to understand the jwplayer: elements.
A unique feature of RTMP is the ability to do live streaming, e.g. of presentations, concerts or sports events. Next to the player and an RTMP server, one then also needs a small tool to ingest (upload) the live video into the server. There's a bunch of such tools available, but the easiest to use is the (free) Flash Live Media Encoder. It is available for Windows and Mac.
A live stream can be embedded in the player using the same options as an on-demand stream. The only difference is that a live stream has no file extension. Example:
<div id='container'>The player will be placed here</div>
<script type="text/javascript">
var flashvars = {
file:'livepresentation',
streamer:'rtmp://www.myserver.com/live/'
};
swfobject.embedSWF('player.swf','container','480','270','9.0.115','false', flashvars,
{allowfullscreen:'true',allowscriptaccess:'always'},
{id:'jwplayer',name:'jwplayer'}
);
</script>
When streaming live streams using the Akamai, Edgecast or Limelight CDN, players cannot simply connect to the live stream. Instead, they have to subscribe to it, by sending an FC Subscribe call to the server.
This same functionality is used by Wowza Media Server, when setting up multiple servers in a liveedge / liverepeater configuration.
The JW Player includes support for FC Subscribe. Simply add the rtmp.subscribe=true option to your embed code to enable:
<div id='container'>The player will be placed here</div>
<script type="text/javascript">
var flashvars = {
file:'livepresentation',
streamer:'rtmp://www.myserver.com/live/',
'rtmp.subscribe':'true'
};
swfobject.embedSWF('player.swf','container','480','270','9.0.115','false', flashvars,
{allowfullscreen:'true',allowscriptaccess:'always'},
{id:'jwplayer',name:'jwplayer'}
);
</script>
Note: as of JW Player 5.6, this functionality also works in combination with dynamic streaming. The player automatically detects the stream levels and subscribes to each. Previous versions of JW Player 5 only support subscribing to a single stream.
Flash Media Server 3.5 introduced live DVR streaming - the ability to pause and seek in a live stream. A DVR stream acts like a regular on-demand stream, the only difference being that the *duration* of the stream keeps increasing (that is, when the stream is still recording).
Instead of starting from the beginning, the player will automatically jump to the *live* head of the DVR stream, so users can jump right into a live event. Subsequently, they are able to seek back to the beginning.
In order to enable DVR streaming you should:
Here is an example embed code, with the rtmp.dvr option set:
<div id='container'>The player will be placed here</div>
<script type="text/javascript">
var flashvars = {
file:'livepresentation',
streamer:'rtmp://www.myserver.com/live/',
'rtmp.dvr':'true',
};
swfobject.embedSWF('player.swf','container','480','270','9.0.115','false', flashvars,
{allowfullscreen:'true',allowscriptaccess:'always'},
{id:'jwplayer',name:'jwplayer'}
);
</script>
Like HTTP Pseudostreaming, RTMP Streaming includes the ability to dynamically optimize the video quality for each individual viewer. Adobe calls this mechanism dynamic streaming. This functionality is supported for FMS 3.5+ and Wowza 2.0+.
To use dynamic streaming, you need multiple copies of your MP4 or FLV video, each with a different quality (dimensions and bitrate). These multiple videos are loaded into the player using an mRSS playlist (see example right below), or SMIL file (see: loadbalancing). The player recognizes the various levels of your video and automatically selects the highest quality one that:
As a viewer continues to watch the video, the player re-examines its decision (and might switch) in response to certain events:
Framedrop is continously monitored. Spikes are ruled out by taking 5-second averages. Once a quality level results in too large a framedrop, it will be blacklisted (made unavailable) for 30 seconds. After 30 seconds, it will be made available again, since the framedrop might be a result of a very decoding-heavy section in the video or external forces (e.g. the user opening Microsoft Office).
Unlike with HTTP Pseudostreaming, a dynamic streaming switch is unobtrusive. There'll be no re-buffering or audible/visible hickup. It does take a few seconds for a switch to occur in response to a bandwidth change / player resize, since the server has to wait for a keyframe to do a smooth switch and the player always has a few seconds of the old stream in its buffer. To keep stream switches fast, make sure your videos are encoded with a small (2 to 4 seconds) keyframe interval.
As of version 5.6 of the JW Player, dynamic streaming works in combination with load balancing and in combination with the FCSubscribe functionality. In previous versions, combining these features may result in unreliable switching behaviour.
Example
Here is an example dynamic streaming playlist (only one item). It is similar to a regular RTMP Streaming playlist, with the exception of the multiple video elements per item. The mRSS extension is the only way to provide these multiple elements including bitrate and width attributes:
<rss version="2.0" xmlns:media="http://search.yahoo.com/mrss/"
xmlns:jwplayer="http://developer.longtailvideo.com/">
<channel>
<title>Playlist with RTMP Dynamic Streaming</title>
<item>
<title>Big Buck Bunny</title>
<description>Big Buck Bunny is a short animated film by the Blender Institute,
part of the Blender Foundation.</description>
<media:group>
<media:content bitrate="1800" url="videos/Qvxp3Jnv-486.mp4" width="1280" />
<media:content bitrate="1100" url="videos/Qvxp3Jnv-485.mp4" width="720"/>
<media:content bitrate="700" url="videos/Qvxp3Jnv-484.mp4" width="480" />
<media:content bitrate="400" url="videos/Qvxp3Jnv-483.mp4" width="320" />
</media:group>
<jwplayer:streamer>rtmp://www.myserver.com/ondemand/</jwplayer:streamer>
</item>
</channel>
</rss>
Some hints:
For high-volume publishers who maintain several RTMP servers, the player supports load-balancing by means of an intermediate XML file. This is used by e.g. the Highwinds and Streamzilla CDNs. Load balancing works like this:
Here's an example of such an XML file. It is in the SMIL format:
<smil>
<head>
<meta base="rtmp://server1234.mycdn.com/ondemand/" />
</head>
<body>
<video src="library/myVideo.mp4" />
</body>
</smil>
Here's an example embed code for enabling this functionality in the player. Note the provider=rtmp option is needed in addition to rtmp.loadbalance, since otherwise the player thinks the XML file is a playlist.
<div id='container'>The player will be placed here</div>
<script type="text/javascript">
var flashvars = {
file:'http://www.mycdn.com/videos/myVideo.mp4.xml',
provider:'rtmp',
'rtmp.loadbalance':'true'
};
swfobject.embedSWF('player.swf','container','480','270','9.0.115','false', flashvars,
{allowfullscreen:'true',allowscriptaccess:'always'},
{id:'jwplayer',name:'jwplayer'}
);
</script>
RTMP Load balancing in playlists works in a similar fashion: the provider=rtmp and rtmp.loadbalance=true options can be set for every entry in the playlist that uses loadbalancing. Here's an example with one item:
<rss version="2.0" xmlns:jwplayer="http://developer.longtailvideo.com/">
<channel>
<title>Playlist with RTMP loadbalancing</title>
<item>
<title>Big Buck Bunny (podcast)</title>
<description>Big Buck Bunny is a short animated film by the Blender Institute,
part of the Blender Foundation.</description>
<enclosure url="http://www.mycdn.com/videos/bbb.mp3.xml" type="text/xml" length="185" />
<jwplayer:provider>rtmp</jwplayer:provider>
<jwplayer:rtmp.loadbalance>true</jwplayer:rtmp.loadbalance>
</item>
</channel>
</rss>
See the playlist section above for more information on format and element support.
The dynamic streaming mechanism of FMS 3.5+ and Wowza 2.0+ can be used in combination with load balancing. Therefore, simply add the different levels of your video to the SMIL file. Here's an example again:
<smil>
<head>
<meta base="rtmp://server1234.mycdn.com/ondemand/" />
</head>
<body>
<switch>
<video src="videos/Qvxp3Jnv-486.mp4" system-bitrate="1800000" width="1280" />
<video src="videos/Qvxp3Jnv-485.mp4" system-bitrate="1100000" width="720"/>
<video src="videos/Qvxp3Jnv-484.mp4" system-bitrate="700000" width="480"/>
<video src="videos/Qvxp3Jnv-483.mp4" system-bitrate="400000" width="320"/>
</switch>
</body>
</smil>
A couple of hints:
A frequent issue with RTMP streaming is the protocol being blocked by corporate firewalls. RTMP uses the UDP transmission protocol over port 1935, whereas regular HTTP traffic uses the TCP protocol over port 80.
All current-day RTMP servers have a way to circumvent this issue, by tunnelling the RTMP data in HTTP packets, over TCP and port 80. Performance will degrade - especially the buffer times, which may double - but the video can be pushed through corporate firewalls.
The current player tries to automatically detect and circumvents firewall issues for RTMP streaming. Here's how it works:
This functionality is fully automated (the port is automatically set to 80 and rtmp/rtmpe to rtmpt/rtmpte in your streamer flashvar) and works for all flavors of RTMP streaming (on-demand, live, dvr and dynamic).
You can also disable tunneling by setting rtmp.tunneling=false.