Requirements
Prerequisite knowledge                                     
General familiarity with Flash streaming media and programming ActionScript in Adobe Flash or Adobe Flex.
 
Required products
Flash Media Server (Download trial)
 
Sample files
 
User level
Intermediate
 
Additional Requirements
 
Flash Media Server tools
This article provides an overview of integrating dynamic streaming capabilities of Adobe Flash Media Server 3.5 and Adobe Flash Player 10 into existing video players using the new ActionScript 3.0 dynamic stream API from Adobe. I focus not only on the compatibility differences but also the related, internal differences implementing the ActionScript 3.0 dynamic stream API classes for dynamic streaming content. After reading this article you will develop a better understanding of the integral differences between the original playback methodology and the new dynamic streaming process, as well as a tight grasp on compatibility for new and old players.
 
For information on what dynamic streaming is, why you would want to use it, and the basics of the ActionScript 3.0 dynamic stream API, refer to Part 1: Overview of the new capabilities or Part 2: ActionScript 3.0 dynamic stream API.
 
Migrating from Net.Stream.play() to NetStream.play2()
 
Adobe has added new ActionScript 3.0 classes to provide a robust API for accessing valuable QoS data and providing an efficient and powerful means to implement dynamic streaming with a great experience for users. The lower-level classes offer all the power needed to provide highly customizable solutions. For more detailed information on the lower-level classes, read Abhinav Kapoor's article, ActionScript guide to dynamic streaming. The DynamicStream and DynamicStreamItem classes are optional and provided to get applications integrating dynamic streaming quickly, with best practices under the hood and simple integration as key benefits.
 
The NetStream.play2() method provides the needed API starting point for initializing dynamic streaming as well as the other new playback features, such as enhanced playlist support and content swapping. The NetStream class is the obvious choice to add new streaming functionality, since it already handles the primary streaming functionality, and thus would not require a massive change in process. The reason behind adding the new play2() method instead of just enhancing the old play() method is to maintain backwards compatibility and leave available the option of developing video players compatible with multiple versions of Flash Player, which we will discuss later.
 
In general, the limitations of the old classes available to Flash Player version 6 through 9, and interfacing with Flash Media Server 3, were primarily twofold. The first limitation was the lack of information available about the quality and capacity of the current stream. With no truly viable Quality of Service properties, the best you could do was to monitor the bufferLength and currentFPS properties, which was tricky at best for deriving a complete analysis, largely because of how Flash Media Server handles sending data to the buffer. This left it difficult to determine when to switch down, and even more difficult to know when to switch up to a higher bit rate. The other limitation that was very difficult was the switch itself. It was incredibly difficult to make a switch in a smooth fashion, and especially to maintain audio smoothness. The lack of video stream transitions (which are now available) led to a number of user experience issues that were often very difficult to handle appropriately.
 
Playback architecture differences
 
The key differences in playback architecture that should be considered when leveraging dynamic streaming are those surrounding playback initialization, monitoring, and user interface display.
With initialization, the biggest architectural decision is whether to build a custom solution for dynamic streaming and base it off a standard NetStream, or to use the DynamicStream class from Adobe. With a custom solution, you will have to monitor and make all the decisions about when to switch based on the Quality of Service metrics available on the NetStream.info property. In addition, you will need to manage and maintain a list of multi-bitrate files, being sure to keep track of the individual streams' bit rates. For more details on this approach, check out Abhinav Kapoor's article, ActionScript guide to dynamic streaming. If you are using the DynamicStream class, implement it as you normally would a standard NetStream and pass it all the multi-bitrate files in the form of a DynamicStreamItem.
 
With either approach, selecting which stream to play first can be a point of adjustment. By default, the DynamicStream class will play the lowest-bitrate file and then switch up to a higher-bitrate stream once the monitoring data reports the availability to do so. An alternate approach would be to select the mid-range quality stream or to perform a client-to-server bandwidth test, which Flash Media Server has supported natively since version 3. The downside of the initial bandwidth detection test is the approximate two-second delay time to perform the test, though in many custom solutions, that can be worked into the application without adversely affecting the user experience. To specify the stream bit rate to start with when using the DynamicStream class, specify a value for the startRate property on the DynamicStreamItem instance that is passed to the DynamicStream.startPlay() method.
 
