10 Replies Latest reply on Feb 15, 2011 4:26 AM by RandomReado

    Cannot seek immediately after setting the source

    RandomReado Level 1

      In Flash Builder, I have the following code:

       

      [CODE]<?xml version="1.0" encoding="utf-8"?>
      <s:WindowedApplication xmlns:fx="http://ns.adobe.com/mxml/2009"
                             xmlns:s="library://ns.adobe.com/flex/spark"
                             xmlns:mx="library://ns.adobe.com/flex/mx">
          <s:layout>
              <s:VerticalLayout/>
          </s:layout>
          <fx:Script>
              <![CDATA[
                  import org.osmf.events.MediaPlayerStateChangeEvent;
                  private function loadSeek():void
                  {
                      videoPlayer.source = 'rtmp://localhost/project/mp4:1001.mp4';
                      videoPlayer.seek(30);
                  }
              ]]>
          </fx:Script>
          <s:VideoPlayer id="videoPlayer" width="854" height="480" autoPlay="false"/>
          <s:Button label="Load Video &amp; Seek" click="loadSeek()"/>
      </s:WindowedApplication>[/CODE]

       

      When I click the button, the source is set and the video appears. However it should then be seeking to 0:30 but it doesn't.

       

      Any ideas why?

        • 1. Re: Cannot seek immediately after setting the source
          Flex harUI Adobe Employee

          Try calling validateNow after setting the source.

          • 2. Re: Cannot seek immediately after setting the source
            RandomReado Level 1

            The code now reads:

             

            videoPlayer.source = 'rtmp://localhost/project/mp4:1001.mp4';

            videoPlayer.validateNow();
            videoPlayer.seek(30);

             

            Unfortunately that doesn't make any difference. The first frame loads fine but it doesn't seek to 0:30.

            • 3. Re: Cannot seek immediately after setting the source
              Flex harUI Adobe Employee

              Can you wait for one of the events before doing the seek?  All loading is

              asynchronous.

              • 4. Re: Cannot seek immediately after setting the source
                RandomReado Level 1

                Which event would you suggest?

                 

                I tried something like this:

                 

                <?xml version="1.0" encoding="utf-8"?>
                <s:WindowedApplication xmlns:fx="http://ns.adobe.com/mxml/2009" 
                                       xmlns:s="library://ns.adobe.com/flex/spark" 
                                       xmlns:mx="library://ns.adobe.com/flex/mx"
                                       height="550" width="860"
                                       showStatusBar="false">
                    <s:layout>
                        <s:VerticalLayout/>
                    </s:layout>
                    <fx:Script>
                        <![CDATA[
                            import org.osmf.events.MediaPlayerStateChangeEvent;
                            
                            private function loadSeek():void
                            {
                                video.addEventListener(MediaPlayerStateChangeEvent.MEDIA_PLAYER_STATE_CHANGE, seekVideo);
                                video.source = 'rtmp://localhost/project/mp4:1001.mp4';
                                
                                function seekVideo(e:MediaPlayerStateChangeEvent):void
                                {
                                    if (Math.round(video.currentTime) == 30)
                                    {
                                        video.removeEventListener(MediaPlayerStateChangeEvent.MEDIA_PLAYER_STATE_CHANGE, seekVideo);
                                        
                                        trace('SEEKED');
                                    }
                                    else
                                    {
                                        video.seek(30);
                                        
                                        trace(video.mediaPlayerState);
                                    }
                                }
                            }
                        ]]>
                    </fx:Script>
                    <s:VideoDisplay id="video" width="854" height="480" autoPlay="false"/>
                    <s:Button label="Load Video &amp; Seek" click="loadSeek()"/>
                </s:WindowedApplication>
                

                 

                Here's the order of trace events:

                 

                loading
                ready
                buffering
                playing
                buffering
                buffering
                buffering
                buffering
                SEEKED

                 

                I wasn't sure this was the best way to do it since each MediaPlayerStateChange is firing off a seek attempt till the seek is successful. Unless there's another way?

                • 5. Re: Cannot seek immediately after setting the source
                  rfrishbe Level 3

                  Before calling seek(), try waiting for the mediaPlayerStateChange event.  Specifically wait for the READY state and then call seek().

                   

                  Let me know if that works.

                   

                  Thanks,

                  Ryan

                  • 6. Re: Cannot seek immediately after setting the source
                    rfrishbe Level 3

                    Also, if you're planning on seeking to 30, you might want to set autoDisplayFirstFrame="false".  This way the VideoPlayer won't attempt to load up the first frame of the video.

                     

                    -Ryan

                    • 7. Re: Cannot seek immediately after setting the source
                      RandomReado Level 1

                      Hi Ryan,

                       

                      Neither of those worked for me. Code snippet is:

                       

                      if (e.state == 'ready')
                      {
                          video.seek(30);
                          video.play();
                      }

                       

                      I also set "autoDisplayFirstFrame" to false but this made no difference.

                       

                      In my last reply, you'll notice the SEEKED event, i.e. when the video currentTime matches the seek time, occurs after the "ready" event, and after several "buffering" events. Is this the correct or should the video be seeking a lot sooner?

                       

                      This issue is occurring in Flex 4.1 and above, including the latest Flex 4.5 build.

                      • 8. Re: Cannot seek immediately after setting the source
                        rfrishbe Level 3

                        At that time, can you find out if the underlying OSMF object can seek yet?

                         

                        import mx.core.mx_internal;

                        use namespace mx_internal;

                         

                        if (videoPlayer.videoDisplay.videoPlayer.canSeek && videoPlayer.videoDisplay.videoPlayer.canSeekTo(30))

                         

                        If that's not true, you could try listening for some of the underlying OSMF events.  Something like:

                         

                        videoPlayer.videoDisplay.videoPlayer.addEventListener(MediaPlayerCapabilityChangeEvent.CAN _SEEK_CHANGE,  videoPlayer_canSeekChangeHandler);

                         

                        Sorry this turns out to be pretty difficult.  Unfortunately, video tends to be difficult once you move off the normal path.

                         

                        -Ryan

                        • 9. Re: Cannot seek immediately after setting the source
                          RandomReado Level 1

                          Ok I've now got the following code:

                           

                                      private function loadSeek():void
                                      {
                                          import mx.core.mx_internal;
                                          use namespace mx_internal;
                                          
                                          video.addEventListener(MediaPlayerStateChangeEvent.MEDIA_PLAYER_STATE_CHANGE, seekVideo);
                                          video.source = 'rtmp://localhost/project/mp4:1001.mp4';
                                          
                                          function seekVideo(e:MediaPlayerStateChangeEvent):void
                                          {
                                              trace(e.state);
                                              
                                              if (video.videoDisplay.videoPlayer.canSeek && video.videoDisplay.videoPlayer.canSeekTo(30))
                                              {
                                                  trace('SEEK');
                                                  
                                                  video.removeEventListener(MediaPlayerStateChangeEvent.MEDIA_PLAYER_STATE_CHANGE, seekVideo);
                                                  video.seek(30);
                                              }
                                          }
                                      }

                           

                          The order of trace events is:

                           

                          loading
                          ready
                          buffering
                          playing
                          paused
                          SEEK

                           

                          However when "SEEK" is firing, the selected position is still 0:00, even though canSeek and canSeekTo both return true.

                           

                          I also tried the other event you suggested but got the same result:

                           

                                      private function loadSeek():void
                                      {
                                          import mx.core.mx_internal;
                                          use namespace mx_internal;
                                          
                                          video.videoDisplay.videoPlayer.addEventListener(MediaPlayerCapabilityChangeEvent.CAN_SEEK_CHANGE, seekVideo);
                                          video.source = 'rtmp://localhost/project/mp4:1001.mp4';
                                          
                                          function seekVideo():void
                                          {
                                              trace('SEEK');
                                              
                                              video.videoDisplay.videoPlayer.seek(30); // also tried: video.seek(30);
                                          }
                                      }
                          

                           

                          Again, the "SEEK" trace event fires but the video remains at 0:00.

                          • 10. Re: Cannot seek immediately after setting the source
                            RandomReado Level 1

                            I had an idea today. In this code I've managed to get it to send 1 seek request only and it seems to work every time:

                             

                            private var _paused:Number;
                            private var _pausedSeek:Boolean;
                            
                            protected function initApp():void
                            {
                                video.addEventListener(MediaPlayerStateChangeEvent.MEDIA_PLAYER_STATE_CHANGE, seekVideo);
                            }
                            
                            protected function loadSeek():void
                            {
                                _paused = 0;
                               
                                video.source = 'rtmp://localhost/project/mp4:1001.mp4';
                            }
                            
                            protected function seekVideo(e:MediaPlayerStateChangeEvent):void
                            {
                                trace(e.state+' - '+video.currentTime);
                               
                                if (e.state == 'paused')
                                {
                                    _paused++;
                                    _pausedSeek = (_paused == 2) ? true : false;
                                }
                               
                                if (_pausedSeek)
                                {
                                    _pausedSeek = false;
                                   
                                    video.seek(30);
                                   
                                    trace('SEEK'+_paused);
                                }
                            }
                            

                             

                            When I call "loadSeek()" the "_paused" variable is reset to 0. When we set the source there's a number of paused events before the video seeks, so I've set it to count the paused events, and when it reaches 2 it fires the seek once only.

                             

                            Here's the trace events:

                             

                            loading - 0
                            ready - 0
                            buffering - 0
                            playing - 0
                            paused - 0.08
                            buffering - 0.08
                            paused - 0
                            buffering - 0
                            SEEK2
                            paused - 30.163

                             

                            Sometimes when click the button I see 0:00 for less than a second before it seeks. Other times I don't and it seeks immediately.

                             

                            So far this is by far the best solution I've found that doesn't spam the server with seek requests till one is successful, and it works every time. Would be nice though if OSMF had this sort of functionality built in, perhaps as an Event, instead of having to write your own.