11

See title. I am trying to play an audio file 4 times in a row, every 300 milliseconds. However, the clip is longer than 300ms, so it ignores new play requests until the clip is done playing. I'm looking for some way to stop and restart the clip every 300ms.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
    <meta http-equiv="content-type" content="text/html;charset=UTF-8" />
</head>
<body>
    <audio id="note0440"><source src="0440.a4.wav" type="audio/wav"></audio>
    <script type="text/javascript">
        function playNote (loop) {
            var n = document.getElementById("note0440")
            if (loop > 4)
                return
            n.volume = 0.05
            // n.currentTime = 0
            n.pause()
            n.play()
            setTimeout("playNote("+(loop + 1)+")", 300)
        }
    </script>
    <div style="margin:50px"><button onclick="playNote(1)">Play Note</button></div>
</body>
</html>

This does not work. It does not stop and restart, whether or not n.currentTime = 0 is used.

Here's a WAV file if you need one for testing: http://popstrip.com/misc/0440.a4.wav

2
  • -Does running .stop() before running .play() work?- I've since actually read some doco - and looks like that there is no .stop(). But as a few have suggested, pausing then setting the time back to 0 should give the same effect.
    – Shadow
    Commented Nov 6, 2012 at 2:00
  • also, fyi, your doctype specifies a version of html which does not even support the audio tag. change it to <!DOCTYPE html>
    – Max DeLiso
    Commented Nov 6, 2012 at 2:46

4 Answers 4

33

Wherever you are calling the stop just do the following in the order of -

 n.pause();
 n.currentTime = 0;
 n.play();      
2
  • Have you tried this in Firefox? It works for me in Chrome, but not FF. Thanks!
    – user353885
    Commented Nov 6, 2012 at 2:24
  • As @user931794 and shadow points out - this must not be fully supported in Firefox yet, but this should be the proper method. I guess it's back to Flash for now. =/
    – user353885
    Commented Nov 6, 2012 at 2:34
4

from section 4.8.10.6 of the specification

media . duration Returns the length of the media resource, in seconds, assuming that the start of the media resource is at time zero.

Returns NaN if the duration isn't available.

Returns Infinity for unbounded streams.

media . currentTime [ = value ] Returns the official playback position, in seconds.

Can be set, to seek to the given time.

Will throw an InvalidStateError exception if there is no selected media resource or if there is a current media controller.

So the specification does not allow for seeks of less than one second. However, different browsers will all implement it a different way (of course). Some browsers may support this, but getting it to reliably work in all deployed browsers today will be a huge pain in the ass. Assuming that you could issue millisecond seeks, the other issue is that the js interpreter may not be able to fulfill your request in time, i.e. the processing of the seek takes longer than the value of the seek, which would lead to other difficulties.

My advice to you would be to abandon the html5 approach for now if you really need smaller than one second granularity for your seeks, and use a plugin or some code running natively on the host if at all possible.

7
  • 1
    That's handy to know. But I don't think he wants to seek - I think he just wants to stop it if goes for too long?
    – Shadow
    Commented Nov 6, 2012 at 2:02
  • stops and starts must occur on a seek boundary AFAIK
    – Max DeLiso
    Commented Nov 6, 2012 at 2:03
  • Makes sense for starts... didn't know about stops though? (Haven't tested though)
    – Shadow
    Commented Nov 6, 2012 at 2:13
  • 1
    What @shadow said - the objective is not sub-second seeking (say that 10 times fast) but to play the clip 4 times in a row quickly. I just want to hear the clip repeat quickly (every 300ms to be exact). Thanks!
    – user353885
    Commented Nov 6, 2012 at 2:20
  • Then that's Firefox's fault. I'm afraid I'm going to agree with @user931794 - it's not supported well enough yet. You could likely do this sort of thing using Flash.
    – Shadow
    Commented Nov 6, 2012 at 2:28
1

This answer seems to be correct https://stackoverflow.com/a/13243338/8554041 BUT I tried it in an audio element without controls attribute and it didn't work. It would only work with audioElement.currentTime=1 as mentioned by https://stackoverflow.com/a/13243333/8554041 but 1 second after 0 is too much time for my use case.

So I tried audioElement.currentTime=null and it worked! ✅ Here is my solution in a snippet.

<audio src="/file.mp3" id="audioElement" />

audioElement.play()
audioElement.currentTime = null

It worked on Chrome 87, Firefox 84, I'll be testing on other browsers soon and I'll update it here.

Thanks.

-2

This is a bit of a hack, but I do this:

<audio src="blah.wav" type="audio/wav" preload="preload" id="blah0"></audio>
<audio src="blah.wav" type="audio/wav" preload="preload" id="blah1"></audio>
<audio src="blah.wav" type="audio/wav" preload="preload" id="blah2"></audio>
<audio src="blah.wav" type="audio/wav" preload="preload" id="blah3"></audio>

var audioStore = [
  document.getElementById('blah0'),
  document.getElementById('blah1'),
  document.getElementById('blah2'),
  document.getElementById('blah3'),
];

var n = 0;

function playBlah () {
  // Cycle through the clips
  audioStore[n].play();
  n = (n+1)%4;
}

Do this for as many as you need. Bonus is, you don't lose the tail of your sound, so you can afford to use ambiance (games sometimes want the sounds to overlap for example).

There are more elegant ways of doing this. I would actually write a function that takes an audio filename, an id stem (like blah in the example) and a number of elements to cycle through (max simultaneous value for that sound), and returns a function that can be called to play the sound. This function will also add the elements to the page.

Finally, you should probably use at least MP3 and Wav to get the largest spread of x-browser compatibility, the more formats the better, as wave is major bandwidth hog.

Hope this helps. (I've used this technique in Chrome, Firefox, Ice Weasel) on Win, Mac OSX and Linux

Not the answer you're looking for? Browse other questions tagged or ask your own question.