OSMF Fix: “Local HDS” Playback

OSMF & Local F4M Files

The Open Source Media Framework (OSFM) doesn’t respond well when you pass it a local F4M file path for playback. Playing back local HDS fragments is an edge case, but enough people have encountered this problem that I think it deserves a little attention.

Fixing the IndexHandler

The basics involve extending the HTTPStreamingF4FIndexHandler then overriding the constructFragmentRequest() method & removing the requirement that HTTP be part of the URI.

So, after you’ve created your new class that extends org.osmf.net.httpstreaming.f4f.HTTPStreamingF4FIndexHandler, add the following override:

[actionscript3]override protected function constructFragmentRequest(serverBaseURL:String, streamName:String, segmentId:uint, fragmentId:uint):String
{
var requestUrl:String = "";
requestUrl += streamName + "Seg" + segmentId + "-Frag" + fragmentId;
return requestUrl;
}[/actionscript3]

The original constructFragmentRequest() method looks like:

[actionscript3]protected function constructFragmentRequest(serverBaseURL:String, streamName:String, segmentId:uint, fragmentId:uint):String
{
var requestUrl:String = "";
if (streamName.indexOf("http") != 0)
{
requestUrl = serverBaseURL + "/" ;
}
requestUrl += streamName + "Seg" + segmentId + "-Frag" + fragmentId;
return requestUrl;
}[/actionscript3]

So you can see we just removed the “http” requirement.

Now you need to get OSMF to use your adjusted IndexHandler. This means you need to create a custom NetLoader, that creates a custom StreamingFactory & then the Factory creates your IndexHandler. Once you have all of this done, you can then create a custom MediaFactory (I usually just extend DefaultMediaFactory) and create a MediaFactoryItem that can handle your local F4M file resource, & specify your new NetLoader for the element that is returned.

Convoluted eh? Let’s break it down.

Creating the Factory

Since we are dealing with HDS content extend org.osmf.net.httpstreaming.f4f.HTTPStreamingF4FFactory & override the createIndexHandler() method. In this method set the indexHandler property equal to an instance of your IndexHandler (mine is named “LocalFileStreamingF4FIndexHandler”).

Example:
[actionscript3]override public function createIndexHandler(resource:MediaResourceBase, fileHandler:HTTPStreamingFileHandlerBase):HTTPStreamingIndexHandlerBase
{
indexHandler = new LocalFileStreamingF4FIndexHandler(fileHandler);
return indexHandler;
}[/actionscript3]

Creating a NetLoader

Now we need our NetLoader – this is where the Factory is created. I extended org.osmf.net.httpstreaming.HTTPStreamingNetLoader & created an override for the createHTTPStreamignFactory() method.

Example:
[actionscript3]override protected function createHTTPStreamingFactory():HTTPStreamingFactory
{
return new LocalFileStreamingF4FFactory();
}[/actionscript3]

Creating a custom MediaFactory

Now we need to be able to injet this NetLoader into the system. So extend the org.osmf.media.DefaultMediaFactory & add a MediaFactoryItem that return a new VideoElement. Pass in an instance of your NetLoader to the the VideoElement constructor.

Example:
[actionscript3]localFileStreamingNetLoader = new LocalFileStreamingNetLoader();
localHDSFileNetLoader = new LocalHDSContentNetLoader();
addItem( new MediaFactoryItem( "com.realeyes.osmf.elements.video.httpstreaming", localHDSFileNetLoader.canHandleResource,
function():MediaElement
{
return new VideoElement(null, localHDSFileNetLoader);
}
)
);[/actionscript3]

Specifying the canHandle and passing in the NetLoader

You can also see in the previous bit of code that the MediaFactoryItem asks for a canHandleResource function. This is where conditions are added to make sure the you’re working with the right type of media. For this situations you can default to the super’s canHandleResource() which checks the resource HTTP Streaming metadata.

Now you have a setup that can handle a local F4M file and the downloaded fragments. There are a couple of considerations you’ll need to keep in mind:

  1. The fragments and F4M file must reside in the same directory. OSMF looks for the fragments in the directory that they F4M is in.
  2. Multi-bitrate won’t work, unless you can download the fragments for all the bitrates and work out storage for them.

The provided examples is the least obtrusive way to get local HDS content to play. Alternatively  you can edit the HTTPStreamingIndexHandler and compile an OSMF swc to use for a quick and dirty fix.

15 Replies to “OSMF Fix: “Local HDS” Playback”

  1. Hey John, This is exactly what I'm trying to do, but I'm unfortunately having trouble implementing your directions. Is there any chance you'd be willing to share the source to properly override all of these classes? Thanks, Jordan

  2. Hi John,

    I've pretty much got this working now I think – great solution – except…I'm stuck at the last hurdle! Doh! Is there any hope you'd be willing to post your source code for this so us mere mortals can get this fix working please? 🙂

    cheers!

    Chris

  3. Hi John,

    to clarify my above comment – I'm actually finding a problem with the IndexHandler, the streamName appears to be incorrect, I keep getting a Stream not found media error from the core of the player, tracing out request URL is in the format:

    streamname/mainfest filename/streamnameSeg1-Frag1

    and it can't seem to find the fragment…any thoughts on this at all? The folder containing the manifest and fragments is in the same directory as the player SWF…

    Cheers again for any help you might be able to provide

    Chris

    1. Chris, the path looks correct to me for HDS content, do you have the fragments locally or just the manifest file? OSMF expects the fragments (the files with the streamnameSeg{#}-Frag{#}) to be in the same directory as the manifest file.

      There are a couple of ways you can get the Fragments – the simplest is to inspect the HTTP calls (Firebug or charles) when a player is playing back the HDS content & then download the files – that is pretty manual though. Another was is to extract the fragments from the packaged content. This involves parsing through the segment files created when packaging the content and pulling out the fragment data – essentially reproducing what the HTTP Origin Module does. The file spec for F4V (http://www.adobe.com/devnet/f4v.html) has the necessary info to parse through the segment files.

      Hope that Helps – John

      We have built a tool to extract the fragments that was up on the now defunct Adobe Marketplace and have yet to get the app up somewhere it can be purchased.

  4. Hi John,

    I've got all the segment .f4f and.f4x files locally, so – (ray of light starts to appear in my head), I need the fragments, NOT the segments in the same directory as the manifest file.

    Also, to be *even* more specific about the path being parsed b the IndexHandler, it's:

    streamname/manifestfilename.f4m/streamnameSeg1-Frag1

    so the path actually contains the manifest file extension along with the name, I'm not sure if that's supposed to be the case or not? Seems a little odd though…

    Cheers for the reply, much appreciated!

    Chris

    1. Yep – fragments are the key. You're right the .f4m in the path doesn't look right. I'm not sure why it would be keeping that around. What version of OSMF are you using?

      1. That might be part of the issue, I haven't testing the local playback with 2.0 much – I've been working wtih 1.6. I'm sure they changed something that broke the path for local content. Oh joy.

  5. Actually, as a thought – is there any way I could get some more info on the F4Fragment Extractor – is it an Air app, or a native runtime program – and how would I go about purchasing it off you, etc etc?

    Yet more thanks (running out of interesting ways of being flattering!)

    Chris

    1. Ha! Thanks.
      If you wouldn't mind emailing me (john [AT] realeyes.com) a little info about the project you're working on, I'm sure we can work something out with the extractor.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.