Flash Media Server to Adobe Connect

August 22, 2011

In this article I will describe how to use a recently created custom pod for Adobe Connect. This custom pod is provided free of change and is provided as is with no additional support or warranty (how is that for some lawyer speak). Briefly, this custom pod allows you to stream high frame rate video from the Adobe Flash Media Server to an Adobe Connect meeting room. I used the collaboration sdk to create a shared experience. In other words if you are a host in a meeting room you can load and setup a connection to both live and ondemand video that you control for the meeting participants. As the host you make the connection and choose the video and when you hit play all participants will see that the video has started to play. This is very different than a typical video player where each individual has their own experience and could be watching different sections of a the same or different videos. This custom pod understands the different Adobe Connect meeting roles (i.e. host, presenter, participant). Only the host has interface elements (buttons, progressbar, etc…). Admittedly  the user interface could use some work and I do intend to improve it so do not beat me up too bad but also do not hesitate to give me advice on improvements.

The following is a simple diagram of the workflow.

Live Video Workflow for Custom Pod

A) Flash Media Encoder B) Flash Media Server C) Custom Pod in Connect Meeting

There are many considerations when ever you consider streaming high quality video. First of all the camera is an important part of the equation. I did a number of tests with web cameras and found that two of the three web cameras that I tested could not consistently produce 30 frames per second of video. Do not skimp on a quality camera. The second, third and fourth and and and considerations are all BANDWIDTH. You cannot stream a 500 kbps stream over a connection that only has 300 kbps available. There are many people that are confused about bandwidth but it is fairly simple. If you look at the diagram above you will notice that you have to send the encoded stream from the camera / laptop to the Flash Media Server and then on to Adobe Connect. You need the appropriate amount of bandwidth at each step. It is not enough to have a great connection from FMS (Flash Media Server) to Adobe Connect you also need an appropriate connection from the source (camera / laptop) to FMS. Often someone assumes that because their wireless card mentioned 54 Mbps that they are covered for streaming video. The key consideration is “usable bandwidth”. I have included the ability to test bandwidth in this application as well as a status indicator that will give you an idea if your connection is appropriate for the video you are attempting to stream.  It is also important to note that available bandwidth changes continuously.  You might find that you do a bandwidth test and have plenty and thirty seconds later you have half as much. It is best not to use a wireless connection as their is more variability and more unknowns with a wireless connection versus a wired connection.

Custom Pod UI:

Lets walk through some of the functionality of the custom pod.  After it is uploaded to a share pod inside of Adobe Connect it should look like the following:

Adobe Connect Custom Video Pod

Adobe Connect Custom Video Pod

The first thing you should understand is that this is the interface that the host will see when they upload the custom pod. The dark green in the progress bar shows the progress of the playing video. The dark blue shows the size of the current buffer. If you do not see any dark blue then there is no buffer and you are probably not having a great play back experience. You will not see a progress bar for live video as there is not enough buffer to show. Notice the green status indicator in the upper left hand corner of the screen.  This indicator will be seen by both hosts presenters and participants. This indicator shows only the local connection status. In other words if you are looking at this indicator it shows your status not a combined or status of other individuals in the meeting. The following table gives a brief highlight of the states and meanings.

  This indicates no connection. Each time you connect the indicator will turn green initially and each time you disconnect it will turn black.
  This indicates the initial connection as well as a video that has enough bandwidth to play and keep up with the video that is being sent from the Flash Media Server.
  This indicates that there are or have been issues with the video playback. Often times this is represents a temporary condition so do not panic the first time you see the indicator turn orange or red.
  This indicates that the issues are getting worse but as stated before this can be temporary so give it at least a few seconds and see if the condition improves.

If someone in the meeting mentions that the video playback is not smooth or the quality is not great you could ask them what the color of the indicator is to get an idea if the problem is bandwidth related. This indicator does not indicate a change in frames per second. It is possible to retrieve fps data from the metadata of the stream but it seems that this does not indicate that actual fps on the passed on from the encoder (e.g. Flash Media Live Encoder).

Adobe Connect Meeting Host:

