9 Replies Latest reply on Jan 19, 2010 9:12 AM by DJDonovanNYC

    SerialElement access

    DJDonovanNYC

      Been trying to dig around and find more information on this but no luck. Seems like a basic question though.

       

      When using a SerialElement, is there an event or an approach for determining which video is playing in the sequence and when the change is fired? I've played around with round about ways of doing this, but it seems to me that there should be a more direct way to do this?

       

       

      Also is there an easy way to get the duration for the individual elements in a SerialElement?

       

      Message was edited by: DJDonovanNYC

        • 1. Re: SerialElement access
          RyanOConnell Level 2

          Hello,

           

          The SerialElement is a CompositeElement, so if you need to access individual elements there are getChild and numChildren public properties and methods.   The duration for child elements will be on the TimeTrait of the child elements.

           

          The SerialElement doesn't currently expose the currently playing item as a public API.   Only a few use cases required this behavior, and so it has been made protected.  You can subclass the SerialElement and access the currentchild through overriding processAddedChild and processAddedRemove. The traitAggregator  property (protected as well) will also have a listenedChild, which will be the current child.

           

          -Ryan

           

          • 2. Re: SerialElement access
            DJDonovanNYC Level 1

            Thanks for the info Ryan. Interesting response and should do the trick. I'm not sure why that value wasn't exposed though? What if you want to fire off tracking information that is associated with each of the individual children of the SerialElement? Also how would you access trait information of the respective elements if you can't get the current items position in the array? The fact that you have a getChildAt(index) on the SerialElement as well as numChildren, I'd think that the currentIndex should be exposed?  Just my thoughts. An event for when this index changes also would be very useful IMHO.

             

            The only other thing I could think of, would be to assign facet data to the child elements, but as far as I know, the data doesn't get updated and bubbled up tot the SerialElement container? Once again I would need to drill down to the child elements and retrieve the facet that way?

             

            Thanks again for the help:)

             

            Donovan Adams

            • 3. Re: SerialElement access
              DJDonovanNYC Level 1

              So I tried your suggestion a couple different ways and didn't have any luck. Mostly because the TraitAggregatorEvent class is an internal class. What I wound up doing was creating my own CustomSerialElement class in the org.osmf.composition package and adjusted the updateListenedChildIndex to:

               

              private function updateListenedChildIndex():void

              {

                   listenedChildIndex = traitAggregator.getChildIndex(traitAggregator.listenedChild);

                   dispatchEvent(new SerialElementEvent(SerialElementEvent.INDEX_CHANGE, listenedChildIndex));

              }

               

               

              I also created a new event in org.osmf.events called SerialElementEvent which has a public index property. This gets called when updateListenedChildIndex is called. I added a listener to my CustomSerialElement variable within my application:

               

              _videoSequence.addEventListener(SerialElementEvent.INDEX_CHANGE, onIndexChange);

               

              And the callback:

               

              private function onIndexChange(event : SerialElementEvent) : void {

                   var cmd:Metadata = CustomSerialElement(_player.element).getChildAt(event.index).metadata;

                   var key:KeyValueFacet = cmd.getFacet(new URL("test.php")) as KeyValueFacet;

               

                   trace("******** "+event.index, key.getValue(new ObjectIdentifier("id")), key.getValue(new ObjectIdentifier("path")));

              }

               

              Updates nicely even when doing a temporal seek back to the first video.

               

               

              Obviously subclassing would be ideal, but because of the privates in SerialElement, along with the internal classes, I had to put the extra stuff within the org.osmf folder.

               

              Maybe I can make this a contribution!

              • 4. Re: SerialElement access
                bringrags Level 4

                Before you go too far down that path, let me offer some insight into the current design.  There's a reason that SerialElement doesn't expose an event for the current child changing, nor a getter for the current child.  The reason is that we don't want clients of a MediaElement to be coding against APIs of a specific subclass, we want clients to code against the MediaElement abstraction itself.  The latter approach is far more flexible as things change.  With the former approach, if you later decide to wrap your SerialElement in a ParallelElement (to add some new logic in parallel), then your client code will break.  The MediaElement API was designed to be able to support serial and parallel cases without having to resort to casting to subclasses.

                 

                What exactly are you trying to achieve (i.e. what's the use case) that leads you to believe you need to know when the SerialElement's child changes?  The idea behind SerialElement (as with all other MediaElement subclasses) is that a client shouldn't need to know it's a SerialElement.  So if you have a use case where the client will perceive it as a sequence of multiple MediaElements, then perhaps SerialElement isn't the right approach.  If we can get a better idea of your use case, we may be able to point you in a more appropriate direction (which I suspect is the use of metadata facets, as your previous post also suggests).

                • 5. Re: SerialElement access
                  DJDonovanNYC Level 1

                  This makes sense and was something I considered. Possibly creating my own sequence outside of using the SerialElement class, but I figured that since it's there, I might as well use it. Also considering that it creates a complete timeline with duration and seek capability reflective of the content within the SerialElement, I decided to give it a shot. Maybe you can suggest an alternate path that functions like the SeriallElement class with the smooth transition and ability to scrub back to a previous child clip. My use case is anytime our player serves a video, data/metadata with the respective video needs to be fed to anaytics and ad ops. We could assign specific metadata to the predetermined collective clips, but being able to piece them together on the fly and fire off the events as the clips are playing seems like a more accurate and flexible solution. If I'm understanding the methodology for the SerialElement, it sounds like you take a collection of clips and create the SerialElement and you've created a new clip and that's that. Another approach I had was to run a series of TemporalElements that fire off the events in parallel with the created SerialElement, but that seemed like extra work versus getting the data/index directly. I guess the bottom line is the SerialElement creates a nice user experience when creating a group of clips, but as a person developing video playback for a cable network, we need to track every little thing . Also the way I have it set up is if someone scrubs back to a previous video, the video impression is fired off which is very useful analytic data. Maybe a new MediaElement can be created that supports back to back video playback with awareness? SequentialVideoElement? Just thinking out loud

                   

                  Anyways let me know your thoughts and thanks for your help. This discussion is helping me to further understand the osmf architecture as well as hash out our own requirements and ideas. I noticed there are plans for interstitial video which looks awesome!

                   

                  Cheers,

                  Donovan Adams

                  • 6. Re: SerialElement access
                    bringrags Level 4

                    Ok, it sounds like a SerialElement is actually the appropriate element for your use case, since you want to present all of the pieces to the user as if they're one (with interstitial seeking and a single duration).  Your use case is a prime example of what metadata should be used for.   A MediaElement's metadata property is capable of firing change events whenever metadata changes.  So let's say you create a SerialElement with three VideoElement children, and assign some metadata in a custom KeyValueFacet (i.e. you define your own namespace URL for the facet) to each one.  And to go further, let's say that you assign a single key to each child, but with different values, along the following lines:

                     

                    var serial:SerialElement = new SerialElement();


                    var video1:VideoElement = new VideoElement(...);

                    var facet1:KeyValueFacet = new KeyValueFacet(new URL("http://my.custom.namespace.com");

                    facet1.addValue(new ObjectIdentifier("myKey"), "value1");

                    video1.metadata.addFacet(facet1);

                    serial.addChild(video1);


                    var video2:VideoElement = new VideoElement(...);

                    var facet2:KeyValueFacet = new KeyValueFacet(new URL("http://my.custom.namespace.com");

                    facet2.addValue(new ObjectIdentifier("myKey"), "value2");

                    video2.metadata.addFacet(facet2);

                    serial.addChild(video2);


                    var video3:VideoElement = new VideoElement(...);

                    var facet3:KeyValueFacet = new KeyValueFacet(new URL("http://my.custom.namespace.com");

                    facet3.addValue(new ObjectIdentifier("myKey"), "value3");

                    video3.metadata.addFacet(facet3);

                    serial.addChild(video3);

                     

                    When you play this SerialElement back, you'll get a FacetValueChangeEvent when the SerialElement transitions from the first child to the second ("value1" -> "value2") and another FacetValueChangeEvent when the SerialElement transitions from the second child to the third ("value2" -> "value3").  You would get the same event sequence if you had a single VideoElement with a single facet, and which changed its metadata values on the fly during playback.

                     

                    The key here is that the client of your MediaElement can simply listen for the FacetValueChangeEvent (and other metadata events) and respond to those changes, without needing to know whether the MediaElement is a SerialElement with three children, or a single VideoElement.  If you later decided to wrap your SerialElement in a ParallelElement, then the client code would not need to change.

                     

                    This might seem like a lot of boilerplate for a single value changing, but this approach really pays off when you have a bunch of metadata on each child, where some of it overlaps and some doesn't, and the metadata that does overlap sometimes changes from child to child, and sometimes doesn't.  The framework will automatically detect the relevant changes and dispatch the appropriate events, provided that you've defined the metadata appropriately.

                     

                    And I believe that if you scrub back from the third child to the first, you'll get a FacetValueChangeEvent as a result of that transition (if I'm wrong, that's a bug), which should again allow you to have a single code path for responding to metadata change events.

                     

                    Let us know if you make progress with this approach, I'm curious whether you run into any obstacles specific to your use case.

                    • 7. Re: SerialElement access
                      kenneth.garee

                      Hey bringrags,

                       

                      I'm trying to make use of the FacetValueChangeEvent as you described and I'm unable to catch the event.

                      for each(var song:XML in songList){

                        var audioElement:AudioElement = new AudioElement(new SoundLoader, resource);

                        var kv_facet:KeyValueFacet = new KeyValueFacet(new URL("http://my.custom.namespace.com"));

                        kv_facet.addValue(new ObjectIdentifier("song_id"), song.@song_id);

                        audioElement.metadata.addFacet(kv_facet);

                        serialElement.addChild(audioElement);

                      }

                       

                      mediaDisplay = new MediaPlayerSprite();

                      mediaDisplay.addEventListener(FacetValueChangeEvent.VALUE_CHANGE, onFacetValueChange);

                       

                      The songs load in the SerialElement but there is no FacetValueChangeEvent dispatched.

                       

                      Is there something I'm missing?

                       

                      Thanks,

                      Ken

                      • 8. Re: SerialElement access
                        bringrags Level 4

                        Since MediaPlayerSprite is primarily a UI class, it doesn't dispatch any metadata events (or any other events, for that matter), so you'd have to add your listener elsewhere.  Looking closer, I now notice that MediaPlayer also doesn't dispatch metadata events, which seems like an omission.  Until we remedy this and add those events to MediaPlayer, you would have to add your listener directly to the MediaElement that will dispatch them (in this case, AudioElement).

                         

                        Can you file a bug on the absence of metadata events (MetadataEvent, FacetValueEvent, and FacetValueChangeEvent) on MediaPlayer?

                        • 9. Re: SerialElement access
                          DJDonovanNYC Level 1

                          UPDATE * It seems as though the index will be provided as a protected getter and setter.

                           

                          http://forums.adobe.com/message/2501155