HTML5音频停止功能

222

我正在为导航栏中的每个链接添加点击事件,以播放一个小的音频剪辑。

HTML 代码:

<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 代码:

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

到目前为止,它运行得很好。

问题在于当声音剪辑已经在播放时,我点击任何链接时都没有反应。

我尝试在链接的点击事件上停止已经播放的声音,但是在HTML5的Audio API中没有直接的事件可以做到这一点。

我尝试了以下代码但它不起作用。

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

有什么建议吗?

18个回答

505

你可以尝试使用pause(),而不是stop()

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

这样做应该会产生预期的效果。


8
这在Chrome中无法工作。音频元素一直在加载音频,这不是应该发生的事情。 - Pieter
4
在Chrome浏览器中,即使将preload属性强制设为none并剥离<source>标签的src属性,<audio>元素仍会持续加载。 - Alessandro Fazzi
14
可以,谢谢。顺便说一下,我很想知道为什么W3C决定不在规范中包含“停止”方法。 - Reahreic
2
只需要这个 audio.load() - morganney
谢谢,我只在JS中声明和使用音频,这个方法非常有效。 - Adam Dolson
如果有人需要更多的参考资料,这里提供一个链接。https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement - vee

37

首先您需要为音频元素设置一个ID

在您的JS代码中:

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

var oldSrc = ply.src;//仅用于记住旧源

ply.src = "";//要停止播放器,您必须将源替换为空


5
音频流媒体的最佳解决方案 - Hossein
2
好的,那将会为音频源文件发起另一个网络请求。 - Md. Arafat Al Mahmud
1
音频在加载完成之前无法播放,这会导致不必要的延迟。 - Abhi
当播放流媒体(如互联网广播)时,火狐浏览器在暂停/播放切换时会重复最后一块的问题有个好的解决方案。非常感谢。 - namikiri

17

我遇到了同样的问题。如果是电台,停止操作应该停止流,并使播放器进入直播状态。但是我看到的所有解决方案都存在一个缺点:

  • player.currentTime = 0会一直下载流。
  • player.src = ''会触发error事件。

我的解决方案:

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

而 HTML

<audio src="http://radio-stream" id="radio" class="hidden" preload="none"></audio>

这个在Chrome和Firefox上都能运行。但是,在Firefox中,它会导致以下错误(控制台中)[安全错误:https://localhost/url.html中的内容可能无法从blob:https://localhost/cac32534-78b0-4a62-8355-cc8f1e708d64中加载数据。] 但貌似没有负面影响,因为代码在此之后仍然继续执行(不像未捕获异常)。 - BReddy

16

这是我使用stop()方法的方式:

在代码的某个地方:

audioCh1: document.createElement("audio");

然后在stop()函数中:

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

这样我们不会产生额外的请求,旧的请求被取消了,我们的音频元素处于干净状态(在Chrome和FF中进行了测试):>


15

这种方法有效:

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

但是,如果你不想每次停止音频时都写这两行代码,你可以做其中的两件事情。我认为第二种方法更合适,但我不知道为什么“JavaScript标准之神”们没有将其标准化。

第一种方法:创建一个函数并传递音频

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

//then using it:
stopAudio(audio);

第二种方法(更受欢迎):扩展Audio类:

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

我在一个名为“AudioPlus.js”的 Javascript 文件中编写了以下代码,并在任何处理音频的 script 之前将其引入我的 html 中。

之后,您可以对音频对象调用 stop 函数:

audio.stop();

终于解决Chrome的"canplaythrough"问题:

虽然我没有在所有浏览器上测试过,但这是我在Chrome中遇到的一个问题。如果你尝试在一个附加了“canplaythrough”事件监听器的音频上设置currentTime,那么你将再次触发该事件,这可能会导致不良结果。

因此,解决方案与当你附加一个事件监听器时确实不希望它再次被触发的所有情况类似,就是在第一次调用后删除事件监听器。像这样:

//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:

需要注意的是,您可以向Audio类(或任何原生JavaScript类)添加更多自定义方法。

例如,如果您想要一个“重新启动”方法来重新启动音频,它可能看起来是这样的:

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

函数停止音频(audio) { audio.pause(); this.audioStream.src = ""; }这样做对我起了作用,并且在Chrome浏览器上移除了当页面上有音频播放时出现的扬声器图标。在Chrome版本59.0.3071.109上测试过。 - lasec0203
1
一般情况下,我不建议像这样扩展原型。具有音频重度应用程序可能具有不同的停止功能以适应不同情况,并且与原型进行操作可能会导致长期的错误。 - milesaron

6

有时在Chrome中无法正常工作,

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

只需像这样进行更改,

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

5

我自己编写了一个JavaScript函数来切换播放/暂停状态 - 因为我处理的是广播流,所以我希望清除缓冲区,以便收听者不会与广播电台失去同步。

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;
        }
}

原来,在Chrome浏览器中仅仅清除currentTime是不够的,还需要同时清除source并重新加载。希望这能有所帮助。

4
作为一则旁注,因为我最近在使用已被接受的答案中提供的停止方法,根据这个链接:

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

通过手动设置currentTime,可以在音频元素上触发“canplaythrough”事件。在链接中提到了Firefox,但我在Chrome上手动设置currentTime后遇到了这个事件的触发。因此,如果您将行为附加到此事件,则可能会陷入音频循环。

2

shamangeorge写道:

通过手动设置currentTime,可以在音频元素上触发“canplaythrough”事件。

的确如此,暂停也会触发“pause”事件,这两者都使得这种技术不适用于作为“停止”方法。此外,如zaki所建议的设置“src”将使播放器尝试将当前页面的URL作为媒体文件进行加载(并失败),如果启用了“autoplay” - 将“src”设置为“null”是不允许的;它将始终被视为URL。除了销毁播放器对象外,似乎没有好的方法提供“停止”方法,因此我建议只需放弃专用的停止按钮,提供暂停和跳过按钮即可 - 停止按钮实际上不会添加任何功能。


2

仅这样有什么问题?

audio.load()

根据规范MDN的说明:
播放此元素中任何先前正在播放的媒体资源将停止。
调用load()会中止涉及此媒体元素的所有正在进行的操作。

这将重置音频到其原始状态,暂停应该在某个点停止,然后从同一点重新开始。 - Alok Jain
@AlokJain 这个问题是关于停止,而不是暂停然后恢复。也许可以更新标题? - morganney
谢谢您指出这一点,但是这个问题已经有9年了,您的答案可能会帮助到未来的某个人。 - Alok Jain

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接