Reputation: 20409
I would like to play music (with HTML5 audio) and show some graphical elements at particular times (should be synced with audio timing).
Would it be OK to use JavaScript's window.setTimeout
function to do it?
setTimeout(function() {
requestAnimationFrame(function() {
// display something
});
}, 1400);
setTimeout(function() {
requestAnimationFrame(function() {
// display something else
});
}, 2300);
Or, are there any better ways to do this?
Upvotes: 4
Views: 952
Reputation:
setTimeout
only usually executes after the given delay, and when the browser's thread is clear.
So no, it isn't perfectly accurate, but I think that for your purposes it will be close enough, often less than 0.2% delay,
Image from this question
However, on a slower user's machine, the effect might be more noticeable, and using setTimeout isn't recommended.
Instead, you can use the timeupdate
event and the currentTime
property to more accurately match the audio,
var audio = document.querySelector('audio#my-audio');
audio.addEventListener('timeupdate', function(){
switch (this.currentTime){
case 1:
//stuff
break;
/* etc. */
}
}
currentTime
uses seconds to count though, so you'll have to make do with a less precise metronome, but the accuracy's there.
Upvotes: 3
Reputation: 60507
"Accurate enough" is subjective, but in general, no. You don't know when the audio will finish downloading and start playing, or if it will play through without buffering or being paused by the user.
Instead you could use the timeupdate
event and currentTime
property, to properly sync events to the timeline.
var exampleElement = document.getElementById('example');
var lastTime = 0;
exampleElement.addEventListener('timeupdate', function(e) {
var nowTime = this.currentTime;
//Check if just passed the 1.4 second time mark.
if (nowTime > 1.4 && lastTime < 1.4) {
//Add a message to the debug element.
var logElement = document.getElementById('log');
logElement.textContent += 'Do something at 1.4 seconds\n';
}
lastTime = nowTime;
});
<audio id="example" controls="controls" autoplay="autoplay">
<source src="http://media.w3.org/2010/07/bunny/04-Death_Becomes_Fur.mp4" type='audio/mp4'>
<source src="http://media.w3.org/2010/07/bunny/04-Death_Becomes_Fur.oga" type='audio/ogg; codecs=vorbis'>
</audio>
<pre id="log"></pre><!--debug element-->
Upvotes: 3
Reputation: 700192
If you are able to start the timeout at the same instance as the audio starts, then it's accurate enough. With a screen frequency of 60 Hz for example, you have 16 ms until the next frame, so it doesn't actually have to be that accurate.
Depending on what you are displaying, even a few frames off might be acceptable. Consider for example that animated film updates at a rate of 12 Hz (cinema film runs at 24 Hz, and animations are updated every other frame).
Note however that the timout callback runs on the same thread as everything else, so it will only be accurate as long as you don't have anything else running that occupies the main thread for too long. If you for example have some other event handlers that do some heavy work, that could delay the timeout enough to be visible.
Upvotes: 0