Example
 
var ds:DynamicStream = new DynamicStream(nc); var dsi:DynamicStreamItem = new DynamicStreamItem(); // add a new stream/bitrate pair dsi.addStream("mp4:realeyes_300k.mov", 300); dsi.addStream("mp4:realeyes_700k.mov", 700); dsi.addStream("mp4:realeyes_1000k.mov", 1000); //Specify the desired starting bitrate to use dsi.startRate = 700; // start playing ds.startPlay(dsi);
 
Strategies for managing earlier Flash Player–FMS compatability
 
The new dynamic streaming capabilities and associated APIs and classes were developed with backwards compatibility in mind. This enables you to offer the new dynamic streaming capabilities to users running Flash Player 10 while providing alternate video playback for users on previous versions of Flash Player from a single application with only minor modifications. The two items you need to manage are access of the NetStream instance play2() method and the info property.
 
To enable backwards compatibility with Flash Player 9, the play2() method and info property should not be invoked unless the user has Flash Player 10 or later. To do this, you can check the user's Flash Player version at runtime from the static version property on the Capabilities class: Capabilties.version. The return value of a Capabilities.version call will be a String formatted as such:
 
[platform/OS] [majorVersion],[minorVersion],[buildNumber],[internalBuildNumber]
 
Possible platform/OS values are "WIN", "MAC", and "LNX". Here is an example: WIN 10,0,0,0. You can determine the major Flash Player version number in several different ways; one option will be shown and discussed in the next walkthrough.
 
The following method will return a number for the major version of Flash Player while ignoring which dot release it is. This is valuable for determining if the user's installed copy of Flash Player is version 10 or later. This is done by performing some basic string manipulations to the Capabilities.version property available in either Flash or Flex:
 
 
import flash.system.Capabilities; public function getFlashPlayerMajorVersion():Number { var fpVersionStr:String = Capabilities.version; return Number( fpVersionStr.split(" ")[1].split(",", 1) ); }
 
Once the version has been identified, then a conditional if() statement can be used—one branch for Flash Player 10 using the play2() method and info property for Quality of Service monitoring, and the other branch for earlier versions of Flash Player to continue using the play() method and any previous monitoring techniques. For more information on some of the previous techniques for dynamic streaming in Flash Player 9, please see my article, Dynamic stream switching with Flash Media Server 3.5.
 
If you are using the DynamicStream and DynamicStreamItem classes, the conditional system starts the same by checking the Flash Player version, but differs at a higher level. If the user is not using Flash Player 10 or later, then the DynamicStream class should not be instantiated or used at all. Instead, the standard NetStream class should be instantiated and used for the previous versions of Flash Player. This will give you a fork in your stream management, but is still relatively easy to manage.
 
Important: If the Flash Player version is not used conditionally to determine whether to use a NetStream instance play2() method, info property, or DynamicStream class, then if any of these are used, the result could be a runtime error being thrown for users running versions prior to Flash Player 10.
 
Another important requirement to successfully implement dynamic streaming is Flash Media Server 3.5. Therefore, it is wise to verify the server version in your application before trying to make any dynamic streaming–related calls. This is done by accessing the version property on the NetStatusEvent with the event object containing a info Object and a codeproperty (event.info.code) with the value of NetConnection.Connect.Success. The property is on the data Object within the info Object of the event (event.info.data.version) and is a string with the full dot release of Flash Media Server.
 
Walkthrough 4. Dynamic streaming with backwards compatibility
 
In this walkthrough, you will do the following:
  • Add conditional logic to the previous walkthrough you created in Part 1 (Walkthrough 3: FLVPlayback with an external SMIL file) to invoke the dynamic streaming only if supported
  • Check for the appropriate Flash Player version at runtime
  • Check for the appropriate Flash Media Server version at runtime
  1. Open DynamicStreamSample-Compatible.fla in the {start files}/DynamicStreamSample - Compatible folder.
  2. Open DynamicStreamSample.as in the {start files}/DynamicStreamSample - Compatible/com/realeyes/media/ folder. This file is a continuation of Walkthrough 1; we are adding code to make the class backwards compatable.
  3. Locate the comment //Create a NetStream property and declare a new private variable named _ns typed as a NetStream object:
