FMS Review and More..

Topics:
Review: FMS

FMS Review

Built-in Live Application

Each of you has a live folder in your flash folder on ITPs server. This folder maps to itp.nyu.edu/NETID/live on the Flash Media Server. This means that your NetConnection object would use that as the URL to connect to.

Within the live folder you will see several files.

main.asc is the server side actionscript that defines the actual application.

Application.xml defines some defaults such as where recorded streams are saved as well as where shared objects exist on the server. You should make sure that the paths in this file refer to your NETID: /home/NETID/flash/..

allowedHTMLdomains.txt specifies a list of servers/domains that can host the HTML which holds the SWF which can connect to this application. By default it has only a "*" which means any server/domain.

allowedSWFdomains.txt specifies a list of servers/domains that can host the SWF which connects to this application. By default it has only an "*" which means any server domain.

Right now it is fine to leave * but down the road we may need to change this to allow only "itp.nyu.edu" in both of these files. If you are hosting the SWF or HTML which contains the SWF on your own server you may need to add that to the list.

main.asc contains two sections which refer to the use of those files. The first part is at the very top:
        this.HTMLDomainsAuth =  true;
        this.SWFDomainsAuth =   true;
        
If you don't want to utilize the allowedHTMLdomains.txt or allowedSWFdomains.txt files you can switch the "true" to "false".

The other place that these files are referred to is directly below that:
        // Populating the list of domains which are allowed to host HTML file
        // which in turn may embed a SWF that connects to this application
        this.allowedHTMLDomains = this.readValidDomains("allowedHTMLdomains.txt","HTMLDomains");

        // Populating the list of domains which are allowed to host a SWF file
        // which may connect to this application
        this.allowedSWFDomains = this.readValidDomains("allowedSWFdomains.txt","SWFDomains");
        


Unfortunately these commands by default are wrong. If you have "true" in the first section and the second section is as it is shown above, no one will be able to connect as the FMS won't be able to open those files (it won't be able to find them).

To make things work properly you need to change the path to the files putting in the proper path from your home directory to this application (in our case, "live"):
	this.allowedHTMLDomains = this.readValidDomains("live/allowedHTMLdomains.txt","HTMLDomains");
	this.allowedSWFDomains = this.readValidDomains("live/allowedSWFdomains.txt","SWFDomains");
		
Now the "live" application should work for you..

main.asc

As we know main.asc contains all of the application logic for any application on FMS. Generally it will have the following the function definitions:

application.onAppStart = function() { ... }
Called when the application is loaded by the server

application.onConnect = function(currentClient, p_autoSenseBW) { ... }
Called when a client is connected to via a Flash client (NetConnection). At some point you should have a line in the function which says: this.acceptConnection(currentClient); otherwise the client won't connect.. (If you don't want the client to connect, you would call this.rejectConnection(currentClient);

application.onDisconnect = function(currentClient)
Called when a client is disconnected from FMS.

trace() is a good function to use throughout the code so you can see what is happening on in the FMS console. (http://itp.nyu.edu/fms/)
trace("application is starting up!");
		
The FMS Server-Side ActionScript Language Reference is a good place to look for functionality that you may need: http://livedocs.adobe.com/fms/2/docs/wwhelp/wwhimpl/js/html/wwhelp.htm?href=00000630.html

A good source for various tutorials is: FMS Guru: http://www.fmsguru.com/

Recording Live Streams

Clients (Flash Streaming/Broadcasting Applications) can use the "record" parameter in the NetStream.publish() method.. This is great for simply recording on the server but if you want to push things further, it isn't the greatest..

The server itself can determine when a live stream is recorded and published for others.
application.onAppStart = function() 
{
	// Create a Server Side Stream
	this.serverNetStream = Stream.get("serverStream");
	
	// Play a stream called "liveStream" that is published from a client to the serverNetStream
	this.serverNetStream.play("liveStream",-1,-1);  
	// NetConnection.publish("liveStream","live"); // Client side..

	// Information callback on serverNetStream
	this.serverNetStream.onStatus = function(info)
	{
		if (info.code == "NetStream.Play.PublishNotify")
		{
			// This is how we tell something was published from a client

			// tell the server to start recording
			// a function we created below
			application.startRecording();
		}
		else if (info.code == "NetStream.Play.UnpublishNotify")
		{

			// This is how we tell that something was unpublished from a client

			// tell the server to stop recording
			// a function that we created below
			application.stopRecording();
		}
	}
}
		
application.startRecording = function()
{
	trace("start recording");
	this.serverNetStream.record();	
}

application.stopRecording = function()
{
	trace("stop recording");
	this.serverNetStream.record(false);
}
	
The "Stream" class is our key.. The streams are recorded in the place specified in your Application.xml file.

The above records and allows people to play the live stream. It could be extended to play files off of the server when the publisher disconnects or made to allow the server to switch playing from one live stream to another.

Shows Live Stream from Client: http://itp.nyu.edu/~sve204/liveweb/splayer.php?rtmp=rtmp://itp.nyu.edu/sve204/recordandstream&stream=liveStream

Shows Live Stream from Server: http://itp.nyu.edu/~sve204/liveweb/splayer.php?rtmp=rtmp://itp.nyu.edu/sve204/recordandstream&stream=serverStream

Calling Commands on the Server

Client Side:
package 
{ 
  import flash.display.Sprite; 
  import flash.events.NetStatusEvent; 
  import flash.net.NetConnection; 
  import flash.net.Responder; 

  public class ConnectAndDoSomething extends Sprite 
  { 
        // Overall NetConnection for communicating with FMS
        private var nc:NetConnection; 
        
        // RTMP URL, same as directory on FMS
        private var rtmpURL:String = "rtmp://itp.nyu.edu/sve204/APPLICATIONNAME";
         
        // Responder (for communicating messages with FMS)
        private var responder:Responder; 
        
        public function ConnectAndDoSomething() 
        { 
        	// Construct NetConnection and connect to server
             nc = new NetConnection(); 
             nc.connect(rtmpURL); 
             
             // Add a listener for connection
             nc.addEventListener (NetStatusEvent.NET_STATUS,connectionHandler); 
        } 
        
        
        // Listener for connection
        private function connectionHandler(e:NetStatusEvent):void 
        { 
        	// If we are connected
             if (e.info.code == "NetConnection.Connect.Success") 
             {
             		// Create a responder to call a method on server
                   responder = new Responder(gotResponse);
                   
                   // Call the doSomething function on server with our new responder
                   nc.call ("doSomething",responder); 
             } 
        }
        
        // got something back from the server
        private function gotResponse(command:String):void
        {
        	trace("Got Response from Server: " + command);
        }
 }
}
Server Side:
application.onConnect = function(currentClient)
{
         // Function that get's called by the client to determine where to go
        currentClient.doSomething = function(command)
        {
                trace("Client Called doSomething");

                // Send something back to the client
                return "Something Done";    
        };
}
Using this, you could easily write a client which changed the live stream to another live stream and the like..