Most of url path in OSMF assumes the standard as it covers most of cases. As you said you can take the approach to extend the NetConnectionFactory (also look at FMSUrl class) or you might write your own plugin to interpret your own server/video path.
curious, Is any reason behind you wanted to do non standard way?
I need to do it like this, because this is just how our cdn is/works.
Extending NetConnectionFactory is easy enough I guess, but I also need to figure out how to get my own play trait in there somehow to handle the netStream.play(). Why aren't the net stream traits exposed in the lib again ( org.osmf.net.NetStream*Trait -> [ExcludeClass] ) ?
That seems like a lot of work just to split a string in a different place. I'm pretty disappointed this isn't easier to do. Can we look at ways to make this easier in an upcoming release?
The FMSUrl (which btw, is excluded from lib as well) being more involved seems a bit more flexible, no? Wasn't it more involved in some of the early, pre-rc sprint drops?
Thanks for your input. Your feedback would a great help in evaludating our OSMF netStream work flow.
Can you file this as request enhancement with your details (why you would need the net stream trait to be flexibla and how make it easier for you) ?
Have you considered to make it into a plugin? It might be helpful to look at AkamaiStreamingPlugin from perspective of yours.
AFAICT, there is nothing advantageous (as far as the workflow goes) with creating a plugin... I still need to figure out how to do it ( what to extend, what to override, etc ) before I can create a plugin out of it.
And thank you, I will put details into JIRA.
Here is what I had to do. Let me know if any of these steps could be done more easily.
1. Extend org.osmf.net.NetConnectionFactory
You must override createNetConnectionURLs() method to return Vector containing fms host urls the way you want them.
- Wanted to use buildPortProtocolSequence() method, but it's private. Had to dupe that functionality.
- Would be more ideal to just override buildConnectionAddress method, but it's private as well.
- There are a lot of useful const's as well in NetConnectionFactory (protocol strings, ports), but they too are private.
2. Use your factory
Pass instance of your netConnectionFactory to loader constructor when creating your media element. Now you can connect to FMS servers correctly, but can not play the correct resource.
3. Create your own 'play' trait
The 'play' trait is what actually calls netStream.play*() method, and org.osmf.net.NetStreamPlayTrait is what the VideoElement uses. I encountered a few problems/annoyances here...
- NetStreamPlayTrait is hidden in .swc using [ExludeClass]/@private. It's there, but you won't get hints or autocompletion in FlashBuilder.
- The playStateChangeStart() method is where the streamName gets figured out, so I initially wanted to just extend NetStreamPlayTrait and override that method. You would have to dupe all the functionality in the that method in the override, and the functionality relies on a lot of private fields and methods. No go there. You end up basically having to totally recreate your own play trait from scratch!
- A MUCH easier approach would have been an overridable method getStreamName(url) in NetStreamPlayTrait. Or call some sort of (overrideable) factory instance method to get stream name... not an untouchable static method. Same goes for play arguments too. You're F'd in the same way if you want different play args than NetStreamUtil.getPlayArgsForResource() gives you.
4. Extend the VideoElement, so you can add your new play trait in
You need to override the processReadyState() method and add your new play trait - to the load trait (?), not the media element - BEFORE you call super.processReadyState().
Thanks John for taking time to detail this out.
I'll have the team look at your concern to see what we can improve in custom stream urls.
I would add that it's just as "painful" (or even impossible) to (nicely) extend the behavior for regular urls (like http).
My use case is like a custom "protocol" that get resolved into an http url (think YouTube with a preliminary phase of loading more params for the final url to be constructed and loaded).
I ended up extending NetLoader, putting most of the logic in executeLoad(). The rest (of NetLoader) is then useless to me. It seems like extending LoaderBase would seem more appropriate (but can't because of the constructor signature for VideoElement)
I like the architecture a lot (with traits, clear separation of concerns, event based, etc.) but it seems the implementation is a little "off".
- VideoElement taking a NetLoader? Why not a LoaderBase?
- NetLoader assuming LoadTrait are of type NetStreamLoadTrait (created by LightweightVideoElement)
- Can't extend NetLoader.processFinishLoading() because NetStreamLoadTrait (the param) is "invisible" (excluded)
- NetStreamPlayTrait is also invisible
- NetLoader.executeLoad() could call a function to deal with the "default" in the switch. This way, custom behavior could be easily implemented while keeping the standard (rtmp, http, etc.) logic in place.
What took me 10 minutes to code similar logic in other players (Flowplayer, JWPlayer) took me hours in OSMF...but I'm not giving up yet
Thanks for the constructive feedback. I think we put thoughts / discussion around those areas (you've pointed when the framework was being built.
That's why now it is important to hear what your experience is. I added your comment to FM-996 however, if you'd like, please log your enhancement request as a new bug so that we can give more details to your point for consideration.
Thank you Ryan.
Is it going to be OSMF Project standard to adjust code for any CDN?
Even Internal independent corporate CDNs?
When I posed the same question about a different international CDN I was told that non-standard URI/Stream combinations should be adjusted at the CDN level and not at the OSMF Project Code level - and that I should report the problem to my CDN.
Should I post a bug report as well?
If the use case is to convert one URL (with custom protocol) into another URL, then I wouldn't solve it at the NetLoader level. Instead, I would use a proxy that can convert the original URL to the desired URL as a preflight operation. We have exactly such an example in the ExamplePlayer sample app, see VideoProxyElement, VideoProxyLoader, and VideoProxyLoadTrait here:
Since I don't have the exact details of your use case, I'm not sure if this is exactly what you're looking for. So let me know how it works out (or if it doesn't, why not).
closing FM-1000 as Brian suggestion seems to address it. If your findings differ from what Brian's comment (using ProxyElement), please re-open the bug and add the comment there, please.
Looks like the perfect solution Brian.
John_vh, sir, you saved my weekend. (I know this thread is OLD, but I really wanted to thank you)
I overrided the NetConnectionFactory and was struggling with the PlayTrait.
But then I read your post about the processReadyState() method, and everything became clear =)
Just to add another annoyance about overriding the NetConnectionFactory:
- I needed to put the file inside the package org.osmf.net, because I'm using the NetNegotiator class (which is INTERNAL and cannot be used from other packages).
It really bugs me how many things are private and "hidden" from the user.
As of today, I did'nt even realize how on earth I can get the number of dropped frames (or dropped frames per second).
Anyway, thank you.