简体   繁体   English

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

[英]Play (and replay) a sound on safari mobile

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. 它适用于Chrome和Safari,但我无法在Safari移动设备上运行。 I saw that the sound has to be initialised with a user action so I tried that: 我看到声音必须通过用户操作初始化,所以我尝试了:

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 Buzz library, and the issue is the same. 我也试过Buzz库,问题是一样的。

So, the question is : how can I play a sound programmatically on mobile browsers ? 所以,问题是:如何在移动浏览器上以编程方式播放声音?

First of all: HTML5 audio support in Mobile Safari on iOS (5.01, 5.1) is rather limited . 首先:iOS(5.01,5.1)上的Mobile Safari中的HTML5音频支持相当有限 But I have managed to get some small 'event type' sounds working in my iPad 2 web apps. 但我已经设法在我的iPad 2网络应用程序中获得一些小的“事件类型”声音。 Since you are talking about only one sound file for your app, you don't have to fall back on audio sprites tricks (ie 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). 由于您只讨论应用程序的一个声音文件,因此您不必依赖于音频精灵技巧(即将多个MP3合并为一个MP3文件并根据您想要的声音更改合并文件中的播放位置玩了)。

As you have noticed, you cannot play audio automatically in Mobile Safari, ie without the user clicking on some element. 您已经注意到,您无法在Mobile Safari中自动播放音频,即用户无需单击某个元素。 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. 但是,当Mobile Safari创建音频对象时,您可能会遇到0.5秒的延迟。 Here is a solution to this 'problem': 这是这个'问题'的解决方案:

  • 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. 在应用程序启动时(加载/初始化时),在用户单击/点击应用程序中的任何位置时,立即向HTML文档添加单击处理程序,该文档开始播放音频文件。 This will force Safari to start loading the audio. 这将迫使Safari开始加载音频。
  • 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. 现在,当您需要时,再次开始播放音频(无延迟)。

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

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. 确保在页面加载时调用initAudio。 Ie in your Init function or for jquery inside the document.ready ($(function(){});) 即你的Init函数或者document.ready中的jquery($(function(){});)

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM