FMS, Live Streaming and Sync Between Publisher and Subscribers

Here I would like to discuss the FMS, Live Streaming and Sync issues between publisher and subscribers. Also I would discuss about possible solutions 🙂

The problem: Let’s say we are publishing a live stream using FMLE (Flash Media Live Encoder) or our custom publisher to FMS (Flash Media Server). There are 5 subscribers who are watching this live stream (given that those subscribers connected to stream after the stream has been already published). Now NetStream.time will not give absolute stream time for any of the subscriber connected to live stream because it gives time since the playback of live stream is started by subscriber. Now let’s say I (as a publisher) want to take certain action (such as displaying an image, or some message, or slide) on subscribers on specific point of time (in terms of viewing the live stream). Let’s say from publisher side, when I see (or speak) something (a tortoise in scene!) on screen, I want to show another picture of that same thing to all subscribers (dancing tortoises!) exactly at the same time when each one of them see tortoise on their live stream.

SharedObject can not be used because that will not provide any kind of sync (in terms of live streaming) because they are asynchronous and live streams may get delayed due to slow bandwidths on subscribers.

Even we can not directly call a function on FMS which would in turn call functions to all subscribers because that process would be instantaneous (compared to delay in live stream) and if there are number of subscribers this process may hang FMS (and publisher) application for a fraction of second.

The Solutions:

1) Somehow give all subscribers the absolute stream time. This would be an ideal solution but not easy. From FMLE, I managed to find a solutions and that is timecode. Let’s say if the publishing video frame rate is 15 fps then FMLE would encode a keyframe at each group of 15 frames (given that timecode interval is same as frame rate of video). Now the timecode is embedded as system time and date which we need to take care of. The condition here is the video must be recorded on server so that we can know the start time of publishing. On subscribers we get onFI() event at each 1 second which would give you current date and time. From this current time subtract the initial time (which is found by playing recorded stream) and that would give you absolute live stream time 🙂

2) Another way is kind of events instead of focusing on time but yet it keeps solid track of sync. From publisher side, call NetStream.send() function along with necessary parameters. This will actually embed metadata on current frame being encoded. When subscribers get this frame, they get the embedded event and they can take the necessary action by analyzing the data given in that event. Usually I would prefer to use onMetaData event for this stuff 🙂

Phue! It’s been late night now (1:43 AM already) and I am going for sleep now. If any one have any questions, post me a comment and I will be back there right away 🙂

Thanks, Naresh

Set TextField horizontal scroll to initial position

If you want to set the position of horizontal scroll position inside TextField, you can use TextField.scrollH.

Let’s say I am typing in the input TextField and I typed beyond the width of TextField. You will see the last characters visible you typed. Now due to some other event, say user clicks on other than this TextField, focus is changed to some other object than this TextField, you may want to reset the scroll position of TextField to starting characters in it.
You will use :
TextField.scrollH = 0;

This will set the horizontal scroll of TextField to 0 and hence showing the starting characters in TextField.

Built-In Context Menu Items on Flash TextField

Is there any way to hide default context menu items on Flash TextField? Some one will try to answer with ContextMenu.hideBuiltInItems() function, but this function does not really work with Flash TextField. It does not hide the built in items.

So following code does work but not as expected ::

var myContextMenu:ContextMenu = new ContextMenu();
myContextMenu.hideBuiltInItems();

var txt:TextField = new TextField();
txt.contextMenu = myContextMenu;
addChild(txt);

Now if you right click on TextField then you will see that you can see all the built in item. Any one knows why?

Flash Player 10 Release Candidate

On August 11, 2008, Adobe released Flash Player 10 Release Candidate. This version has only one update from last Beta update and that is NSS, i.e. Flash Player 10 for Linux now supports Mozilla’s Network Security Services(NSS) for secure network connections.

You can find more information about this on adobe labs over Flash Player 10 release notes.

Flash: TextField.htmlText and Automatic Line Breaks

Problem :: When you deal with TextField.htmlText don’t append any html strings directly to htmlText property of TextField. Because the TextField appends “<br>” tag automatically before it appends any html string to htmlText property, it will set your string automatically in next line instead of the current line. This mistake is done to save memory as we don’t have to create a temporary string.

Example :

textField.htmlText = “”;                 //clear any previous texts

for(var i:uint = 0; i < 3; i++)
{
var str:String = “”;
str += “Hello World”;
str += “<br>”;                    //As you’re thinking of breaking line from here
textField.htmlText += str;
}

//output would be something like following ::
Hello World
//This line break because of <br> tag
Hello World         //This is an automatic line break
//This line break because of <br> tag
Hello World         //This is an automatic line break
//output finished

Possible Solution :: Create an empty string and append all the html strings to this string. When the final string is ready, assign this string to htmlText property of TextField. This will not create any unnecessary line breaks inside TextField.

Example :

textField.htmlText = “”;                 //clear any previous texts
var htmlStr:String = “”;                  //Temporary empty string

for(var i:uint = 0; i < 3; i++)
{
var str:String = “”;
str += “Hello World”;
str += “<br>”;                    //As you’re thinking of breaking line from here
htmlStr += str;
}

textField.htmlText = htmlStr;

//output would be something like following ::
Hello World
Hello World
Hello World
//output finished

Hope this would prevent someone from mistakes which I did 🙁

Ans: ActionScript 3.0 Object class Quiz

And here is the answer to quiz ::

undefined                                   //as property ‘prop1’ is not defined in obj2 and we pointed obj1 to obj2

Khokhaneshiya                          //now we defined ‘prop1’ in obj1 and set value ‘Khokhaneshiya’

//also obj2.prop1 will be Khokhaneshiya… You can trace out 🙂

What you were thinking? 🙂

ActionScript 3.0 Object class Quiz

Check following code ::

var obj1:Object = new Object();
obj1.prop1 = “Naresh”;
obj1.prop2 = “Khokhaneshiya”;
var obj2:Object = new Object();
obj2.prop2 = “Hello world”;
obj1 = obj2;
trace(obj1.prop1);
//What will be output here
obj1.prop1 = “Khokhaneshiya”;
trace(obj1.prop1);
//What will be output here

Be honest, Don’t trace it out using Flash.

You will have answer in following posts !

AIR and Network Detection

We can detetct the network in AIR using following code ::

Need to use ‘ServiceMonitorShim’ complied clip from AIR components in your fla file.

import air.net.URLMonitor;
import flash.net.URLRequest;
import flash.events.StatusEvent;
var monitor:URLMonitor;
monitor = new URLMonitor(new URLRequest(‘http://192.168.0.57’));
monitor.addEventListener(StatusEvent.STATUS, announceStatus);
monitor.start();
function announceStatus(e:StatusEvent):void
{
         trace(“Status change. Current status: ” + monitor.available);
}

Email Validation in ActionScript 3.0 using RegExp

You can use following function for validation of email using ActionScript 3.0 RegExp class.

/**
* @usage    Check if the given email address string is valid or not
* @param    email:String    Email address string that is to be checked
* @return    Boolean        Returns true if valid email, false otherwise
*/
public function isValidEmail(email:String):Boolean
{
var emailExpression:RegExp = /^[a-z][\w.-]+@\w[\w.-]+\.[\w.-]*[a-z][a-z]$/i;
return emailExpression.test(email);
}

Hope it would be useful to someone 🙂

Regards,

Naresh Khokhaneshiya