Jul 9, 2008 4:12 AM
FLVPlayback / Custom NCManager Problems
-
Like (0)
Hi,
I'm trying to do the same thing (creating a custom NCManager by extending NCManager) to work with live streams and Limelight. I have already written a completely custom class two years ago that works, but I am trying to do the same thing... use FLVPlayback and base everything off of it. You said you had posted some code that demonstrated how to do this, but I'm not seeing it?
If you don't mind sharing it, it would really help out a lot.
Regards,
Sean Smith
Hi,
Do you have your code for working around this? You mentioned posting it, but it does not appear to be here. I've run into the same issue and could use the help.
I was able to successfully make this work for our company's Adobe Flash video player using Flex Builder 3 running the Flex 3.3 SDK with the latest version of FLVPlayback 2.5.
Here is the custom NCManager class I created:
package com.companyname {
use namespace flvplayback_internal;
import fl.video.*;
import flash.net.NetConnection;
public class NCManagerLimelight extends NCManager {
public function NCManagerLimelight() {
super();
}
override flvplayback_internal function onConnected(p_nc:NetConnection, p_bw:Number):void {
super.onConnected(p_nc, p_bw);
this.netConnection.client = com.companyname.ConnectClientLimelight;
this.netConnection.call("FCSubscribe", null, this.streamName);
}
}
}
As you can see, it references a custom ConnectClient class I extended, which follows:
package com.companyname {
use namespace flvplayback_internal;
import fl.video.*;
import flash.net.NetConnection;
public class ConnectClientLimelight extends ConnectClient {
public function ConnectClientLimelight(owner:NCManager, nc:NetConnection, connIndex:uint=0) {
super(owner, nc);
}
public function onFCSubscribe(info:Object):void {
// do nothing
}
public function onFCUnsubscribe(info:Object):void {
// do nothing
}
}
}
The above class really does nothing except prevent the debug errors it would throw if onFCSubscribe was not defined. Finally, you put it all together by placing those two files (named NCManagerLimelight.as and ConnectClientLimelight.as respectively) in a folder structure that matches your package namespace off of the src folder for your Flex project. In the above code, I used com.companyname, so you would want to place the two files in a folder located at src/com/companyname in your Flex project.
Be sure to import the NCManagerLimelight class in your own source code by doing the following:
import com.companyname.NCManagerLimelight;
Then, right before you instantiate your FLVPlayback (where isLive is set to true for a live show) do the following to make your new NCManager class the default class for all video players:
VideoPlayer.iNCManagerClass = NCManagerLimelight;
Lastly, after you instantiate your FLVPlayback instance, you need to make sure it's isLive and autoPlay properties are both true. For example:
flvPlaybackInstance.autoPlay = true;
flvPlaybackInstance.isLive = true;
I hope this helps!
Regards,
Sean Smith
Thank you. Hopefully this will work for Akamai as well as Limelight. If I have to make any changes to the code, I'll post them. With an Akamai connection, the (considerably out-of-date) documentation claims you wait until FCSubscribe returns NetStream.Play.Start to create your NetStream object and begin playback, which I am hoping is not actually the case.
Actually, that sounds pretty much exactly how Limelight's documentation defines the procedure and the above example I posted works fine for me. I'm pretty sure you don't receive the NetStream.Play.Start response from the live FMS server until after you've called the FCSubscribe method. Once the FLVPlayback component receives this, it should begin to play automatically assuming you remembered to set the autoPlay property to true. On a side note, I could ONLY get this to work with the autoPlay property set to true. For some reason, FLVPlayback did not want to fire the buffering or playing events if it was not set to auto play, although I could hear the audio from the stream in the background (the video container was not visible at the time so I'm not sure about whether you can see it or not).
Also, on another side note, I'm pointing the source property of the FLVPlayback component to a SMIL file on our web server. However, I don't think this should make any difference whether you're using a single live stream or multiple streams, such as through a SMIL file. The NCManager class should take care of any connection, at least to my knowledge...
It looks like I messed something up, so I'm going to add a bunch of trace statements and see if I can figure out what is going wrong.
I do the following in my FLVPlaybackController:
fp.autoPlay = true;
fp.isLive = true;
fp.source = qs.vidURL;
Before you set those properties, and even before you create your instance with something like fp = new FLVPlayback();, did you remember to do this part?
VideoPlayer.iNCManagerClass = NCManagerLimelight;
What exactly is not working for you? The first thing I usually do when I run into problems is trace each video event. I would also throw a trace into the custom NCManagerLimelight class, immediately after the FCSubscribe call to make sure that it's going through that part of the code.
Also, if you are doing a single RTMP stream, you may have to play around with the structure to get it to work. Sometimes you have to include _definst_ in the stream path so it knows what part of the path is the stream name. For example, if this doesn't work:
rtmp://companyname.someserver.akamai.com/companyname/streamName
Try doing something like:
rtmp://companyname.someserver.akamai.com/companyname/_definst_/streamN ame
I did, but it looks like I needed to add it to the first frame of the .fla file instead. It is working now, thanks! Now I just have to track down and fix the following so no errors are thrown.
Error #2044: Unhandled NetStatusEvent:. level=error, code=NetConnection.Call.Failed
at fl.video::NCManager/http://www.adobe.com/2007/flash/flvplayback/internal::connectRTMP()
at fl.video::NCManager/connectToURL()
at fl.video::VideoPlayer/http://www.adobe.com/2007/flash/flvplayback/internal::_load()
at fl.video::VideoPlayer/load()
at fl.video::FLVPlayback/doContentPathConnect()
at fl.video::FLVPlayback/set source()
at fl.video::FLVPlayback/load()
at FLVPBController/setUp()[C:\Documents and Settings\nathan\Desktop\FlashFiles\spruceplayer_updated\FLVPBControll er.as:121]
at FLVPBController()[C:\Documents and Settings\nathan\Desktop\FlashFiles\spruceplayer_updated\FLVPBControll er.as:74]
at SkinControl/setUp()[C:\Documents and Settings\nathan\Desktop\FlashFiles\spruceplayer_updated\SkinControl.a s:249]
at SprucePlayer_fla::MainTimeline/frame1()[SprucePlayer_fla.MainTimeline ::frame1:275]
Yeah, sorry can't help you with that one... I'm more of a Flex person myself.
Never really cared much for the Flash IDE way of doing things. Glad I could help and good luck debugging! ![]()
- Sean
I figured it out -- there were several spots I could put the NCManagerLimelight line in and I just had to find the absolute first initialization. I also added a switch to use the standard NCManager if the player is using on-demand rather than live. I may add in something to return the information from FCSubscribe, but that can wait.
I've just started learning Flash, and everyone else here uses the Flash IDE, so it was easier going that route than using Flex (otherwise, I'd have to completely redesign our existing codebase). I write my AS files in FlashDevelop, but have to open .fla files in CS4.
Thank you for all of your help. Once it was working, it turned out to be so simple!
Yeah, that's pretty much what my player is doing right now too (using NCManager for on-demand). However, once Limelight has enabled FMS 3.5 for our on-demand content (I'm hoping sometime next week), I am going to only have it set it to the custom class for live shows and use the NCManagerDynamicStream (default) class for FLVPlayback! ![]()
Again, glad I could help. This was one of those problems that I could absolutely not find a solution for online, so I was more than happy to provide one. Good luck and happy coding.
- Sean
Just wanted to provide an update... the previous solution I had posted does not work with live dynamic streaming that is provided with FMS 3.5. However, after doing some beta testing, it appears that the following will work. In fact, very little had to change -- I changed the classes that were being extended from NCManager and ConnectClient to NCManagerDynamicStream and ConnectClientDynamicStream respectively and changed the code that makes the FCSubscribe call so that it would call it immediately upon connection for each defined stream name in the dynamic stream list.
Here is the new code for the custom NCManager class:
package com.companyname {
use namespace flvplayback_internal;
import fl.video.*;
import flash.net.NetConnection;
public class NCManagerLimelight extends NCManagerDynamicStream {
public function NCManagerLimelight() {
}
override flvplayback_internal function onConnected(p_nc:NetConnection, p_bw:Number):void {
super.onConnected(p_nc, p_bw);
this.netConnection.client = com.companyname.ConnectClientLimelight;
for (var x:uint = 0; x < this.streams.length; x++) {
// Call FCSubscribe for all available streams
this.netConnection.call("FCSubscribe", null, this.streams[x].src);
trace("FCSubscribe: " + this.streams[x].src);
}
}
}
}
And the new custom ConnectClient class:
package com.companyname {
use namespace flvplayback_internal;
import fl.video.*;
import flash.net.NetConnection;
public class ConnectClientLimelight extends ConnectClientDynamicStream {
public function ConnectClientLimelight(owner:NCManager, nc:NetConnection, connIndex:uint=0) {
super(owner, nc);
}
public function onFCSubscribe(info:Object):void {
// do nothing
}
public function onFCUnsubscribe(info:Object):void {
// do nothing
}
}
}
Copyright © 2011 Adobe Systems Incorporated. All rights reserved.
Use of this website signifies your agreement to the Terms of Use and Online Privacy Policy (updated 07-14-2009).