You will notice that each role in an Adobe Connect meeting has a slightly different view of this custom pod. The host has complete control. As a mater of fact the first host to upload the custom pod retains complete control and all other hosts will see the controls but will only be controlling their local experience. With that said I think that it is a good practice to have only a single host in most if not all meetings. More than one presenter is not an issue but more that one host can create issues regardless if you are using this custom pod or not.  The following is the host view of the custom pod:

Custom Pod with Settings Visible

Custom Pod with Settings Visible

Workflow for live video:

The first step to playing live video is to have a live video source. Keep in mind that if you intend to use a simple web camera your quality will probably not be that much better than what you would get out of the default camera support in Adobe Connect. If on the other hand you have a higher quality camera or would like a higher frame rate follow these steps.

1) setup a computer with enough horse power to encode the video and with enough bandwidth to send that video to the Flash Media Server. Download and install the free Flash Media Live Encoder.

2) setup or use an existing Flash Media Server. There are a great number of resources for getting started with the Flash Media Server.

3) upload the custom pod. The custom pod is in a zip archive. In a share pod in Adobe Connect simply locate the custom pod zip archive on your computer and upload the entire zip.

4) enter the server url and stream name for the video that you are publishing from the Flash Media Live Encoder. It is a simple matter to find the connection stream for the server. You will notice by the example above the entry field that it starts with rtmp. This is the realtime message protocol used by FMS. The next element in the connection stream is the server ip address or dns name. After the slash following the server name or ip address is the application name. This may seem a little strange but this represents a folder name inside the application folder inside the installation folder of the Flash Media Server. Once you have the Flash Media Server installed find the installation folder and open it and inside you will find the application folder. Inside of the application folder you will find a vod and live directory. These are the default applications. If we analyze the following connection url, rtmp is the protocol, the ip address is the address of the Flash Media Server and vod represents the default directory for ondemand streams (i.e. files) inside the application directory.

rtmp://192.168.0.2/vod

The stream name is what ever the file name is for ondemand or what ever name you entered into the Flash Media Live Encoder.

Flash Media Encoder Output Panel

Flash Media Encoder Output Panel

After the all the elements of the workflow are in place it is time to turn on the camera and stream the video from Flash Media Live Encoder to FMS. This is a pretty straight forward task, simply hit the start button in Flash Media Live Encoder.

Once the live video is streaming to Flash Media Server it is time to connect to and play the live stream into the custom pod inside of Adobe Connect.

Custom Pod Settings Panel

Custom Pod Settings Panel

This is the settings panel for the Custom Pod that you will use in the Adobe Connect Meeting room. It allows you to setup and make a connection to the Flash Media Server. It also allows you to choose between ondemand and live streams and test your bandwidth. Notice that the stream name is the same as the the stream field in the Flash Media Live Encoder. If these do not match you will not see video in the custom pod. Also notice that if you want to view live video you must select the Live Stream check box.

Well I think that about covers it. I will post the link to down load the custom pod later today along with a few other links that might be helpful. Please drop me a comment to let me know if it is working or not and any improvements that you would like to see.

I put together a short overview presentation of the custom pod functionality and setup. If you would like to jump right to the link that allows you to register for download it is on slide eight. Please let me know what you think. Note: If you are having trouble with the registration page clear the cache on your browser and reload the page.


Passing Variables Into Flash using the Querystring

June 7, 2010

I decided the write this post because I have been getting numerous requests for using a simple media player (Flash) with a dynamic html page. In other words people would like to have a list of videos in html as links and when you click the link the video reference is passed into the media player (Flash) and plays the video. There are a number of ways to accomplish this task but for this example I am going to show how you can have one page pass variables to a second page via the querystring, the second page picks up the variables using swfobject and passes them into the media player.

The example files are setup so that the home.html page has the link with the name value pairs (querystring). When you run the home.html page in a browser and click the link the player.html page with load. If you look at the location field of your browser you should see something like the following:

http://localhost/passingVars/player.html?videourl=rtmp://localhost/vod/sample.flv&videocaption=just%20a%20bit%20of%20text

