Before we get started here are the requirements for this tutorial:

FMIS 3 (any size hosting plan)
Flash CS4 or Flex Builder 3 (Adobe)

Source Files [switchingsource]
Video Files [optional]

Stream switching is best used with logic that checks for the user’s bandwidth or stream quality and switching the feed based on those factors. I will approach this with a very simple sample, mostly focusing on the switching logic that you would use to change a users stream.

If you want a more in depth look at handling switching with bandwidth and quality checking, refer to this tutorial:

Dynamic stream switching with Flash Media Server 3

Let’s get started – in your Influxis account, create a new application folder named “switching”. Then upload a blank main.asc file to the directory or, if you are using the application wizard, select the default main.asc file. If you are using your local install of FMS 3.5, create the folder within your default application’s directory.

We will use 5 versions of 1 video file for this sample. You can use the ones in the sample source files (sample1_1500kbps.f4v, sample1_1000kbps.f4v,sample1_700kbps.f4v, sample1_500kbps.f4v, sample1_150kbps.f4v) or create your own. When encoding your videos, Adobe recommends you keep the Audio samples and Bitrates the same for all the files. This way we will get a smooth transition from one file to the next hopefully without hearing any audio pops.

Upload your videos to your account under your application folder matching this folder structure:

switching / streams / _definst_

The video files should exist in the _definst_ folder. If the folders are not there, you can easily create them with the “Create Directory” button in the wizard.

Open flash and create a new FLA, or open Flex and create a new Flex Project.
Within the FLA or MXML script tag, write your connection code to the application you created on your FMS account called “switching”. The rtmp path should look like this:


"rtmp://account.rtmphost.com/switching"

Your Influxis account will be in place of ‘account’ in the rtmp path above, or account.rtmphost.com would be localhost if you are working off of your local machine.

You should have something like this:

FLA (frame 1, Layer 1)

import flash.events.NetStatusEvent;
import flash.net.NetConnection;

var rtmp:String = "rtmp://account.rtmphost.com/switching";
var nc:NetConnection = new NetConnection();

function onNetStatus( p_e:NetStatusEvent ):void
{
	var code:String = p_e.info.code;
	trace("onNetStatus "+code);

	switch( code ) {
		case "NetConnection.Connect.Success":
			break;
	}
};

nc.addEventListener( NetStatusEvent.NET_STATUS, onNetStatus );
nc.connect( rtmp );

MXML



Note: In flex do not forget to call the init function from the Application “creationComplete” event.

I make it a rule to always check my connection first before continuing with the rest of my code.

Now that we have connected successfully, we can move forward.

To keep things simple I’m going to use one button for playing the stream, and I will use radio buttons in the UI to let the user switch between the different videos which were uploaded. This will help us clearly see the switching in action.

Add a video window to the stage of the FLA, or if you are using Flex Builder, create a video control in your MXML. We’ll call the video object “vidWin”. Then create a “doStreams” method to create our stream that we will be using to play the video file. Call the doStreams method from our onNetStatus method after we received a successful connection. Now create a play method that will handle playing the video when the user clicks on the “play” button. Give it a stream name from the files we uploaded to our account to test our logic. Later we will make it play the file dynamically based on some radio buttons we will be implementing.

FLA

import flash.events.NetStatusEvent;
import flash.net.NetConnection;
import flash.net.NetStream;

var rtmp:String = "rtmp://account.rtmphost.com/switching";
var nc:NetConnection = new NetConnection();
var ns:NetStream;

function onNetStatus( p_e:NetStatusEvent ):void
{
	var code:String = p_e.info.code;
	trace("onNetStatus "+code);

	switch( code ) {
		case "NetConnection.Connect.Success":
			doStreams();
			break;
	}
};

nc.addEventListener( NetStatusEvent.NET_STATUS, onNetStatus );
nc.connect( rtmp );

function doStreams():void
{
	ns = new NetStream( nc );
	ns.client = this;
	ns.addEventListener( NetStatusEvent.NET_STATUS, onNetStatus );

	vidWin.attachNetStream( ns );
};

function doPlay( p_e:MouseEvent ):void
{
	ns.play("mp4:sample1_1500kbps.f4v", 0, -1 );
};

