HTML5 Audio stop function
Asked Answered
R

19

224

I am playing a small audio clip on click of each link in my navigation

HTML Code:

<audio tabindex="0" id="beep-one" controls preload="auto" >
    <source src="audio/Output 1-2.mp3">
    <source src="audio/Output 1-2.ogg">
</audio>

JS code:

$('#links a').click(function(e) {
    e.preventDefault();
    var beepOne = $("#beep-one")[0];
    beepOne.play();
});

It's working fine so far.

Issue is when a sound clip is already running and i click on any link nothing happens.

I tried to stop the already playing sound on click of link, but there is no direct event for that in HTML5's Audio API

I tried following code but it's not working

$.each($('audio'), function () {
    $(this).stop();
});

Any suggestions please?

Restorative answered 12/2, 2013 at 14:12 Comment(0)
C
514

Instead of stop() you could try with:

sound.pause();
sound.currentTime = 0;

This should have the desired effect.

Craver answered 12/2, 2013 at 15:37 Comment(6)
This is not working in Chrome. The audio element keeps loading audio, which is not what should happen.Johnathan
In Chrome the <audio> keeps loading also with preload attribute forced to none and the <source>'s src stripped out.Mollie
This works, thanks. On a side note i'd love to know why the w3c decided to not include a stop method in the spec.Ruhr
Just this audio.load().Lawry
Thank you, I declare and use the audios in JS only and this worked like a charm.Gorgonzola
In case someone looking for more reference, here it is. developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElementGiordano
V
38

first you have to set an id for your audio element

in your js :

var ply = document.getElementById('player');

var oldSrc = ply.src;// just to remember the old source

ply.src = "";// to stop the player you have to replace the source with nothing

Voleta answered 21/3, 2013 at 5:29 Comment(4)
Best solution for audio streamingAdditament
well..that will make another network request for the audio source fileAgile
Audio won't play until loaded, and this will cause unwanted delay in playing audio.Computation
A nice solution of the problem when playing a stream like internet radio and Firefox repeats the last chunk when pause/play is toggled. Thank you a lot.Tinner
G
17

This method works:

audio.pause();
audio.currentTime = 0;

But if you don't want to have to write these two lines of code every time you stop an audio you could do one of two things. The second I think is the more appropriate one and I'm not sure why the "gods of javascript standards" have not made this standard.

First method: create a function and pass the audio

function stopAudio(audio) {
    audio.pause();
    audio.currentTime = 0;
}

//then using it:
stopAudio(audio);

Second method (favoured): extend the Audio class:

Audio.prototype.stop = function() {
    this.pause();
    this.currentTime = 0;
};

I have this in a javascript file I called "AudioPlus.js" which I include in my html before any script that will be dealing with audio.

Then you can call the stop function on audio objects:

audio.stop();

FINALLY CHROME ISSUE WITH "canplaythrough":

I have not tested this in all browsers but this is a problem I came across in Chrome. If you try to set currentTime on an audio that has a "canplaythrough" event listener attached to it then you will trigger that event again which can lead to undesirable results.

So the solution, similar to all cases when you have attached an event listener that you really want to make sure it is not triggered again, is to remove the event listener after the first call. Something like this:

//note using jquery to attach the event. You can use plain javascript as well of course.
$(audio).on("canplaythrough", function() {
    $(this).off("canplaythrough");

    // rest of the code ...
});

BONUS:

Note that you can add even more custom methods to the Audio class (or any native javascript class for that matter).

For example if you wanted a "restart" method that restarted the audio it could look something like:

Audio.prototype.restart= function() {
    this.pause();
    this.currentTime = 0;
    this.play();
};
Genovera answered 1/1, 2017 at 8:24 Comment(2)
function stopAudio(audio) { audio.pause(); this.audioStream.src = ""; } Doing this ended up working for me and removed the speaker icon in Chrome Browser that appears when audio is playing on the page. tested on Chrome Version 59.0.3071.109Poverty
In general, I wouldn't recommend extending prototypes like this. An audio-heavy application may have different stop functions for different cases and messing with prototypes is likely to lead to bugs in the long-term imhoRombert
L
17

