Playing Video File from Limelight Secured URL
We worked on a project that utilized 360° panorama viewer, called PanoSalado, and ran into an issue with streaming video from Limelight, a popular CDN service.
PanoSalado renders one more more video sources by capturing the bitmaps and laying them “flat” allowing user to pan and zoom. For this project, our video source (encapsulated by a class called VideoSource) contains an instance of FLVPlayback. This is a standard Flash class for playing flv videos. To use it to play an flv file, one can simply call its load function.
var videoURL:String = “http://blabla.vo.llnwd.net/bla/bla/abc.flv”;
_video.load(videoURL);
_video is an instance of FLVPlayback. And the core of FLVPlayback is a class called VideoPlayer.
Now, here’s the issue. When we assign videoURL with Limelight secured url that has expiration time (ie., the flv is accessible for X minutes after it’s first available), FLVPlayback stops working. For some reasons, it doesn’t like the secured URL which has the following format:
http://blabla.vo.llnwd.net/bla/bla/cde.flv?e=…&h=…
The extra parameters after .flv are necessary for Limelight to recognize the validity of the request. Without them, cde.flv is not accessible.
To address this issue, we have to find out its root cause. When load function is called, FLVPlayback passes the call to VideoPlayer which then utilizes NCManager class to, among other things, validate the URL and determine its protocol (progressive vs. streaming/RTMP). What makes the request to secured URL break is the fact that NCManager only considers files with “.flv” postfix a valid non-streaming file. This check occurs in connectToURL function inside NSManager.as:
public function connectToURL(url:String):Boolean {
…
if (… parseResults.streamName.slice(-4).toLowerCase() == “.flv” ) {…
Okay, now that we know the cause, it’s fairly straightforward to come up with the fix. What we need is a custom NCManager which will allow the limelight secured url format. We created a class call LimelightNCManager and it looks like this:
public class LimelightNCManager extends NCManager
{
public var LIMELIGHT_ID:String = “llnwd.net”;
override public function connectToURL(url:String):Boolean {
var ret:Boolean;
// if this is limelight url, we assume it’s an http…
if (url.indexOf(LIMELIGHT_ID)>0 &&
url.indexOf(“http://”)>=0 &&
url.indexOf(“?”)>0) {
// init
initOtherInfo();
_contentPath = url;
// parse URL to determine what to do with it
var parseResults:ParseResults = parseURL(_contentPath);
var name:String = parseResults.streamName;
var canReuse:Boolean = canReuseOldConnection(parseResults);
_isRTMP = false;
_streamName = name;
ret = (canReuse || connectHTTP());
}
else
ret = super.connectToURL(url);
return ret;
}
}
Once we have this class ready, we need to let VideoPlayer know and use it to manage network communications. Otherwise, VideoPlayer will continue to use NCManager. VideoPlayer exposes a static property called iNCManagerClass. To replace NCManager with our custom class, we simply assign the property to the definition of the custom class. We have to do that prior to calling the load function. Here’s the code snippet:
fl.video.VideoPlayer.iNCManagerClass = LimelightNCManager;
_video.load(videoURL);
Now, the video will play just fine even when videoURL is in Limelight secured url format.
1 Comment