Setting the granularity of the HTML5 audio event 'timeupdate'

26,545

Solution 1

I'm sorry, but that's the way it works. From the html5 specs:

Every 15 to 250ms, or whenever the MediaController's media controller position changes, whichever happens least often, the user agent must queue a task to fire a simple event named timeupdate at the MediaController.

Also,

The event thus is not to be fired faster than about 66Hz or slower than 4Hz (assuming the event handlers don't take longer than 250ms to run). User agents are encouraged to vary the frequency of the event based on the system load and the average cost of processing the event each time, so that the UI updates are not any more frequent than the user agent can comfortably handle while decoding the video.

If you read through the specification, you can get the idea that timeupdate event is something of a "best effort" kind of event. It will fire when it can and always as long as it does not to affect performance too much.

You could filter the events discarding some from time to time to smooth the arrival times, but I'm afraid it's not possible to do the opposite.

Solution 2

It should be noted that you can read the currentTime property of a video much more often. If time is really critical, and you can live with a little bit of uncertainty, you can try this instead.

It is, however, a lot less elegant than using the tag's own timeupdate event.

setInterval(function () {
    console.log(audio.currentTime); // will get you a lot more updates.
}, 30);

In this case, you'll have to manage the interval yourself, make sure that you clear it before nulling the audio element. But it is a possibility.

I'm using this approach on a video element, but it should apply here, too.

Share:
26,545
udit
Author by

udit

Updated on January 14, 2020

Comments

  • udit
    udit over 4 years

    I'm trying to create a simple looping feature using HTML5 audio and have a very primitive solution as follows:

    $(audio).bind('timeupdate', function() {
      if (audio.currentTime >= 26){
        var blah = audio.currentTime; 
        audio.currentTime = 23;
        console.log(blah);
      }
    })
    

    This works fine but the only glitch here is that the timeupdate event doesnt trigger very consistently. For instance, the console.log above returned: 26.14031982421875

    26.229642868041992

    26.13462257385254

    26.21796226501465

    ...etc. (You get the idea..inconsistent times)

    Obviously this won't work for an application where the timing is important (music applications). So the obvious solution to me would be to increase the granularity with which the timeupdate event is triggered. I havent been able to find any API docs...but would love to know if there is a way to do this.

  • Foreever
    Foreever over 10 years
    I logged the current time and the interval is more than 500 ms sometime. IS this interval more for devices with low performance?
  • amenthes
    amenthes over 10 years
    we use this inside a cordova project that plays/pauses a video in tandem with a content-layer the user gets to control. In that case, we didn't have a performance issue with it. But it is true, you now have one more thing to do every few milliseconds. Instead of setInterval, you could also read the .currentTime whenever another event occurs (like user interaction). Or you could calculate a "safe margin" if you care about video position, but only "around" the 1 minute mark - set a timeout for 59 seconds and start a tighter interval after those 59 seconds.
  • August
    August over 8 years
    For shorter audio clips, this method is almost invisible
  • rogerdpack
    rogerdpack almost 8 years
    Many seem to prefer 250ms for whatever reason
  • ffxsam
    ffxsam over 7 years
    Probably better to use requestAnimationFrame instead of setInterval.
  • amenthes
    amenthes over 7 years
    Only in case you're updating a visual thing. We did not do this for two reasons: we did not display the current state (ok, we did, too, but for that the timeupdate-event was good enough) but compared it to an internal reference. Also, at that time, requestAnimationFrame was not widely supported.
  • rogerdpack
    rogerdpack over 6 years
    FWIW requestAnimationFrame is guaranteed "max 60 fps" it seems...so if you need to do anything with more granularity, use Interval I guess...
  • supersan
    supersan about 5 years
    This should be the accepted answer since it gives an actual solution instead of just saying it can't be done.. kudos for thinking out of the box and providing a solution!