Thursday, November 29, 2012

AMS Adobe Media Server: Getting Great RTMFP Quality

If you're new to working with Adobe Media Server (previously Flash Media Server) you may find that your video quality is not looking so great. But why?

There are several key factors involved when trying to reach the maximum video stream quality between users. By analyzing how these are implemented in your system, you will be able to tweak settings until you reach the best stream quality possible.

Before this protocol, Flash was only able to stream video using RTMP. This protocol is TCP based which means overhead for packet delivery. RTMFP uses UDP which allows for dropped packets without adverse effects. Another major improvement is that video streams are able to be streamed directly between users (P2P) and aren't relayed by the media server. This can reduce your hardware requirements possibly saving money while improving the user experience.

2. Bandwidth:
This is one of the fastest ways to kill your video quality and a factor you will have little to no control over. User's transferring video streams between each other using RTMFP bypass the server which means you only need the computing power to store their unique fingerprints and lightweight socket connections (a story for another time). This also means that the quality the user transmits is completely up to the bandwidth available to that user. If they have a shoddy internet connection or overloaded / slow internet equipment, this will quickly hamper the experience for the other user. Keep in mind that the user is uploading video data (which is typically much less available bandwidth for users than download speeds).

3. Camera Settings:
When setting up the Camera singleton to transmit data to the media server, you have a couple different options.

  • Camera Size: (Default: 160x120)
    • Try to match the same dimensions as the player showing the stream. Having this set low with a large playing area will cause gross pixelation. Likewise, having the player be smaller than the dimensions of the video feed will cause sharpness in the picture to occur. (Note: Some cameras will only output up to a certain size, after this point, Flash scales the feed causing pixelation.) Set this using setMode method.
  • Camera FPS: (Default: 15)
    • The FPS will of course determine the ideal rate as which frames in the stream are sent to the other user(s). This is only recommended as the recipients will determine if this rate is achievable with the given bandwidth and quality. Set this using setMode method.
  • Camera Quality: (Default: 50)
    • This will determine the compression applied to the frames transmitted to the other clients. Setting this to zero will prioritize bandwidth property below adjusting the quality as needed to maintain bandwidth settings. Set this using the setQuality method.
  • Camera Bandwidth: (Default: 16384)
    • The bandwidth property allows you to limit the usage of bandwidth while trying to maintain the FPS and quality settings you have determined or that exist by default. Setting this to 0 will prioritize the quality of the frames while reducing FPS to maintain constant streaming. Set this using the setQuality method.

By tweaking these settings and using your existing user analytics (and your preferences), you should be able to calculate the best values for each of these settings.

While there is no way to 100% ensure perfect picture and high quality streaming between users, tweaking the settings above will help you get the most out of it and give your users the best possible experience.

Saturday, November 24, 2012

Dynamic Application Instances - AMS Adobe Media Server / FMS Flash Media Server

While playing around with Adobe Media Server and writing an application for it, I wanted to figure out how to add dynamic applications with custom instance names. I looked through the Administration API trying to figure out how to dynamically generate new application instances (which I refer to as rooms).

The solution was right under my nose the whole time, turns out all you need to do is specify the context when connecting to the application on AMS (even without the application running) and it will create that application with the instance name you provide.

For example
This will connect the to application:
netconnectionvar.connect("rtmp://localhost/chat", params);

And this will create a new instance of the chat application:
netconnectionvar.connect("rtmp://localhost/chat/instancename", params);

Hopefully this will save you quite a bit of time.

Friday, November 16, 2012

AMS Adobe Media Server / FMS Flash Media Server - Reset Administrator Password

Working with Adobe Media Server (used to be called Flash Media Server), I had a situation in which I couldn't seem to remember my admin password.

This turned out to be a pretty simple fix. If you go to where your Adobe Media Server is installed you will find a program called AMSAdmin.exe (or fmsadmin.exe). By entering in this command, you will be able to type in your new password.

$ amsadmin -console -u username

Wednesday, November 7, 2012

AS3 TextConverter.importToFlow Explained

Working on a WYSIWYG type editor for a project, I found myself needing to import and export raw TextLayoutFormat in string format (vs XML) for use in transport. When obtaining the string data and using it within an import, I found myself not quite sure how to use the returned TextFlow object.

This is how I solved the problem. First I used the importToFlow passing along my string, and specifying that it was in the TEXT_LAYOUT_FORMAT, and the configuration file I wanted the TextFlow to have (since it is only read-only following object construction).

var flow:String = TextConverter.export(textFlow, TextConverter.TEXT_LAYOUT_FORMAT, ConversionType.STRING_TYPE) as String;
var _textFlow:TextFlow = TextConverter.importToFlow(flow, TextConverter.TEXT_LAYOUT_FORMAT, configuration);

Now I found myself with two TextFlow objects, one which was the original connected to several controllers, and implemented with many event listeners, and so on. I actually had two problems.

Problem 1: The data string which I assumed had textflow structure within it, was empty. An empty string will fire an error, so be sure the string data is properly formatted and not empty.

Problem 2: Simply replacing my orginal TextFlow object with my new one meant that all my existing attribute would be lost.

I ended up creating a method called setupTextFlow which would take a TextFlow instance and apply all the listeners I wanted, as well as would loop through a dictionary of existing containers and reconnect them, and then finally set it to update all controllers.

Side Note: I wish I could just set the TextFlow object to contain my new data, but I couldn't find any methods that would allow me to just replace contents. replaceChildren almost seems to work, but I couldn't find a way to access all the children elements of the TextFlow for replacement.

Saturday, November 3, 2012

FFserver / FFmpeg Error : This feed is already being received.

It has been a while since I have done much with ffmpeg (and I've never worked with ffserver). So when streaming a resource over my network, I was trying to get the browser to play the video natively. When I went to the browser and typed in the URL: I got the following error:

This feed is already being received.

Looking back at the ffserver conf file, I noticed there was a feed and a stream. To get the data to stream properly, I needed to use the Stream address which was canon.mjpeg. Once I had modified this, I was able to begin streaming the video data.

Coming Soon:
I'm working on a device (using raspberry pi) that will stream live video feeds over the internet for under $100. Stay tuned to see that research posted.