I was having same issue. A stop should stop the stream and onplay go to live if it is a radio. All solutions I saw had a disadvantage:

  • player.currentTime = 0 keeps downloading the stream.
  • player.src = '' raise error event

My solution:

var player = document.getElementById('radio');
player.pause();
player.src = player.src;

And the HTML

<audio src="http://radio-stream" id="radio" class="hidden" preload="none"></audio>
Luthuli answered 12/9, 2017 at 9:37 Comment(1)
This works in Chrome and Firefox. However, in Firefox it results in the following error (in console) [Security Error: Content at https://localhost/url.html may not load data from blob:https://localhost/cac32534-78b0-4a62-8355-cc8f1e708d64.] It appears to have no negative effect as the code continues to execute after this (unlike an uncaught Exception).Respectful
I
16

Here is my way of doing stop() method:

Somewhere in code:

audioCh1: document.createElement("audio");

and then in stop():

this.audioCh1.pause()
this.audioCh1.src = 'data:audio/wav;base64,UklGRiQAAABXQVZFZm10IBAAAAABAAEAVFYAAFRWAAABAAgAZGF0YQAAAAA=';

In this way we don`t produce additional request, the old one is cancelled and our audio element is in clean state (tested in Chrome and FF) :>

Interjection answered 12/4, 2015 at 11:49 Comment(0)
A
6

It doesn't work sometimes in chrome,

sound.pause();
sound.currentTime = 0;

just change like that,

sound.currentTime = 0;
sound.pause();
Ardussi answered 8/11, 2018 at 9:31 Comment(0)
L
5

From my own javascript function to toggle Play/Pause - since I'm handling a radio stream, I wanted it to clear the buffer so that the listener does not end up coming out of sync with the radio station.

function playStream() {

        var player = document.getElementById('player');

        (player.paused == true) ? toggle(0) : toggle(1);

}

function toggle(state) {

        var player = document.getElementById('player');
        var link = document.getElementById('radio-link');
        var src = "http://192.81.248.91:8159/;";

        switch(state) {
                case 0:
                        player.src = src;
                        player.load();
                        player.play();
                        link.innerHTML = 'Pause';
                        player_state = 1;
                        break;
                case 1:
                        player.pause();
                        player.currentTime = 0;
                        player.src = '';
                        link.innerHTML = 'Play';
                        player_state = 0;
                        break;
        }
}

Turns out, just clearing the currentTime doesn't cut it under Chrome, needed to clear the source too and load it back in. Hope this helps.

Lotty answered 8/4, 2015 at 9:7 Comment(0)
C
4

As a side note and because I was recently using the stop method provided in the accepted answer, according to this link:

https://developer.mozilla.org/en-US/docs/Web/Guide/Events/Media_events

by setting currentTime manually one may fire the 'canplaythrough' event on the audio element. In the link it mentions Firefox, but I encountered this event firing after setting currentTime manually on Chrome. So if you have behavior attached to this event you might end up in an audio loop.

Corsetti answered 9/8, 2014 at 1:47 Comment(0)
K
2

shamangeorge wrote:

by setting currentTime manually one may fire the 'canplaythrough' event on the audio element.

This is indeed what will happen, and pausing will also trigger the pause event, both of which make this technique unsuitable for use as a "stop" method. Moreover, setting the src as suggested by zaki will make the player try to load the current page's URL as a media file (and fail) if autoplay is enabled - setting src to null is not allowed; it will always be treated as a URL. Short of destroying the player object there seems to be no good way of providing a "stop" method, so I would suggest just dropping the dedicated stop button and providing pause and skip back buttons instead - a stop button wouldn't really add any functionality.

Kira answered 23/11, 2014 at 22:59 Comment(0)
L
2

What's wrong with simply this?

audio.load()

As stated by the spec and on MDN, respectively:

Playback of any previously playing media resource for this element stops.

Calling load() aborts all ongoing operations involving this media element

Lawry answered 19/9, 2022 at 14:0 Comment(3)
This will reset the audio to its original state, pause should stop at some point and start again from the same point.Restorative
@AlokJain The question is about stop, not pause and then resume. Maybe update the title?Lawry
thanks for pointing this out, but this question is 9 years old, your answer might help somebody in future.Restorative
O
1

This approach is "brute force", but it works assuming using jQuery is "allowed". Surround your "player" <audio></audio> tags with a div (here with an id of "plHolder").

<div id="plHolder">
     <audio controls id="player">
     ...
     </audio>
<div>

Then this javascript should work:

function stopAudio() {
    var savePlayer = $('#plHolder').html(); // Save player code
    $('#player').remove(); // Remove player from DOM
    $('#FlHolder').html(savePlayer); // Restore it
}
Odrick answered 19/3, 2015 at 16:3 Comment(4)
Same thing is explained by zaki in his answer above, without use of jquery.Restorative
I didn't experiment with it, but I wasn't sure that his method would work if there were multiple <source> tags.Odrick
#FlHolder seems a typo for #plHolderMollie
In reply to @alok-jain comment: I think this answer is completely different from the @Voleta 's one. Here we are re-rendering an element in the DOM, in the other answer he's just "blanking" the src attribute of the player.Mollie
N
1

I was looking for something similar due to making an application that could be used to layer sounds with each other for focus. What I ended up doing was - when selecting a sound, create the audio element with Javascript:

                const audio = document.createElement('audio') as HTMLAudioElement;
                audio.src = getSoundURL(clickedTrackId);
                audio.id = `${clickedTrackId}-audio`;
                console.log(audio.id);
                audio.volume = 20/100;
                audio.load();
                audio.play();

Then, append child to document to actually surface the audio element

document.body.appendChild(audio);

Finally, when unselecting audio, you can stop and remove the audio element altogether - this will also stop streaming.

            const audio = document.getElementById(`${clickedTrackId}-audio`) as HTMLAudioElement;
            audio.pause();
            audio.remove();
Nibble answered 5/12, 2021 at 23:31 Comment(0)
A
1

If you have several audio players on your site and you like to pause all of them:

$('audio').each( function() {
    $(this)[0].pause();
});
Affiliation answered 12/5, 2022 at 6:41 Comment(0)
S
0

I believe it would be good to check if the audio is playing state and reset the currentTime property.

if (sound.currentTime !== 0 && (sound.currentTime > 0 && sound.currentTime < sound.duration) {
    sound.currentTime = 0;
}
sound.play();
Seabolt answered 21/4, 2016 at 19:18 Comment(0)
P
0

for me that code working fine. (IE10+)

var Wmp = document.getElementById("MediaPlayer");                
    Wmp.controls.stop();

<object classid="clsid:6BF52A52-394A-11D3-B153-00C04F79FAA6"
    standby="Loading áudio..." style="width: 100%; height: 170px" id="MediaPlayer">...

Hope this help.

Polygraph answered 2/2, 2017 at 14:0 Comment(0)
Y
0

What I like to do is completely remove the control using Angular2 then it's reloaded when the next song has an audio path:

<audio id="audioplayer" *ngIf="song?.audio_path">

Then when I want to unload it in code I do this:

this.song = Object.assign({},this.song,{audio_path: null});

When the next song is assigned, the control gets completely recreated from scratch:

this.song = this.songOnDeck;
Yaws answered 11/2, 2017 at 17:27 Comment(0)
B
0

The simple way to get around this error is to catch the error.

audioElement.play() returns a promise, so the following code with a .catch() should suffice manage this issue:

function playSound(sound) {
  sfx.pause();
  sfx.currentTime = 0;
  sfx.src = sound;
  sfx.play().catch(e => e);
}

Note: You may want to replace the arrow function with an anonymous function for backward compatibility.

Bangweulu answered 11/4, 2017 at 19:29 Comment(0)
M
0

In IE 11 I used combined variant:

player.currentTime = 0; 
player.pause(); 
player.currentTime = 0;

Only 2 times repeat prevents IE from continuing loading media stream after pause() and flooding a disk by that.

Mazel answered 27/8, 2020 at 10:29 Comment(0)
N
0

To deal with the chrome playing it from the start, do this:

sound.currentTime = 0;
sound.addEventListener('canplaythrough', () => {
  sound.pause();
});
Nasia answered 28/1 at 18:40 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.