Recording on FMS 3.5 with FMLE and DVR Functionality

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 [optional]

This is a very simple approach to recording your streams with FMLE on FMS 3.5, assuming you know the basic principals and rules of FMS like creating an application, connecting to it and playing a stream. For more information on this you can read the Getting Started section of the Adobe Live Docs.

Let’s start with the Server Side logic first. Open Flash CS4 and create a new ActionScript Communication File, or you can use any ActionScript editor that supports AS 1.0 logic, even a simple text editor like NotePad will work. Save the file as “main.asc” (an asc file is an ActionScript Communication File that FMIS uses similar to an AS file). Copy and paste this logic into your main.asc file:

main.asc

application.onAppStart = function()
{
	trace("app fme started!");
};

application.onConnect = function(p_c)
{
	this.acceptConnection(p_c);
};

application.onPublish = function (p_c, p_stream)
{
	trace("onPublish stream: "+p_stream.name);
	p_stream.record();
};
application.onUnpublish = function(p_c, p_stream)
{
	trace("onUnpublish stream: "+p_stream.name);
	p_stream.record(false);
};

As we know “onAppStart” fires automatically when FMIS loads the application, and “onConnect” fires automatically when a user connects to your application. Within the “onConnect” above we are accepting every client’s connection with the “Application.acceptConnection” method. That’s a real brief description of what is happening in the main.asc file (again for more on this please referr to the samples in the docs).

In the main.asc, the methods we really want to focus on are the “onPublish” and “onUnpublish” methods from the Application Class (these methods were introduced in FMS 3.0).   The methods notify our code when a client has published or unpublished a stream. They pass two pieces of data within its receiving arguments, the Client object, of the client publishing or un-publishing, and the Stream object that is being published. Here are the API references:

Client API

Application API

In the onPublish event we receive a reference to the stream that is being published to the FMS service. The Server-Side Stream class has a method called “record” which tells FMS to record the stream to the server. Calling that same method but passing it a “false” Boolean will stop the recording.  So if you look back at our methods, onPublish starts the recording, and onUnpublish stops it.  These methods will fire if ANY client starts recording not just the FMLE, so be sure you implement some type of checking before allowing record. This will work in most cases since everyone else is usually playing a stream as a viewer and only 1 playing stream is expected.

Stream API

Okay, that is all for our Server-Side code.  Now, let’s create our application and upload the main.asc file to it. In your Influxis account, access the file manager screen and create a new application folder named “fme”. Then upload your main.asc file to the directory. If you are using your local install of FMS 3.5, create the folder within your default application’s directory and put your main.asc file in there.

If you are using the application wizard to create a new application, select the radio button that’s labeled “I will add my own”, hit ‘continue’ and select the “Upload ASC” to upload your main.asc file.

Okay, now let’s create the simple viewe — 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 “fme”. The rtmp path should look like this:

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

The account part 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/fme";
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.

It’s important to check your connection first before continuing with the rest of my code. Open the FMS Administration Panel when you work in FMS — it will show you live logging which is crucial when debugging FMS Applications; the majority of connection failures can be tracked to Server-Side code throwing errors.

Now that we have connected successfully, let’s build our stream which will play the video that FMLE will be playing on the FMS server.

Using Flash – Add a video window to the stage of the FLA and give it an instance name of “vid”, then add a button component and give it an instance name of “btnPlay”.   If you are on Flex, add a button component with an id of “btnPlay” and add a UIComponent with an id of “vidHolder”. In your init methods create a video Object and add it as a child to the vidHolder.

Create a streams method called doStreams that will handle the creation of our NetStream Object. Create a NetStream within the function called nsIn:NetStream.  Be sure to declare it at the top.   Add a string variable called “vidName” which will contain the name of the stream that FMLE will be publishing out.  Set the value of vidName to “livefeed”.

public var vidName:String = "livefeed";

Finally create a method called “doPlay” this will handle our btnPlay events and play our stream. Call the play method of the netstream nsIn, and set our “vidName” variable as the first argument. 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 (frame 1, Layer 1)

var rtmp:String = "rtmp://account.rtmphost.com/fme/";
var vidName:String = "livefeed";

