Diving into programming ScribeLive, the 2.0 version â?? which is being done entirely in Flex â?? Iâ??ve run into the problem of not being able to pull in the Limelight video stream properly. I was banging my head against the wall â?? since I was capable of pulling in a live stream into Flex from our own FMS server, but any attempt to pull in a stream from Limelight would result in frustration.
Looking at older code I could see that the FCSubscribe was being polled – but I couldnâ??t understand why the new code in Flex not using this FCSubscribe would work with our own FMS servers, but not with Limelight.
I tried looking up what the problem could be via google but found nothing. I asked the flexcoders list but was pretty much ignored. Through searching Flex blogs, I found John C Bland II, who recently left Limelight as an AS3 coder.
John was kind enough to explain to me that the real problem was how FCSubscribe works with Edge Servers:
A normal FMS install is just a straight up 1 server install. A CDN install uses edge servers which means there is an origin server with many other servers on the â??edgeâ? that communicate back to the origin. In order to connect to the proper stream, an FCSubscribe has to be called. That call basically calls the edge server which does a â??searchâ? to find the stream. Thatâ??s why you have to do the â??timerâ? trick to continuously ping to see if the server found the stream yet. My method isnâ??t a timer. It is with â??connected callsâ?. So, try to connect (subscribe), if it fails, wait 1 second (setInterval) and subscribe, if it fails, wait 1 second again and subscribe. Do that over and over until the maximum amount of connects is reached. Of course before each setInterval I clearInterval so I donâ??t have multiple running at once. You get a pretty much immediate response from the server so you can get away with firing off multiple setIntervals/subscribes but it could get hairy. I prefer to try and only try again if it fails (with a 1 second pause between the retries).
Kind enough to show me some example code, I changed it just a tad to fit in the way I was calling it (and I believe Iâ??ll make it into a subcomponent as part of the cleanup:
private var connection:NetConnection;
private var stream:NetStream;
private var video:Video = new Video();
private var vidTimer:Timer;
private var _fcSubscribeCount:int = 0;
private var _fcSubscribeMaxRetries:int = 3;
private var _fcSubscribeInterval:Number;
public function videoInit():void {
connection = new NetConnection();
connection.client = this;
connection.addEventListener(NetStatusEvent.NET_STATUS, videoStatusHandler);
connection.addEventListener(SecurityErrorEvent.SECURITY_ERROR, vidSecurityErrorHandler);
connection.connect(streamURL);
}
private function subscribe():void{
connection.call(â?FCSubscribeâ?, null, streamName);
var nsClient:Object = {};
nsClient.onMetaData = ns_onMetaData;
}
public function onFCSubscribe(info:Object):void{
switch(info.code){
case â??NetStream.Play.StreamNotFoundâ?:
clearInterval(_fcSubscribeInterval);
if(_fcSubscribeCount >= _fcSubscribeMaxRetries){
_fcSubscribeCount = 0;
}else{
_fcSubscribeCount++;
//subscribe failed; wait 1 second then try again
_fcSubscribeInterval = setInterval(subscribe, 1000);
}
break;
case â??NetStream.Play.Startâ?:
_fcSubscribeCount = 0;
clearInterval(_fcSubscribeInterval);
connectStream();
break;
}
}
private function videoStatusHandler(event:NetStatusEvent):void {
//Alert.show(event.info.code);
switch (event.info.code) {
case â??NetConnection.Connect.Successâ?:
subscribe();
break;
case â??NetStream.Play.Startâ?:
//Alert.show(â?netstream play startâ?);
break;
case â??NetStream.Play.StreamNotFoundâ?:
//Alert.show(â?Stream not found: â? + streamName);
break;
}
}
private function vidSecurityErrorHandler(event:SecurityErrorEvent):void {
Alert.show(â?securityErrorHandler: â? + event);
}
private function connectStream():void {
var nsClient:Object = {};
nsClient.onMetaData = ns_onMetaData;
stream = new NetStream(connection);
stream.addEventListener(NetStatusEvent.NET_STATUS, videoStatusHandler);
video.attachNetStream(stream);
stream.play(streamName);
stream.client = nsClient;
uic.addChild(video);
uic.addEventListener(ResizeEvent.RESIZE, resizeVideo);
video.width= uic.width;
video.height = uic.height;
}
private function resizeVideo(ev:ResizeEvent):void{
video.width = uic.width;
video.height = uic.height;
}
** originally posted at scribemedia