MXML



Note: You only need to add the mp4: to the stream name if your files are in h.264 format, if you are using regular FLV files you should not have it.

The UIComponent object called vidHolder used in the MXML is a simple view I use to display my Video Object and give it Component properties. You can replace the videoHolder and Video Object with a Video Display component instead.

Test the application and, once you connect, click the play button. It should start playing a stream in the video window.

Let’s begin adding our switching logic. Like I said before, we are going to use radio buttons to switch between the different bitrates of video while the stream is playing. Add four (4) radio buttons and label each one with the different bit rate number representing each one of the videos we uploaded (1500, 1000, 700, 500, 150). Now give each radio button from lowest to highest bit rate an instance name of the letter “r” and a numeric sequence starting from zero (0), so the lowest bit rate radio button would have an instance name of r0, the next r1 and so on. If adding them in Flex, use the id property on each radio button component. Create a common groupName for the buttons. I’m naming mine “rates” but you can also leave it at default. Upon connection I will get the button group and listen to changes so we can switch the video when the radio button selection changes.

Add a new variable called “videoFiles” and list each of the video file names so we can play them.

var vidFiles:Array = ["mp4:sample1_150kbps.f4v", "mp4:sample1_500kbps.f4v",
"mp4:sample1_700kbps.f4v", "mp4:sample1_1000kbps.f4v", "mp4:sample1_1500kbps.f4v" ];

I want to create a handler that will get the relevant video file from the array based on the radio button selected and I don’t really want to create a big condition statement. I will make a method that substrings the number from the radio button name and uses that number for referencing the slot in the array (“getSelectedVideo():String”), and then finally send that name to a method that will handle our switching (“switchVideo( p_sName:String )”).

This is what the three (3) methods should look like:

//handles radio button group change event.
private function onGroupChange( p_e:Event ):void
{
	switchVideo( getSelectedVideo() );
};
//returns relevant video name
private function getSelectedVideo():String
{
	var rb:RadioButton = rg.selection;
	var sName:String = rb.name;
	var s:String = vidFiles[ Number(sName.substr(1)) ];
	return s;
};
//switches the video.
private function switchVideo( p_sName:String ):void
{
	var npo = new NetStreamPlayOptions();
	npo.streamName = getSelectedVideo();
	npo.transition = NetStreamPlayTransitions.SWITCH;
	ns.play2(npo);
};

If you notice the switchVideo method uses the new play2 function on the netStream class. This will only work with the Flash 10 plugin, so Flex users should make sure you are targeting Flash Player 10 in your compiler settings; otherwise you will get errors.

Ok here is the end code for each IDE respectively:
FLA

import flash.events.NetStatusEvent;
import flash.net.NetConnection;
import flash.net.NetStream;
import flash.net.NetStreamPlayOptions;
import flash.net.NetStreamPlayTransitions;
import fl.controls.RadioButton;
import fl.controls.RadioButtonGroup;

var rtmp:String = "rtmp://account.rtmphost.com/switching/";
var vidFiles:Array = ["mp4:sample1_150kbps.f4v","mp4:sample1_500kbps.f4v",
"mp4:sample1_700kbps.f4v","mp4:sample1_1000kbps.f4v","mp4:sample1_1500kbps.f4v"];
var nc:NetConnection = new NetConnection();
var ns:NetStream;

var rg:RadioButtonGroup;

function onNetStatus( p_e:NetStatusEvent ):void
{
	var code:String = p_e.info.code;
	trace("onNetStatus "+code);

	switch( code ) {
		case "NetConnection.Connect.Success":
			doStreams();
			//set a listener to the button group so i can handle changes.
			rg = r0.group;
			rg.addEventListener( Event.CHANGE, onGroupChange );
			btnPlay.enabled = true;
			break; 
		case "NetStream.Play.Transition":
		case "NetStream.Play.Start":
			break;
		case "NetStream.Play.Stop":
			break;
	}
};

function doStreams():void
{
	ns = new NetStream( nc );
	ns.client = this;
	ns.addEventListener( NetStatusEvent.NET_STATUS, onNetStatus );

	vidWin.attachNetStream( ns );
};

function doPlay( p_e:MouseEvent ):void
{
	ns.play( getSelectedVideo(), 0, -1 );
};

