6 Replies Latest reply on Oct 20, 2009 7:24 AM by Todd Pasternack

    Getting to the NetStream object

    charles_newman-6QjwQx

      Hi Folks,

       

      I had a few developers at MAX this week express to me their frustration about finding and getting to the NetStream object so I wanted to provide a little info here.  Some of the other OSMF developers can chime in as well.

       

      First, it depends on what you are trying to do.  If your goal is to add a callback on the client object, you can do this via the client property on the VideoElement such as:

       

      videoElement.client.addHandler(NetStreamCodes.ON_META_DATA, onMetaData);

       

      Take a look at the MetadataProxy class in the MetadataSample project.

       

      If your goal is to create your own custom NetStream class, you'll need to write a plug-in. The nice thing about plug-ins is they can be loaded at run-time or compiled in and the plug-in code looks identical in both cases, the plug-in doesn't know the difference.  In your plug-in, create your own NetLoader and override the createNetStream method.

       

      Take a look at the AkamaiBasicStreamingPlugin project for an example of how to do this.  Note you probably don't need to provide your own custom NetConnectionFactory. The Akamai plug-in does this to ensure the creation of a unique key used for connection sharing if auth tokens are specified.

       

      Hope this helps,

       

      - charles

        • 1. Re: Getting to the NetStream object
          charles_newman-6QjwQx Level 1

          ...and another use case I wanted to add is the more obvious one that you probably already know about, that is the case where you simply want to get to the NetStream object the framework created for you.  You can get to this via the ILoadable trait on the media element *after* the media element has been loaded.

           

          // somewhere in your code:

          var loadable:ILoadable = mediaElement.getTrait(MediaTraitType.LOADABLE) as ILoadable;
          loadable.addEventListener(LoadableStateChangeEvent.LOADABLE_STATE_CHANGE, onLoadableStateChange);

                         ...

           

          // in your load state change listener:

               ...

               switch (event.newState)
               {
                    case LoadState.LOADED:

                          var loadedContext:NetLoadedContext = event.loadable.loadedContext as NetLoadedContext;
                          var netStream:NetStream = loadedContext.stream;

           

           

          - charles

          • 2. Re: Getting to the NetStream object
            Todd Pasternack

            Charles,

             

            I'm trying to detect when a video is complete using the addHandler method off of the client property from VideoElement:

             

            var videoOne:VideoElement = new VideoElement ( new NetLoader, new URLResource(new URL("rtmp://4vl5ylx6.rtmphost.com/stream_test/quantumofsolace_8_hd")));
                       

            videoOne.client.addHandler(NetStreamCodes.NETSTREAM_PLAY_COMPLETE, onVideoComplete);

             

            serialElement.addChild (videoOne);

             

            As you can see this is indeed a streaming video. But as soon as I add the listener I get nothing. If I comment it out, the video plays but I obviously can't detect for the completion event.

             

            Any thoughts or insights or "you did it wrong!" would be greatly appreciated!

             

            Best,

            Todd

            • 3. Re: Getting to the NetStream object
              charles_newman-6QjwQx Level 1

              Hi Todd,

               

              There are a couple of problems with your code. First, the client property on the VideoElement is going to return null until the NetLoader is asked to load the media.  So you need to wait until the media is loaded before trying to access the client property.

               

              Second, "NetStream.Play.Complete" is an info object passed to the "onPlayStatus" method, so you can't add a callback for an info object.

               

              I've pasted some sample code below.  Also note: before folks do things like this, I recommend looking at the internal traits in OSMF and see if there is one that fits your needs, it could  save you time and lines of code.  For example, there is a "durationReached" event on the ITemporal trait.

               

              As you probably know, there are two different ways to detect the end of a video: for streaming, you can simply use the onPlayStatus and the NetStream.Play.Complete.  But for progressive files, the best way to do it is to read the duration from the metadata and in your NetStatusEvent.NET_STATUS event handler, you can check  if the NetStream time is within a delta of duration say, within 1 sec.

               

              OSMF should be doing this for you, if not, it should and you should file a bug.

               

              Here is a working example of your code, but I would recommend playing with the ITemporal trait and see if it is behaving properly for you.

               

                  public class osmf_test_client_addhandler extends Sprite
                  {
                      private static const TEST_STREAM:String = "rtmp://cp67126.edgefcs.net/ondemand/mp4:mediapm/osmf/content/test/sample1_700kbps.f4v";
                      private var videoOne:VideoElement;
                     
                      public function osmf_test_client_addhandler()
                      {
                          // Create the Sprite class that holds our MediaPlayer.
                           var sprite:MediaPlayerSprite = new MediaPlayerSprite();
                          addChild(sprite);
                         
                          videoOne = new VideoElement(new NetLoader, new URLResource(new URL(TEST_STREAM)));
                          var loadable:ILoadable = videoOne.getTrait(MediaTraitType.LOADABLE) as ILoadable;
                          loadable.addEventListener(LoadableStateChangeEvent.LOADABLE_STATE_CHANGE, onLoaded);
                                     
                          var serialElement:SerialElement = new SerialElement();
                          serialElement.addChild(videoOne);
                         
                          sprite.element = serialElement;           
                      }
                     
                      private function onLoaded(e:LoadableStateChangeEvent):void
                      {
                          if (e.newState == LoadState.LOADED)
                          {
                              videoOne.client.addHandler(NetStreamCodes.ON_PLAY_STATUS, onPlayStatus);
                             
                          }
                      }
                      private function onPlayStatus(info:Object):void
                      {
                          switch (info.code)
                          {
                              case NetStreamCodes.NETSTREAM_PLAY_COMPLETE:
                                  trace("Got here!");
                                  break;
                          }
                      }
                  }

               

              Thanks,

              - charles

              • 4. Re: Getting to the NetStream object
                Todd Pasternack Level 1

                Thanks, Charles. Works great.

                 

                To be honest, although I understand conceptually the idea of the 

                traits, I'm having a difficult time finding examples of how to use 

                them, access them, when to use them, etc.

                 

                For example, I wouldn't have thought I would have had to use ILoadable 

                on a streaming video. I instinctively thought that meta-data would be 

                accessible as soon as the video connected and listening for a 

                "complete" event would then be viable.

                 

                If there is some documentation I've overlooked with specifics or 

                tutorials you could suggest specific to traits that would be very 

                helpful.

                 

                I know traits are the core component of OSMF and understanding them is 

                integral to moving forward with any of my experiments.

                 

                Thanks much!

                 

                Todd

                • 5. Re: Getting to the NetStream object
                  bringrags Level 4

                  I'll chime in with a few points.  First, in 99% of the cases you don't need to worry about traits at all.  Instead, you should be using the MediaPlayer class (perhaps wrapped in MediaPlayerSprite), which exposes the full API of all traits in a "flattened" form.  Of course, if you're trying to define your own media, or create compositions (i.e. anything where you have to work with a MediaElement rather than a MediaPlayer), then you do need to be aware of traits.

                   

                  The main idea behind MediaElement and the traits API is that we want OSMF clients to be able to write their code independent of the media type they're presenting.  If your player works for video, then it ought to work for audio, images, SWFs, or even compositions containing all of the above.  But for this to work, we need an abstraction that works for all media types.  This abstraction is going to be less efficient than working with the native API, and in some cases more confusing (you point out that "loadable" isn't something that should apply to a streaming video), but the benefit is that you don't have to change your player when you bring in new media types.  And once you've internalized what each trait is intended to represent (e.g. ILoadable will transition your media from its initial state, to the point where it is ready for playback -- which might mean calling NetConnection.connect, or Loader.load, or some other sequence of methods), then you can stop thinking about how the underlying media actually works, and just code to the traits.

                   

                  So with that in mind, any time you find yourself needing to access the underlying media implementation (e.g. NetStream's client property), there should be an alarm bell going off in your head that something is wrong.  Either you've overlooked a MediaElement/trait API that does what you're looking for, or we've missed something that ought to be abstracted and incorporated into the MediaElement/trait API (and we especially want to know about the latter).

                   

                  In terms of documentation/tutorials on traits, the best I can recommend is to look closely at the implementations of specific traits for different media (e.g. NetStreamPlayableTrait vs. AudioPlayableTrait).  Sometimes the best way to get your head around an abstraction like this is to see multiple examples of what it represents.  I'd also recommend looking at the ExamplePlayer app, as that's a good demonstration of a player which makes no assumptions about media types.  Based on your feedback so far, I think you're getting pretty deep into the core of OSMF, so I'd love to hear any other thoughts you have on what kind of resources we should provide to help others (i.e. what has been helpful for you so far).

                   

                  Cheers,

                  Brian

                  • 6. Re: Getting to the NetStream object
                    Todd Pasternack Level 1

                    Thanks so much for this great overview, Brian. You should include this 

                    on the front page of the forum!

                     

                    My first experiments with OSMF were approached exactly as you 

                    suggested, using the MediaPlayer class wrapped in MediaPlayerSprite. 

                    It's when I started to pick apart some of the media classes/elements 

                    that I lost my way a bit.

                     

                    I guess the part I didn't know was how to work with/access the actual 

                    traits. The fact that you "assign" the traits to the media element and 

                    then use that to listen for events had alluded me. I thought each 

                    media class/element would have been able to listen for events itself. 

                    And yes I know, traits are the beauty and power of OSMF and yet 

                    through all of the documentation and examples I didn't pick up on this.

                     

                    And I consider myself a relatively smart person... relatively.

                     

                    So I guess more explicit examples in the code documentation of how to 

                    use the traits would be great. With real-live examples tied to 

                    different media types/elements.

                     

                    I know your team lives and breathes this framework everyday. But for 

                    folks just diving in (or maybe dove in months ago but is only floating 

                    on their back instead of doing the breast stroke... weird analogy), 

                    more concrete examples of using traits to listen for events would be 

                    great. And also, cracking open the provided example source files in 

                    Flex without having to track down all the packages and fixing errors 

                    would be nice, too.

                     

                    Overall, I'm a fan so far - no question. But inundating the user-group 

                    with tons of examples and use-cases is very much a welcome thing.

                     

                    Brian, I hope this helps. And if there are specific documents I missed 

                    that do address the specifics I mentioned about traits please point me 

                    to them. I'm sure there will be others in the community who may have 

                    overlooked them, as well.

                     

                    Best,

                    Todd