Forums

/

JavaScript SEEK with RTMP

15 replies [Last post]

Are there any examples of HTML hyperlinks that can jump the video to a position using SEEK, even if the video is not playing? I'll be using RTMP. The problem is that calling SEEK will not start the video.

Here is the example I'm looking at:
http://home5.inet.tele.dk/nyboe/flash/mediaplayer4/JW_API_xmpl_5-1-0-0.html

I'd like to simulate a playlist as HTML links, such as this:

<p><a href="#" onclick="player.sendEvent('SEEK', 120)">Tutorial 1</a></p>
<p><a href="#" onclick="player.sendEvent('SEEK', 220)">Tutorial 2</a></p>
<p><a href="#" onclick="player.sendEvent('SEEK', 320)">Tutorial 3</a></p>
<p><a href="#" onclick="player.sendEvent('SEEK', 420)">Tutorial 4</a></p>

These links only work if the video is playing. I'd like them to start the video and jump to those spots.

    <script type="text/javascript">
      var player   =  null;
      var seek     =     0;
      var seekFlag = false;
      var currentState;

      function playerReady(obj)
      {
        player = gid(obj.id);
        player.addModelListener('STATE', 'stateMonitor');
      };

      function stateMonitor(obj)
      {
        if((obj.newstate == 'PLAYING') && (seekFlag))
        {
          seekFlag = false;
          setTimeout("player.sendEvent('SEEK', seek)", 100);
        }
        currentState = obj.newstate;
      };

      function seekSome(some)
      {
        seek = some;

        if(currentState == 'PLAYING')
        {
          player.sendEvent('SEEK', seek)
        }
        else
        {
          seekFlag = true;
          player.sendEvent('PLAY', 'true');
        }
      };

        function gid(name)
      {
        return document.getElementById(name);
      };
    </script>

<a href="#" onclick="seekSome(20); return false;">SEEK 20</a>

Works perfect, thanks so much!

This is exactly what I want :-) I had it working a month or two ago, but now, using the latest JW flash player and the latest swfobject.js, I cannot get it to work. The video always starts playing from 0 secs.

Kyle, what versions of JWflash player and swfobject are you using? Also, can you confirm that it works when the page/player initially comes up with autostart=false? I can get it to seek and play properly IF the player loads with autostart=true; it only works with autostart=false IF I have previously played the video and then press pause or stop before issuing the seek request.

I modified the example cited above and added the javascript solution show above. You can see my results here:
http://www.ccn.tv/myccn/JW_API2.html

It will start playing at 0 when you press the link for "seek absolute position (10th. second)"

So, am I doing something wrong? Will this only work for a specific version?

@DebFahey,

Try this code:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">

<html lang="en">

  <head>

    <title>JW API Example 5-1-0-0 - JW FLV Media Player</title>

    <script type="text/javascript" src="/js/swfobject.js"></script>

    <script type="text/javascript">
      var flashvars =
      {
        file:                 'http://content.bitsontherun.com/videos/3ta6fhJQ.flv', 
        autostart:            'false'
      };

      var params =
      {
        allowfullscreen:      'true', 
        allowscriptaccess:    'always'
      };

      var attributes =
      {
        id:                   'player1',  
        name:                 'player1'
      }

      swfobject.embedSWF('/OVSS/player41.swf', 'placeholder1', '320', '196', '9.0.115', false, flashvars, params, attributes);
    </script>

    <script type="text/javascript">
      var player   =  null;
      var seek     =     0;
      var seekFlag = false;
      var currentTime;

      function playerReady(obj)
      {
        player = gid(obj.id);
        player.addModelListener('TIME',  'timeMonitor');
      };

      function timeMonitor(obj)
      {
        if((obj.position > 0) && (seekFlag))
        {
          seekFlag = false;
          player.sendEvent('SEEK', seek);
        }
        currentTime = obj.position;
      };

      function seekSome(some)
      {
        seek = some;

        if(currentTime > 0)
        {
          player.sendEvent('SEEK', seek)
        }
        else
        {
          seekFlag = true;
          player.sendEvent('PLAY', 'true');
        }
      };

      function gid(name)
      {
        return document.getElementById(name);
      };
    </script>

  </head>

  <body>

    <a href="http://www.jeroenwijering.com/?item=JW_FLV_Media_Player">JW FLV Media Player</a>
    <br>
    External javascript control.
    <br>
    <br>
    <div id="placeholder1">
      <a href="http://www.adobe.com/go/getflashplayer">Get flash</a> to see this player    
    </div>
    <br>
    <a href="#" onclick="player.sendEvent('PLAY')">play/pause toggle</a>
    <br>
    <a href="#" onclick="player.sendEvent('STOP')">stop playing and buffering</a>
    <br>
    <a href="#" onclick="seekSome(10);return false;">seek absolute position (10th. second)</a>
    <br>
    <a href="#" onclick="player.sendEvent('VOLUME', 50)">set absolute volume 50%</a>
    <br>

  </body>