function onGroupChange( p_e:Event ):void
{
	switchVideo( getSelectedVideo() );
};

function getSelectedVideo():String
{
	var rb:RadioButton = rg.selection;
	var sName:String = rb.name;
	var s:String = vidFiles[ Number(sName.substr(1)) ];
	return s;
};

function switchVideo( p_sName:String ):void
{
	var npo = new NetStreamPlayOptions();
	npo.streamName = getSelectedVideo();
	npo.transition = NetStreamPlayTransitions.SWITCH;
	ns.play2(npo);
};

function onMetaData( p_o:Object ):void
{
	trace("onMetaData  "+p_o.duration);
};

function onPlayStatus( p_o:Object ):void
{
	var code:String = p_o.code;
	trace("onPlayStatus "+code);
	switch( code ) {
		case "NetStream.Play.TransitionComplete":
			break;
	}
};

btnPlay.addEventListener( MouseEvent.CLICK, doPlay );
nc.addEventListener( NetStatusEvent.NET_STATUS, onNetStatus );
nc.connect( rtmp );

MXML


Test your application and you should be able to play a stream. Then select a radio button to switch it to another video and if the encoding process was successful, it should transition smoothly. The player will take a few seconds to transition the file so you might want to add handling for enabling and disabling depending on how you use the feature.

Now you can use this code and implement some bandwidth testing to give the end user the optimal stream without any effort on the user’s part. Or you can create something like a preview, where you play a good quality stream for X amount of seconds, then switch to a really low stream and offer the user to see more of the good quality stream for a membership.

8 Responses to “Dynamic Stream Switching with AS 3 (Flash and Flex)”

  1. Mitch

    I need the ability to live cast in multi-bitrates and be able to give clients a choice to choose their bandwidth.

    Reply
  2. Martin

    Great article. I believe this is already built in with TV Station app?
    Like Mitch I need the multiple bitrates option of FMLE 3 with live casting too, any suggestions?

    Reply
  3. Jerry Chabolla

    @Mitch @Martin have you used the FMLE application from Adobe? That will encode 3 different streams from 1 camera source http://www.adobe.com/products/flashmediaserver/flashmediaencoder/. If FMLE isn’t an option, alternatively you can also use multiple computers with their own camera. Or I believe you can even use 1 computer that has 1 USB camera and 1 FireWire camera. You would have to run 2 instances of your publishing application, one for each camera feed, and set the streaming qualities individually. The first is obviously the easier one. Maybe someone else can post some other alternatives. Thanks.

    Reply
  4. Fernando

    Hello

    I am a client of INFLUXIS and interests myself to know if is possible to utilize H. 264 with some application that offers INFLUXIS for broadcasts live. It is needed to include algun PLAYER to be able to visualize it?

    They know the wirecast (varasoftware.com)?

    Thanks

    Fernando

    Reply
  5. Jerry Chabolla

    @Fernando currently you can use our FME Web Viewer (http://www.influxis.com/applications/fme/) to stream a live broadcast, were also working on an update that will encompass the new DVR and other 3.5 features as well. Feel free to submit concerns or requests to our support team (support@influxis.com).

    Reply
  6. Priyanka

    hi

    Can u tell me how can upload video in FMS server using action script.

    Thanks in advance.

    Priyanka Seth

    Reply
  7. martin schulten

    Jerry,

    Thanks for your reply, I think the alternatives you give on using multiple upstreams with FMLE are very creative thanks,

    Martin

    Reply
  8. Avery

    Adobe posted some VERY helpful tools for managing stream switching, and streaming in general. They built a class for stream switching management that is extremely impressive. If you’re looking to do stream switching, you should just download this and use it instead of building your own, you’ll save yourself a ton of time and headache… I should know ;)

    http://www.adobe.com/products/flashmediaserver/tool_downloads/

    “This ActionScript® 3.0 class is the fastest way to help improve experiences through multibitrate delivery. This class includes algorithms that provide the best available bitrate monitoring and transitions that are easy to use and deploy. You can use these classes with Flash CS4 Professional, Adobe Flex® 3, or the Flex SDK.”

    Reply

Leave a Reply

Current day month ye@r *