var nc:NetConnection = new NetConnection();
var nsIn:NetStream;

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

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

function onMetaData( p_o:Object ):void
{
	//handle metadata
};

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

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

	vid.attachNetStream( nsIn );
};

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

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

btnPlay.addEventListener( MouseEvent.CLICK, doPlay );

MXML


	
		
	

	
		
			
			
		
		
			
		
	

NOTE: If you notice in the code, I use variables to centralize text or data that I might want to change frequently or easily have access to.

Test the code, make sure there are no errors. Since there is no video being published the stream will not play anything.

Let’s setup our FMLE stream to our “fme” application. Open your FMLE application; you can download it from Adobe if you haven’t already done so:

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

Select the “Stream to Flash Media Server” option and make sure the box is checked.  Then in the FMS URL add the rtmp path (rtmp://account.rtmphost.com/fme). In the Stream field enter “livefeed”, adjust your camera and mic settings, then click the “Connect” button. Once you are connected click the green “Start” button to begin the stream.

Cam and Settings I’m using:

Device: Logitech QuickCam Pro 9000 (USB 2.0)
Format: VP6
Frame Rate: 15.00
Input Size: 320×240 (Maintain Aspect Ratio)
Output size: 320 x 240
Bit Rate: 200kbps

Mic Settings:

Device: Realtek HD Audio Input (separate mic connect to jack on computer)
Format: MP3
Channels: Mono
Sample rate: 11025 hz
Bit Rate: 20 kbps

Run your application from flash or flex IDE and move around in front of the camera, tell a joke, anything to notice a difference in time.   Click play on your application and the video should be trailing a few seconds behind the live position.  If you stop streaming from your FMLE, you will receive an unpublished event in your status calls but your feed will play all the way to the end as if it were a pre-recorded video. In fact you can now restart playing your stream and it will play like a recorded video.  Go to your account on the FMS server and see that there is a stream in the streams / fme folder called livefeed.flv

Use this sample to play/record a live stream coming from FMLE or a flash client, or just to play a pre-recorded stream.
Much thanks to Brad Outlaw (Adobe FMS) for the Server-Side code and the always helpful support.

5 Responses to “Recording on FMS 3.5 with FMLE and DVR Functionality”

  1. Tivo Premiere

    I was looking for dvr related articles, this was helpful – bookmarked your site!

    Reply
  2. Curtis

    Still lost unfortuntely! Are these three seperate files?? I know about the main.asc file. But what are these are two files and where do they GO and WHAT ARE THEY SUPPOSE TO BE NAMED?? Somebody help me asap!

    Reply
  3. Mike

    This is a very nice article! I liked it that you took the time to create the client side code for both flex and flash. It really helped me a lot since I only know flex.

    Reply
  4. Devon

    I am unable to record anything for more than a few seconds from a live stream. I might have gotten to two minutes once. It seems that the server times out the record function that I call from the main.asc file. When I review the recordings it does include a small clip of the broadcast but never more than a few seconds. I have confirmed that even though the recording stop the live stream continues.?????

    Help!!!!!!!!

    Is there a conflict with the publish and and recall function???????

    Reply
  5. Noe

    Sorry guys for not being more attentive with the questions you have been posting.

    So lets get started…

    Curtis:
    Are the two files you are referring to the quickviewer_fl.swf and the quickviewer_fl.html. If so these files must be placed within a web directory on your web host/server. Once placed on the web your users can access the quickviewer_fl application and viewer the dvr broadcast you are transmitting from your Flash Media Live Encoder.

    Devon:
    Even though we’re unable to reproduce the issue you were experiencing, we feel the issue may be as a result of Garbage Collection clearing the stream object which isn’t which isn’t really anchored to a constant within the application. What you will want to do to fix the issue is to anchor the stream object to the Application scope, as shown below:

    application.onPublish = function (p_c, p_stream)
    {
    this.stream = p_stream;
    this.stream.record();
    };
    application.onUnpublish = function(p_c, p_stream)
    {
    this.stream.record(false);
    };

    Ok guys how this helps and if you have any questions please feel free to post them or send them over onto Influxis Support (support@influxis.com).

    Thanks,

    Influxis Support
    Noe

    Reply

Leave a Reply

Current day month ye@r *