You could do it either way, and I think the approach would be whether you want the user to see this as one atomic media presentation, or two separate presentations. It sounds like the former, in which case I'd use a SerialElement with three children. The first and third are pretty obvious (VideoElement). For the second, I'd create a custom MediaElement that exposes the image, and which automatically pauses playback when it's loaded. You could do this in a number of ways, but the simplest might be to create a subclass of ProxyElement which wraps an ImageElement. The ProxyElement subclass would add a "fake" PlayTrait (so that the SerialElement would believe that it can play it), and would call pause() on that PlayTrait right when it gets loaded. You'd probably have to experiment a bit to get it exactly right. But as a starting point, you could look at the PosterFrameElement and RTMPPosterFrameElement examples in our ExamplePlayer. These are used to display a poster frame prior to playback. Neither example integrates the pause logic that you need, but you could probably extend them (or rewrite them) to do so.
Thanks for your help. I was able to create a PosterFrame off the example file and add it to a serialElement with an ad and a video. Is there a way to reset the timeline position when playing back serial elements? It looks like even in the example it plays the first element and then when playing the second video the timeline marker jumps to where the first video left off.
Not sure what you mean by "reset the timeline position". The playhead always reflects the position within the overall SerialElement, so when it moves from child #1 to child #2, it doesn't jump back to the beginning. If you want the playhead to move to the beginning, then you should use separate MediaElements rather than a single SerialElement that wraps them up.
Sorry for not being clearer. Yes I need the playhead to go back to the beginning after the first serial element is done. If I wanted to sequence mediaElements to play one after the other would you suggest adding a listener for the video complete then loading a new media element? If so is there an event listener in MediaElement that checks for this?
Yes, I'd recommend that approach. Just listen for the "complete" event on MediaPlayer.
Is there still nothing in OSMF that can handle a list of elements (like SerialElement) but report the currentTime and duration only for the current MediaElement?
Seems wasteful to re-create the logic of playing one item after another. I thought of extending SerialElement and creating my own TimeTrait for this but it's proving a bit hard because of internal classes and private members.
In our project we needed the "PREV/NEXT" functionality badly - so we had to implement some kind of new element for it. Unfortunately subclassing serial did not do due to the reasons you have mentioned. Moreover subclassing CompositeElement did not do because of TraitAggregator reference is hardcoded in the very base class and dependency on multiple internal classes also. That is very annoying and inconvenient. I have posted here concerning it (can't provide a reference now - i'm on mobile phone). So we decieded to implement it with proxy-like element, overriding PLAY, TIME and LOAD traits and a new proxy metadata.
And the lack of PREV/NEXT trait in OSMF is annoying to - so the element would be binded with your controls.
I'll piggy back on this post to ask if anything has been found as an easy way to deal with the composite traits from serial element? We have a client who wants to exclude any pre-roll or post-roll advertisements timelines from the progress bar for the player. The default behavior with the composite time trait makes that quite difficult. Is there an easy way to bypass the composite behavior, or do we still need to hack into composite time trait and extract the time for only the elements we want included? Or do we need to go into multiple media elements as the original post here suggests?
Have you tried replacing a timetrait (with proxy) in prerolls and postrolls before inserting into serial?
I'm not sure just blocking them will do because a lot of things rely on TimeEvent.COMPLETE rather than PlayState change. But you may try to mock time values (e.g. keep them NaN) and make your slider disappear on that. Or maybe just blocking the SeekTrait will do - not sure what will the CompositeSeekTrait deal with that, but still...
The idea is an intriguing one. I agree that it could cause problems with the complete time and might make seeking interesting. Perhaps just having it return 1 second could work to avoid problems with NaN getting aggregated. I'm not sure if the complete event is based on time or if it comes off of NetStream events.
Unfortunately, one of the scenarios I'd like to be able to cover is the MAST plug-in that automatically inserts prerolls and postrolls into a SerialElement. With that I only have easy access to the Composite traits and I don't have easy access to the child traits. I think your idea could work for some of the places we construct our own SerialElements, and is worth a POC. I may have some spare time here soon. Hmmm.
Unfortunately, one of the scenarios I'd like to be able to cover is the MAST plug-in that automatically inserts prerolls and postrolls into a SerialElement. With that I only have easy access to the Composite traits and I don't have easy access to the child traits.
If those rolls are created by MediaFactory, you may try to distinguish the resources, say, by URL or metadata from resources of your video.
If there is no "strong features" on commercials to distinguish - you may add a marker metadata value to your resources.
Thus you may write a proxy plugin that returns true in canHandleResource when the commercial element is being created (by analizng resource).
This way you get rolls wrapped and videos - not wrapped.
That's a good point. I'll try a POC and let you know how that goes. Thanks!
I looked into this, and unfortunately it doesn't look feasible, or at least easily so. The good news is that the control bar doesn't show progress with this approach. However ... the CompositeTimeTrait is listening for complete events on its child TimeTraits. Without that event, the SerialElement won't advance to the next element. The TimeTrait in turn is looking for the duration to equal the currentTime to dispatch a Complete event. That check is done by the setCurrentTime method, which calls the signalComplete method. Both of those methods are helpfully marked final, and can't be overridden.
I could call signalComplete manually, but knowing when to do that would be the trick. I looked into using an internal flag to allow the trait to use the real duration and only show the outside world the 1 second duration. Then I could use currentTimeChangeEnd to compare the currentTime and real duration and then manually call signalComplete. Unfortunately, I couldn't get currentTimeChangeEnd to fire. The base TimeTrait doesn't do a lot of things by default, and the NetStreamTimeTrait, which I'd want my trait to extend, is marked ExcludeClass so I can't piggyback on its functionality. I could pull it out of the framework and make my own version that I can extend, but that's getting messier than I care to go. Maintaining those extracted classes is a PIA.
There's probably a way through the woods, but I'm not sure it is worth it. Manually switching the elements is sounding easier, though that won't cover MAST plugin elements. Perhaps it's time to see if the client really wants that plugin supported. If they do, I'll be back to revisit this approach.
Turbidity, I've got a simple idea.
What if you leave all that trait mess and make things simplier?
Just mark your content elements with some dummy SHOULD_SHOW_SEEK_BAR metadata.
Than watch METADATA_ADD / METASATA_REMOVE events on composition and here is the way to handle it.
Or, if you want seek bar to be visible by default - make the same commercial proxying with SHOULD_NOT_SHOW_SEEK_BAR metadata set.
As for time traits - dealing with time traits is tricky. Especiallly if your element gets into composition.
For instance there is a double check of current/total time equality of all children upon completion event - so you won't want to seek your element before that check passes or you will stick into "playing" state in player.
Have you considered using MediaPlayer API instead of proxies?
You could use a different media player for each media that you want to play. All you have to do to switch between them is to pause the current media player, remove its media element from the media container and add the new one.
You can find an example of this, incapsulated in a reference plugin, here: http://blogs.adobe.com/osmf/2011/03/stage-video-and-ad-insertion-plug-in-for-osmf.html.
Let me know what you think,
I've done something similar to that in a previous use case, but in this particular case the hard requirement is to make the progress bar not include the time for the preroll in the SerialElement. If there's a 30 second preroll, those 30 seconds get added to the time when the main content shows. That's the part that is the sticking point.
Thanks for the heads up about that Advertisement Plugin. I didn't know about that one. That looks like it may be the ticket as long as the client doesn't want the MAST functionality. They're not currently using MAST, but have talked about using that. They're using SerialElements right now, but this looks like this could serve their needs well.
Mike Teleru, thanks again for cluing me into this plugin. I think it is exactly what we need. I've been playing around with it, and I think it will work fine with our implementation of OSMF (based on REOPS). I haven't plugged it into that yet, but in examining how it behaves, I think it should work great, as long as I can figure out the easiest way to pass in the MediaContainer and MediaPlayer. We can listen for layout children changes on the container and then based on the player contents, display or hide the control bar. Listening for metadata could work too. The duration on the media player never changes and the current time does update during preroll playback, which is exactly what we need.
RoberBarker, this should take care of your needs too, I hope.
Thanks again, all!