// Create a NetStream property private var _ns:NetStream;
     
    4. Under the comment // Create a flag for server compatibility, declare a private _isServerCapable Boolean variable:
     
// Create a flag for server compatibility private var _isServerCapable:Boolean;
     
    5. Under the comment // Create target properties, create two private Number variables: _targetFMSVersion and _targetFPVersion set as follows:
     
// Create target properties private var _targetFMSVersion:Number = 3.5; private var _targetFPVersion:Number = 10;
     
    6. Locate the _onNetStatus() event handler method
    7. In the NetConnection.Connect.Success case of the switch/case statement, add a call to the _verifyServerVersion() method and pass it p_evt.info.data.version as the only parameter.
     
    The case statement should now look like the following:
     
case "NetConnection.Connect.Success": { trace( "VERSION: " + p_evt.info.data.version ); _verifyServerVersion( p_evt.info.data.version ); _initStream(); break; }
     
    8. Locate the _verifyServerVersion() method.
    9. Create a local Number variable named fmsVersion and set it equal to the result of the following statement: Number( p_version.split(",", 2).join(".") ) This parses out the version number as returned by the FMS server and creates a number for you.
     
var fmsVersion:Number = Number( p_version.split(",", 2).join(".") );
 
10. Under the provided trace() statement, add an if..else condition. if fmsVersion is greater than or equal to_targetFMSVersion, set the _isServerCapable property to true, otherwise set its value to false:
 
if ( fmsVersion >= _targetFMSVersion ) { _isServerCapable = true; } else { _isServerCapable = false; }
 
The completed _verfyServerVersion() method should look like the following:
 
private function _verifyServerVersion( p_version:String ):void { var fmsVersion:Number = Number( p_version.split(",", 2).join(".") ); trace("fmsVersion: " + fmsVersion); if ( fmsVersion >= _targetFMSVersion ) { _isServerCapable = true; } else { _isServerCapable = false; } }
     
    11. Now we need to get the Flash Player version. Locate the _initStream() method.
    12. Under the comment // Get flash player version, create a local Number variable named fpVersionand set it equal to the value returned from the method getFlashPlayerMajorVersion(). This method has been provided for you; it uses Capabilities.version to get the Flash Player version and then parses the version number in a similar fashion as the FMS server version number.
     
// Get flash player version var fpVersion:Number = getFlashPlayerMajorVersion();
     
    13. Under the comment // Use the appropriate stream, add an if...else block. If fpVersion is greater than or equal to _targetFPVersion and _isServerCapable is true, then call the _initDynamicStream() method, otherwise call the _initNetStream() method:
     
// Use the appropriate stream if ( fpVersion >= _targetFPVersion && _isServerCapable ) { _initDynamicStream() } else { _initNetStream(); }

 

The completed _initStream() method should look similar to the following:

 

private function _initStream():void { trace( "-INIT STREAM -"); if ( !_vidDisp ) { _vidDisp = new Video(); this.addChild( _vidDisp ); } // Get flash player version var fpVersion:Number = getFlashPlayerMajorVersion(); trace("fpVersion: " + fpVersion + " && _isServerCapable: " + _isServerCapable ); // Use the appropriate stream if ( fpVersion >= _targetFPVersion && _isServerCapable ) { _initDynamicStream() } else { _initNetStream(); } }
     
    14.Save and compile the file to run the sample.
Where to go from here
 
Dynamic streaming offers extremely powerful functionality and benefits to end users and their experiences. Implementing dynamic streaming is generally straightforward and the ActionScript 3.0 dynamic stream API makes this even easier. However, since the new dynamic streaming features leverage some new API methods and properties on the NetStream class, it is important to take backwards compatability into consideration. This can be managed easily as you learned in this article by checking the Flash Player version for version 10 or later and by checking the Flash Media Server version with the new event.info.data.version property on the NetConnection instance dispatch of the NetStatusEvent with the event.info.code of NetConnection.Connect.Success for Flash Media Server version 3.5 or later.
 
Be sure also to read the other articles that cover dynamic streaming in the Flash Media Server Developer Center.