labs-headers

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

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

Source Files [optional]

In your Influxis account, create a new application folder named “dvr”.  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 applications directory.

I will approach this with a very simple sample, but I’m also including a more complex version in the source file for everyone to play with. I’m will mostly focus on the code that you need to pull off the DVR functionality.

Let’s get started – 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 “dvr”. The rtmp path should look like this:


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

..and  ‘account’ would be your Influxis account, 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)

var rtmp:String = "rtmp://account.rtmphost.com/dvr";
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

		

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, let’s build our streams. I will make two streams: one publishing my camera up to the FMS server, and the other streaming my video down from the FMS server.

Add two video windows to the stage of the FLA, or create two video controls on the MXML. I will simply name them v1, which will view the camera, and v2, which will view the incoming stream. Let’s also add a reference to our camera and our microphone: name the variable containers “cam” and “mic”.

FLA and MXML

var cam:Camera = Camera.getCamera();
var mic:Microphone = Microphone.getMicrophone();

function doStreams():void
{
	nsOut = new NetStream( nc );
	nsOut.client = {};
	nsOut.addEventListener( NetStatusEvent.NET_STATUS, onNetStatus );
	nsIn = new NetStream( nc );
	nsIn.client = {};
	nsIn.addEventListener( NetStatusEvent.NET_STATUS, onNetStatus );

	v1.attachCamera( cam );
	v2.attachNetStream( nsIn );
};

Note: Be sure to declare these new nsOut and nsIn variables in your code.

Now call the “doStreams” method from the success condition in the switch handler we created. The code should now look like this:

FLA

var rtmp:String = "rtmp://account.rtmphost.com/dvr";
var nc:NetConnection = new NetConnection();
var nsOut:NetStream;
var nsIn:NetStream;

var cam:Camera = Camera.getCamera();
var mic:Microphone = Microphone.getMicrophone();

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

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

function doStreams():void
{
	nsOut = new NetStream( nc );
	nsOut.client = {};
	nsOut.addEventListener( NetStatusEvent.NET_STATUS, onNetStatus );
	nsIn = new NetStream( nc );
	nsIn.client = {};
	nsIn.addEventListener( NetStatusEvent.NET_STATUS, onNetStatus );

	v1.attachCamera( cam );
	v2.attachNetStream( nsIn );
};

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

MXML

		

Note: Remember to add the Video object code in the init function if you are using Flex.

Test your code for any errors.  You should see your camera attach to one of the windows.

Now what I want to add two buttons. We’ll give one of them an instance/id of “btnPub” which will call to start my stream publishing and the other one “btnPlay” which will start playing the feed down. I will add a string variable “vidName” that will help centralize access to the name of my stream. Let’s also create two methods, one called “doPublish” and the other “doPlay”. Here is what the “doPublish” and “doPlay” methods should look like:

function doPublish( p_e:MouseEvent ):void
{
	nsOut.attachAudio( mic );
	nsOut.attachCamera( cam );
	nsOut.publish( vidName, "record" );
};

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

Now this is a live feed we are doing, but in order to get the DVR functionality working on the receiving end we need to set our feed to record.  To do this, simply specify “record” in the second argument or our publish method.  This second argument defaults to “live” if left out, so you must not forget to set it to “record” if you want to use the DVR feature.

In the nsIn stream, we call the play method.  In order for the DVR functionality to work for the playback, you must play the stream as if it were a recorded stream in FMS.  To do this, specify the next two arguments following the name of the stream. The second argument is the frame in which the stream should start, 0 is the first frame in a video, the third argument specifies how long to play the stream.  In our case we want it to play until it ends, so specifying a -1 will do that; any other negative number will default to -1. Like the publish function, leaving out these extra arguments will not allow us to use the DVR controls with the stream, so be sure to add them if you want the DVR feature.

Okay, so now your final code should look like this in its entirety:

FLA

var rtmp:String = "rtmp://account.rtmphost.com/dvr";
var vidName:String = "livefeed";
var nc:NetConnection = new NetConnection();
var nsOut:NetStream;
var nsIn:NetStream;

var cam:Camera = Camera.getCamera();
var mic:Microphone = Microphone.getMicrophone();

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

	switch( code ) {
		case "NetConnection.Connect.Success":
			doStreams();
			btnPub.enabled = true;
			btnPlay.enabled = true;
			break;
	}
};

function doStreams():void
{
	nsOut = new NetStream( nc );
	nsOut.client = {};
	nsOut.addEventListener( NetStatusEvent.NET_STATUS, onNetStatus );
	nsIn = new NetStream( nc );
	nsIn.client = {};
	nsIn.addEventListener( NetStatusEvent.NET_STATUS, onNetStatus );

	v1.attachCamera( cam );
	v2.attachNetStream( nsIn );
};

function doPublish( p_e:MouseEvent ):void
{
	trace("doPublish "+vidName);
	nsOut.attachAudio( mic );
	nsOut.attachCamera( cam );
	nsOut.publish( vidName, "record" );
};

function doPlay( p_e:MouseEvent ):void
{
	trace( "doPlay "+vidName );
	nsIn.play( vidName, 0, -1 );
};

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

btnPub.addEventListener( MouseEvent.CLICK, doPublish );
btnPlay.addEventListener( MouseEvent.CLICK, doPlay );

MXML

		

Now let’s run the application. Let the camera run for a few seconds, wave your hands around, bug out your eyes, stick your tongue out, or put a fellow co-worker in a headlock. Now come back to the application and push play on the playing side of the stream. Your stream should start playing from the first frame, just before the headlock maneuver, and your live stream should still be recording and playing. You will eventually see any other movements you do as the playing stream catches up.

With this you can start to build a more complex interface that allows the user to scrub around the video clip and be able to come back to the live point.

If you haven’t already, go ahead and download the source files to this tutorial and see the more advanced experiment we were playing with. Any improvements that you can post for everyone would be greatly appreciated. I will do my best to keep the source files updated.

2 Responses to “DVR functionality with FMS 3.5 using AS 3.0 (Flash and Flex)”

  1. Alkhawar

    Wonderfull post can i Transfer to my Own Blog

    Reply
  2. influxis

    Sure as long as there is a credit link to the original post it shouldn’t be a problem ;).

    Reply

Leave a Reply to influxis

Click here to cancel reply.

Current day month ye@r *