How to do Dynamic Streaming with Flash Media Server
With Adobe's release of Flash Player 10, Flash supports dynamic streaming. Along with the similar technologies known as adaptive streaming, Smooth Streaming, or bitrate switching, dynamic streaming selects the media stream that best suits a user's connection speed. If you're delivering from a streaming server that supports it, such as Adobe Flash Media Server 3.5, the stream will seamlessly switch during playback if network conditions change.
This tutorial will explain some of the mechanics and limitations of dynamic streaming, and offer a few concrete examples of how to set it up with a couple of popular Flash video players. Dynamic streaming is easy to do, but there are some details to know that will help make your efforts more successful.
The Player Calls the Shots
Dynamic streaming is controlled by the Flash player. Different video players built with Flash will have different implementation details, but there are a few common things you'll always have to do:
- Make multiple files: You'll encode multiple versions of the same video at different bitrates. The player will select the best one according to a user's available bandwidth and CPU load (inferred by counting dropped frames) during playback.
- Give the player a list of the files: The player will need to have a list of the versions that are available, and the bitrates of each. This list will look different depending on which player you're using.
When the player loads, it will detect the user's bandwidth & the screen size and choose the appropriate version of the file. The player will continue to measure bandwidth and dropped frames continually during playback, and will react to screen size changes (such as a user going to full-screen viewing). If you're streaming the video using the RTMP protocol, the player can request a bitrate switch from the server at any time.
The Server Answers the Call
When the server gets the request for a bitrate change, it will try to switch smoothly by locating matching keyframes in the encoded files, then switching on a common frame. This has implications for your encoding: If the keyframes are too far apart, or the files' timelines don't match up, you may not get a smooth switch.
Encoding Multiple Files
To prepare for dynamic streaming, you'll encode your video at several different bitrates. Typically, if you want to support users across all kinds of connections, you'll encode at a variety of bitrates that span the capabilities of your viewers. Which bitrates you select will depend on your audience and the kind of video content you're working with. Adobe's recommendations provide some suggested guidelines. For this example, I encoded at six bitrates.
I created all of the files in Sorenson Squeeze, using constant bitrate encoding (CBR) and setting a keyframe interval of 2 seconds (every 60 frames@30fps or every 30 frames@15fps). Table 1 shows the encoding settings for each file.
Table 1. Encoding settings for Sorenson Squeeze to create files for dynamic streaming.
Testing Methodology
I tested three Flash video players, and streamed video from Amazon Cloudfront/FMS 3.5 (for more on Cloudfront, see How to Get Started with Amazon Cloudfront Streaming). My reference player was the 1080p player found at Jens Loeffler's Flashstreamworks.com. I also tested and provide examples of the JW FLV Player 5.1 from Longtail Video, and Flowplayer 3.1.5.
I set up each player with the streams described above. Then I used bandwidth-limiting tools to simulate fluctuating network conditions while streams played.
I tested a variety of combinations of bandwidth constraints, bufferlength settings, and video encodings, with both H.264 and VP6 video. What turned out to be most revealing were two basic tests performed at various bandwidth restrictions (150Kbps, 300Kbps, 600Kbps, 1200Kbps):
- Starting with full bandwidth, and then throttling back to a lower bandwidth after 10 seconds of play
- Starting at the lower bandwidth, and removing the restriction after 10 seconds of play.
Some Guidelines
None of the three players handled dynamic streaming exactly the same. One thing that proved true is that the implementation in the 1080p player is simply outstanding. It was able to detect a variety of network manipulations and smoothly switch streams almost all of the time. This shows that the basic technology behind dynamic streaming works very well. The other players-JW Player 5.1 and Flowplayer 3.1.5-support dynamic streaming, but were not as adept at handling all of the same tests that the 1080p reference player handled with ease. Since the source code to 1080p is freely available, I expect we'll see improvement in future versions of the other players.
The three most crucial success factors turned out to be:
- the keyframe interval of your encodings,
- the bufferlength configuration of your player, and
- the bitrate spacing and quantity of your media files.
Keyframe Interval: When the server gets a request to switch to a different stream, it will try to make a smooth switch by lining up keyframes in the two files. If your keyframes are too far apart, the server can force a switch, but it won't necessarily be a graceful one. The best bet is to set a fixed keyframe interval which is the same for all streams to guarantee that there are enough keyframes to facilitate stream switching.
Bufferlength: If you have control over bufferlength, you might think that a bigger buffer is always better. Unfortunately, it's more complicated than that. In practice, I found that setting a larger buffer actually made the player more sluggish to sense a change in network conditions. In testing the JW FLV Player in particular, the ideal bufferlength seems to be about 2x the keyframe interval.
Selection of available bitrates: The most successful tests I conducted include a number of streams with fairly close-together bitrates. When network conditions fluctuated, a stream switch that involved a large jump in bitrate or screen size was distracting. Stream switches between more similar bitrates were often barely noticeable and provided a more pleasant user experience.
JW FLV Player 5.1
The JW FLV Player supports dynamic streaming on Flash player 10.x, and supports a less dynamic version of bitrate switching for Flash 9.x, or for when using a server that does not support switching during playback.
- For HTTP progressive download, the player will select the best stream at startup.
- For HTTP streaming or RTMP streaming from FMS 3.0 (or another RTMP server that does not support dynamic streaming), the player will select and switch streams upon startup, seek, or resize actions.
- For RTMP streaming from FMS 3.5, the player will evaluate the available bandwidth continually during playback and call for a switch if necessary.
More details on this can be found in Longtail Video's bitrate switching documentation.
To activate dynamic streaming in JW FLV Player, you simply provide a list of available media files in an RSS playlist. Here's an example:
It's necessary to use both bitrate and width in the playlist entries. The player will use the width values to change streams when a user switches to full-screen viewing, provided that bandwidth is available.
A working example running in JW Player 5.1 can be found on the Flash Dynamic Streaming Sample page.
FlowPlayer
FlowPlayer 3.1.5 supports dynamic streaming over rtmp, as well as simple stream switching for Flash 9.x, or for when using a server that does not support switching during playback. To do dynamic streaming with Flowplayer, you'll need its RTMP and bwcheck plugins.
Flowplayer uses a Javascript library to generate the code for the Flash player. The player configuration is set up in JSON format, and passed into the player in its constructor. A working example and the complete code listing is on the the Flash Dynamic Streaming Sample page, but we'll walk through a few key excerpts here.
To embed Flowplayer, place an <a> element in your HTML where you want the video to appear. This element will be replaced by the player upon initialization. The HREF attribute should be the base filename you've used for your different bitrate versions, plus the filename extension. In the case of mp4 files, you'll need to add an ‘mp4:' prefix to the filename. So, for my files named like Spinoffs_2_Water_500Kbps.mp4 and Spinoffs_2_Water_800Kbps.mp4, the <a> tag looks like this:
The rtmp plugin takes two configuration parameters: the path to the plugin itself, and the flash streaming path on the FMS server.
The bwcheck plugin is where most of the work gets done.
- url: the path to the plugin itself
- serverType: valid values are 'http', 'red5', 'wowza', and 'fms'
- dynamic: true to enable dynamic switching on servers that support it
- netConnectionUrl: the URL to use to check bandwidth. For RTMP, it'll usually be the same as the flash streaming path on your server
- bitrates: a list of the different bitrates you've encoded for this video
- urlPattern: This tells the player what naming convention you've used for the files. {0} represents the base filename of the video, {1} represents the bitrate. In this example, the base filename is ‘mp4:Spinoffs_2_Water', and we'll append ‘_{1}Kbps.mp4' to complete the filename pattern.
The complete Flowplayer bwcheck documentation includes more examples and detailed API documentation.
Related Articles
Amazon Cloudfront offers a new, flexible low-cost CDN solution, particularly for users with relatively small or intermittent streaming delivery needs. Here's how to get up and running.
22 Feb 2010
Companies and Suppliers Mentioned