</html>

Also, be aware that seeking to a position in the video that has not yet downloaded simply won't work unless you are using a streaming server.

Get the v4.2.71 player from here: http://code.jeroenwijering.com/trac/export/74/branches/4.2/player.swf

And specify and upgrade to the Adobe Flash Player 9.0.124. It plugs a bad security hole.

Hi "how"! Thank you for the code, I'll definitely try it out. I grabbed the JW 4.2 code earlier this evening. I'll do the Adobe upgrade as well.

I forgot to mention I am using a streaming server (FMS3). Since the videos I am working with run 60-75 minutes long and are for self-training, it is important to provide access to "chapters" within each video, and that is why I need to seek. Especially I need to support a user who pauses or stops the video one day, and comes back the next day expecting to be able to resume from where he left off. The JW Player has all the right stuff for me to support that as long as I get this one issue of resuming at some point into the video, as well as simply jumping to a chapter.

I just got thru testing a workaround based on the 5-2-1-0 example from nyboe (http://home5.inet.tele.dk/nyboe/flash/mediaplayer4/), but it is a little clumsy: http://www.ccn.tv/myccn/JW_API5210.html. I set autostart=true but used an image for the initial file, and then modified the first two STOP/LOAD links to reference the same file with different START values.

Now to implement your suggestion! Thank you again :-)

RESULTS: http://www.ccn.tv/myccn/JW_API2.html

I switched the code to use JW Player 4.2, I specified a true streaming flash file, and I switched, as "how" suggested, from using the state listener to using the time listener to manage play versus seek. Much better now, just a tiny glitch in that it plays the first second before executing the seek.

I'm wondering if this is the best that can be done? It is definitely better than before.

The player has to be in PLAY or PAUSE mode to seek.

Therefore, the sequence has to be PLAY-SEEK or PLAY-PAUSE-SEEK.

No point in using the second sequence since you want to PLAY.

So there's going to be a momentary "glitch" after the player starts and before it seeks. Usually this is only audio so you could do MUTE-PLAY-SEEK-UNMUTE. I have done that in cases where I was jumping around or changing things and didn't want the audio "glitch".

However, since you are using a streaming server, you also have the "start" flashvar available. If you save the user's position in a cookie, you can jump to that position when the player is initially loaded in the next session.

I would also get rid of the createPlayer() wrapper function and the body onload. They are not needed with swfobject v2.1. Refer to my code above. Your code will execute faster and you won't have rendering anomalies that can occur when you wait until the page is fully loaded before loading the Flash content. Highly recommended by the developers of swfobject.

Sorry, "how", I was sloppy when I updated my code and missed a few details of your example. I have now removed the createPlayer wrapper (and body onload), specified flash player version 9.0.124, and added expressInstall. The video "glitch" (playing a second or so at the beginning of the video while seeking), is still there, but at least the code is cleaner. :-)

Yes, I am planning to save the user's position, to a cookie at a minimum, but ideally I should add a user option to save the position ("bookmark" to database) so that the user can resume at a different PC too.

After sleeping on this, I think maybe the right implementation is to dynamically generate an xml playlist containing the "chapters" (titles, timecodes, and duration, all using the same file url), and maybe include the Resume option as a "special" chapter... I plan to test this today.

@how

This flavour of your stateMonitor() function works for me:

function stateMonitor(obj){
if(obj.newstate == 'PLAYING' && seekFlag == true){
player.sendEvent('PLAY'); // trigger pause
}
if(obj.newstate == 'PAUSED' && seekFlag == true){
seekFlag = false;
var tmp = seek;
setTimeout(function(){ player.sendEvent('SEEK', tmp); }, 100);
// will seek and play
}
currentState = obj.newstate;
};

As you can see, for some reason the player had to be paused before firing the seek event. I also created a closure for setTimeout and captured the current value of seek in a temporary variable (this might not be need)

You could also add the flashvar "start=15" and then click the play button on the player. It will then automatically start at 15 seconds in the video.

Thanks JeroenW,

I was looking for this. It was really helpful.

Can I see it running? Can you show me some link that it's running perfectly?

For some reason, I choose to seek 65 and it starts at like 1:10. any ideas? I'm using a streaming server.

I'm using flashvars like:
streamer: (RTMP:URL on flash server folder),
File: this is actually an .mp4 file, not an FLV ...

JW Player 5.1.897 licensed

Everything else is pretty much just as you specified above in the second example titled JW API Example 5-1-0-0 - JW FLV Media Player

I wonder if there is something screwy with the options on Camtasia that the content folks are using to publish this video?

Thanks for any help u might have on this. :) Happy Thanksgiving!

Chances are the file you are loading is missing a keyframe at that exact second you are trying to seek to, so it is going to to the next available. Also, a link would be helpful.