【问题标题】:HTML5 Audio stop functionHTML5 音频停止功能
【发布时间】:2013-01-27 21:01:00
【问题描述】:

我在点击导航中的每个链接时播放一个小音频片段

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 的音频 API 中没有直接事件

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

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

有什么建议吗?

【问题讨论】:

    标签: html html5-audio


    【解决方案1】:

    您可以尝试使用 stop() 代替:

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

    这应该有预期的效果。

    【讨论】:

    • 这在 Chrome 中不起作用。音频元素一直在加载音频,这是不应该发生的。
    • 在 Chrome 中,&lt;audio&gt; 继续加载,preload 属性强制为none&lt;source&gt; 的源代码被剥离。
    • 这行得通,谢谢。在旁注中,我很想知道为什么 w3c 决定不在规范中包含停止方法。
    【解决方案2】:

    首先你必须为你的音频元素设置一个 id

    在你的 js 中:

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

    var oldSrc = ply.src;// 只是为了记住旧的来源

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

    【讨论】:

    • 音频流的最佳解决方案
    • 好吧..这将对音频源文件发出另一个网络请求
    • 音频在加载之前不会播放,这会导致播放音频时出现不必要的延迟。
    • 在播放网络广播等流时问题的一个很好的解决方案,当切换暂停/播放时,Firefox 会重复最后一个块。非常感谢。
    • 感谢这个完美的工作
    【解决方案3】:

    我遇到了同样的问题。如果它是收音机,则停止应该停止流和播放转到 live。我看到的所有解决方案都有一个缺点

    • player.currentTime = 0 继续下载流。
    • player.src = ''raise 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 中,它会导致以下错误(在控制台中)[Security Error: Content at https://localhost/url.html may not load data from blob:https://localhost/cac32534-78b0-4a62-8355-cc8f1e708d64.] 它似乎没有负面影响,因为代码在此之后继续执行(与未捕获的异常不同)。
    【解决方案4】:

    这是我做 stop() 方法的方式:

    代码中的某处:

    audioCh1: document.createElement("audio");
    

    然后在stop()中:

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

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

    【讨论】:

      【解决方案5】:

      此方法有效:

      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 文件中有这个,我将它包含在我的 html 中,然后是任何将处理音频的脚本。

      然后你可以在音频对象上调用停止函数:

      audio.stop();
      

      最终出现带有“canplaythrough”的 Chrome 问题:

      我没有在所有浏览器中测试过,但这是我在 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 ...
      });
      

      奖励:

      请注意,您可以向 Audio 类(或任何本机 javascript 类)添加更多自定义方法。

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

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

      【讨论】:

      • function stopAudio(audio) { audio.pause(); this.audioStream.src = ""; } 这样做最终对我有用,并删除了 Chrome 浏览器中在页面上播放音频时出现的扬声器图标。在 Chrome 版本 59.0.3071.109 上测试
      • 一般来说,我不会推荐像这样扩展原型。音频繁重的应用程序可能针对不同的情况具有不同的停止功能,并且从长远来看,弄乱原型可能会导致错误
      【解决方案6】:

      从我自己的 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;
              }
      }
      

      事实证明,仅清除 currentTime 并不能在 Chrome 下将其剪切,还需要清除源并将其重新加载。希望这会有所帮助。

      【讨论】:

        【解决方案7】:

        作为旁注,因为我最近使用了已接受答案中提供的停止方法,根据此链接:

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

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

        【讨论】:

          【解决方案8】:

          它有时在 chrome 中不起作用,

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

          就这样改变,

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

          【讨论】:

            【解决方案9】:

            shamangeorge 写道:

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

            这确实会发生,暂停也会触发pause 事件,这两者都使得这种技术不适合用作“停止”方法。此外,如果启用了autoplay,则按照zaki 的建议设置src 将使播放器尝试将当前页面的URL 作为媒体文件加载(并且失败) - 不允许将src 设置为null;它将始终被视为 URL。除了破坏播放器对象之外,似乎没有提供“停止”方法的好方法,所以我建议只删除专用的停止按钮并提供暂停和后退按钮 - 停止按钮不会真正添加任何功能.

            【讨论】:

              【解决方案10】:

              这种方法是“蛮力”,但假设使用 jQuery 是“允许的”,它就可以工作。用 div 包围你的“玩家”&lt;audio&gt;&lt;/audio&gt; 标签(这里的 id 为“plHolder”)。

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

              那么这个 javascript 应该可以工作了:

              function stopAudio() {
                  var savePlayer = $('#plHolder').html(); // Save player code
                  $('#player').remove(); // Remove player from DOM
                  $('#FlHolder').html(savePlayer); // Restore it
              }
              

              【讨论】:

              • zaki 在上面的回答中解释了同样的事情,没有使用 jquery。
              • 我没有尝试过,但我不确定如果有多个 标签,他的方法是否有效。
              • #FlHolder 似乎是 #plHolder 的拼写错误
              • 回复@alok-jain 评论:我认为这个答案与@zaki 的答案完全不同。在这里,我们正在重新渲染 DOM 中的一个元素,在另一个答案中,他只是“空白”了玩家的 src 属性。
              【解决方案11】:

              我一直在寻找类似的东西,因为我制作了一个可以用来将声音相互分层以获得焦点的应用程序。我最终做的是 - 选择声音时,使用 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();
              

              然后,将子元素附加到文档以实际显示音频元素

              document.body.appendChild(audio);
              

              最后,当取消选择音频时,您可以完全停止并移除音频元素 - 这也会停止流式传输。

                          const audio = document.getElementById(`${clickedTrackId}-audio`) as HTMLAudioElement;
                          audio.pause();
                          audio.remove();
              

              【讨论】:

                【解决方案12】:

                我相信检查音频是否正在播放状态并重置 currentTime 属性会很好。

                if (sound.currentTime !== 0 && (sound.currentTime > 0 && sound.currentTime < sound.duration) {
                    sound.currentTime = 0;
                }
                sound.play();
                

                【讨论】:

                  【解决方案13】:

                  对我来说,该代码运行良好。 (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">...
                  

                  希望对您有所帮助。

                  【讨论】:

                    【解决方案14】:

                    我喜欢做的是使用 Angular2 完全删除控件,然后在下一首歌曲有音频路径时重新加载:

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

                    然后,当我想在代码中卸载它时,我会这样做:

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

                    分配下一首歌曲时,控件会从头开始完全重新创建:

                    this.song = this.songOnDeck;
                    

                    【讨论】:

                      【解决方案15】:

                      解决此错误的简单方法是捕获错误。

                      audioElement.play() 返回一个 Promise,因此以下带有 .catch() 的代码应该足以解决这个问题:

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

                      注意:为了向后兼容,您可能希望将箭头函数替换为匿名函数。

                      【讨论】:

                        【解决方案16】:

                        在 IE 11 中,我使用了组合变体:

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

                        只有 2 次重复会阻止 IE 在 pause() 之后继续加载媒体流并由此淹没磁盘。

                        【讨论】:

                          猜你喜欢
                          • 1970-01-01
                          • 1970-01-01
                          • 2014-07-16
                          • 1970-01-01
                          • 1970-01-01
                          • 1970-01-01
                          • 1970-01-01
                          • 1970-01-01
                          • 1970-01-01
                          相关资源
                          最近更新 更多