First notice that this is running on an http server (e.g. http://localhost). Second notice that there is a ? after player.html, the next section contains two name /  value pairs. The first starts with videourl (is the variable) then rtmp://localhost/vod/sample.flv (is the value). Next you will notice a & symbol this is the beginning of the second name / value pair. Finally videocaption is the second variable and just%20a%20bit%20of%20text is the value of that variable. The value is url encoded.

In player.html there is some javascript that picks up the variables and values from the query string and passes them into the Flash file (final.swf). The following captures both the variable name and the value:

if (swfobject.getQueryParamValue(“videourl”)) { flashvars.videourl = swfobject.getQueryParamValue(“videourl”); }


if (swfobject.getQueryParamValue(“videocaption”)) { flashvars.videocaption = swfobject.getQueryParamValue(“videocaption”)

The preceding also adds the variable names and values to to the flashvars object which makes them available to the Flash file. In the Flash file I am able to retrieve the values using the following actionscript:

var paramObj:Object = LoaderInfo(this.root.loaderInfo).parameters;

if(paramObj.videourl){
msg_txt.appendText(“\t” + “videourl : “+ paramObj.videourl + “\n”);
msg_txt.appendText(“\t” + “videocaption : “+ paramObj.videocaption + “\n”);

Then it is a simple matter to pass the value for the video uri to the FlvPlayback component. You can find and download the example here. The Flash source file is in the assets folder (final.fla). This file will require Flash CS5.


Choice!

May 18, 2010

Freedom of choice


CS5 Magic

April 11, 2010

If you have not heard or you have nothing to do with content creation on the web you can disregard this post. On the other hand if you have anything to do with content creation on the web no matter if you are a designer or a developer you are going to want to pay attention to this release.


iWhat? Check this slate out!

March 19, 2010

It is faster with a larger screen,  plays Flash content and has upgradeable memory to name a few of the advantages over its competition. No this is not a cartoon character  it is the Neofonie WePad. Never heard of them, me either but it looks like they could be a contender! Check out the specs at the bottom of the pdf located at the preceding link.


Common Sense Approach to Apple Rhetoric

March 10, 2010

All to often marketing rhetoric is mistaken for technical reality. One one hand we hear Steve Jobs tell the world that Flash does not work well on their devices and with the other hand he is making sure that it does not by denying Flash access to the ability that they retain for only their applications and technology. It is becoming more and more difficult to make these claims as the Open Screen Project is beginning to have an effect. We are starting to see the results of this effort in devices such as the up coming HP Slate. In addition there are a few people that have taken up the gauntlet and did a little research to better understand the issue. I hope you take a look but if you do not an article by Dan Rayburn summarizes the results very well:

“When it comes to efficient video playback, the ability to access hardware acceleration is the single most important factor in the overall CPU load. On Windows, where Flash can access hardware acceleration, the CPU requirements drop to negligible levels.

Overall, it’s inaccurate to conclude that Flash is inherently inefficient. Rather, Flash is efficient on platforms where it can access hardware acceleration and less efficient where it can’t. With Flash Player 10.1, Flash has the opportunity for a true leap in video playback performance on all platforms that enable hardware acceleration.

Apple complaining about Flash being a CPU Hog while not exposing “the appropriate hooks” to enable Adobe to access hardware acceleration seems disingenuous at best.”

Thanks to Dan Rayburn for the lucid approach to this political topic!


Securing Flash Media Interactive Edition

March 8, 2010

A critical component to rich media is securing your content and resources. In this article I am going to cover how to restrict someone with the Flash Media Live Encoder or for that matter any encoder from publishing to the Flash Media Interactive Server. In the process I am going to show you how to allow someone with the appropriate permissions and the Flash Media Live Encoder to publish to the server.

There are many ways to accomplish this goal. First there are Adobe partners that have written plugins for the Flash Media Server that allow you to restrict access to the server through the use of these plugins.

There are also server side APIs that allow you to connect with other systems and data. For instance you can use the WebService class to create and access a WSDL/SOAP web service or the XML class lets you load, parse, send, build, and manipulate XML.

In this short example I am going to use a server side event “onPublish” to retrieve the querystring and respond to a request to publish a live stream from the Flash Media Live Encoder to the Flash Media Interactive Server. Now there is a reason that I am calling out the Flash Media Interactive Edition and not the Streaming Edition and that is that the Streaming Edition does not support server side scripting.

Server side scripts are written and stored in “.asc” files in an application directory inside the application folder on your Flash Media Server. As an example if I had a application called foo I would store my server side script (e.g. main.asc)  in the following location.

server side script location

There are a number of events that you can work with on the server side; for instance onAppStart, onConnect, onPublish. You can find information about these and other events, methods and properties in the documentation.

Lets take a look at the final server side script in the main.asc file.

application.onAppStart=function(){
trace(“***** on App Start”);
}

application.onConnect=function(clientObj){
trace(“**** on connect”);
this.acceptConnection(clientObj);
return true;
}

application.onPublish = function(clientObj, streamObj){
logon = extractQueryString(streamObj.publishQueryString, “logon“);
if(logon != “fmle”){
application.disconnect(clientObj);
trace(“Sorry you aint publishing”);
}

}
function extractQueryString(queryString, arg){
var returnValue = “”;
temp = arg + “=”;
i = queryString.indexOf(temp);
if (i != 0){
temp = “&” + arg + “=”;
i = queryString.indexOf(temp);
}
if (i != -1){
returnValue = queryString.substr(i+temp.length);
i = returnValue.indexOf(“&”);
returnValue = returnValue.substr(0, i);
}
return returnValue;
}

In the preceding code the events are in bold. The helper function that will extract the search term (i.e. the second parameter that we pass in to the extractQueryString function called arg)  that we tell it from the querystring is green. The bit that disconnects an in appropriate publisher is red.

First let me say that this is a very simple example that should be coupled with functionality that does more to integrate with existing systems (e.g. ldap) but after many calls from customers concerned that someone might be able to publish inappropriate content or use their bandwidth I thought I would at least get the ball rolling. The part of the script in red is a great place to look at integrating with other systems. Notice that in the if statement that I am simply looking for the string “fmle” this should really be a more robust solution but it will work for this simple example.

In the preceding code onAppStart does just that it fires when the application starts. The onConnect fires when a client connects to this application. Finally onPublish fires when someone tries to publish a stream to the server.

There are two parameters the first is the client object that represents the client publishing the stream to the server. The second is a reference to the stream that the client is attempting to publish. Even though I am not going to cover it in this article it is worth mentioning that you can use the stream reference to publish a stream from one server to another in the event that you want to propagate a stream across a number of servers.

What will happen when someone tries to publish a stream to an application that has this “main.asc” in the application folder? If they do not add “logon=fmle” to the connection they will be disconnected (see script in red above).  Most people do not want to stop all Flash Media Live Encoders from publishing to their server they just want to make sure that the right users can publish to their server. In this example the way that we do that is to make sure that who ever attempts to publish to the server includes “fmle” in the querystring. This has to happen from the Flash Media Live Encoder or for that matter any encoder that you are using to publish to the server. In this example I am going to use the Flash Media Live Encoder.  The following is a screen shot of the Flash Media Live Encoder’s output panel:

Flash Media Live Encoder Output Panel

Flash Media Live Encoder Output Panel

Substitute your server dns name or ip address for localhost in the preceding screenshot. There are two elements that you need to be aware of in the preceding. First notice that “foo” is after the last forward slash “foo” represents the  application name which is the same as the name of the directory where “main.asc” is located (see first screenshot). Second notice that after the stream name there is the following “?logon=fmle” this is the querystring. This querystring is initially extracted by using publishQueryString property of the stream object (see blue script above). This represents the entire querystring which often includes other parameters. Since we are only interested in the “logon” parameter we pass the querystring to extractQueryString(see green script above). This function parses the query string and returns the term and value of the term we pass into the extractQueryString function (the term that we are passing in is logon and is the second argument in the following script:

logon = extractQueryString(streamObj.publishQueryString, “logon“);

The value of this argument will have to be “fmle” or the attempt to publish will be denied.

That should cover it. If you have questions or comments let me know. I will most likely follow this up with short article about swf verification.


Follow

Get every new post delivered to your Inbox.

%d bloggers like this: