javascript 在 Safari 手机上播放(和重播)声音

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/10951524/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-26 11:36:12  来源:igfitidea点击:

Play (and replay) a sound on safari mobile

javascriptaudiomobile-safari

提问by TimPetricola

I need to play a sound when a new message appears on a website. It works fine on Chrome and Safari but I can't make it work on Safari mobile. I saw that the sound has to be initialised with a user action so I tried that:

当网站上出现新消息时,我需要播放声音。它在 Chrome 和 Safari 上运行良好,但我无法在 Safari 移动设备上运行。我看到声音必须用用户操作初始化,所以我尝试了:

var sound = new Audio('./path/to/my/sound.mp3');
var hasPlayed = false;

$('body').bind('click touchstart', function() {
  sound.load();
});    

sound.addEventListener('play', function() {
  hasPlayed = true;
});

var playSound = function() {
  if(hasPlayed) {
    sound.currentTime = 0;
  }
  sound.play();
}

Unfortunately, the sound still don't play. I also tried with the Buzzlibrary, and the issue is the same.

不幸的是,声音仍然无法播放。我也尝试过Buzz库,问题是一样的。

So, the question is : how can I play a sound programmatically on mobile browsers ?

所以,问题是:如何在移动浏览器上以编程方式播放声音?

回答by Jeroen

First of all: HTML5 audio support in Mobile Safari on iOS (5.01, 5.1) is rather limited. But I have managed to get some small 'event type' sounds working in my iPad 2 web apps. Since you are talking about only one sound file for your app, you don't have to fall back on audio sprites tricks (i.e. merging multiple MP3's into one MP3 file and changing the play position within the merged file depending on the sound you want to be played).

首先:iOS (5.01, 5.1) 上的 Mobile Safari 对 HTML5 音频的支持相当有限。但是我设法在我的 iPad 2 网络应用程序中获得了一些小的“事件类型”声音。由于您只为您的应用程序谈论一个声音文件,因此您不必依赖音频精灵技巧(即将多个 MP3 合并为一个 MP3 文件并根据您想要的声音更改合并文件中的播放位置播放)。

As you have noticed, you cannot play audio automatically in Mobile Safari, i.e. without the user clicking on some element. Technically speaking, the audio must be played(not loaded) in the same call stack as a click event. But you will probably experience a 0,5 second delay then, when Mobile Safari creates the audio object. Here is a solution to this 'problem':

正如您所注意到的,您无法在 Mobile Safari 中自动播放音频,即用户无需单击某个元素。从技术上讲,音频必须在与单击事件相同的调用堆栈中播放(未加载)。但是,当 Mobile Safari 创建音频对象时,您可能会遇到 0.5 秒的延迟。这是这个“问题”的解决方案:

  • At the start of your app (while loading/initializing), add a click handler to the HTML document that starts playing your audio file as soon as the user clicks/taps anywhere in the app. This will force Safari to start loading the audio.
  • Listen for the 'play' event that is triggered when the audio is ready to be played, and immediately pause.
  • Now start playing the audio (without delay) again when you need it.
  • 在您的应用程序开始时(在加载/初始化时),向 HTML 文档添加一个单击处理程序,一旦用户单击/点击应用程序中的任何位置,该处理程序就会开始播放您的音频文件。这将强制 Safari 开始加载音频。
  • 侦听音频准备好播放时触发的“播放”事件,并立即暂停。
  • 现在在需要时再次开始播放音频(无延迟)。

Here is some quick JavaScript code:

这是一些快速的 JavaScript 代码:

function initAudio() {
    var audio = new Audio('./path/to/my/sound.mp3');
    audio.addEventListener('play', function () {
        // When the audio is ready to play, immediately pause.
        audio.pause();
        audio.removeEventListener('play', arguments.callee, false);
    }, false);
    document.addEventListener('click', function () {
        // Start playing audio when the user clicks anywhere on the page,
        // to force Mobile Safari to load the audio.
        document.removeEventListener('click', arguments.callee, false);
        audio.play();
    }, false);
}

回答by mrpanda

For those that are coming across this problem and the solution by Jeroen is not working here is a solution that works and ensures the proper scoping is correctly enforced.

对于那些遇到这个问题并且 Jeroen 的解决方案在这里不起作用的人来说,这是一个有效的解决方案,并确保正确执行适当的范围。

Make sure initAudio is called on page load. I.e. in your Init function or for jquery inside the document.ready ($(function(){});)

确保在页面加载时调用 initAudio。即在您的 Init 函数中或在 document.ready ($(function(){});) 中的 jquery

function initAudio(){
    var audio = new Audio('./path/to/my/sound.mp3');
    var self = this;
    //not sure if you need this, but it's better to be safe
    self.audio = audio;
    var startAudio = function(){
                         self.audio.play();
                         document.removeEventListener("touchstart", self.startAudio, false);
                     }
    self.startAudio = startAudio;

    var pauseAudio = function(){
                         self.audio.pause();
                         self.audio.removeEventListener("play", self.pauseAudio, false);
                     }
    self.pauseAudio = pauseAudio;

    document.addEventListener("touchstart", self.startAudio, false);
    self.audio.addEventListener("play", self.pauseAudio, false);
}