在Chrome后台标签中自动播放声音

15
我有一个使用音频通知的HTML5游戏。
当用户在匹配其他玩家时,他们经常切换标签并依靠音频通知来知道何时回来。但是,Chrome(桌面版)更改为禁止音频通知后,这不再起作用。
如何确保背景中仍然可以使用音频通知?

我使用的是Chrome 49.0.2623.75 m版本,发布日期为2016-03-03。在后台选项卡中,通过setTimeout函数,这个方法可以正常工作。 - Serge Seredenko
请参考以下链接: https://dev59.com/LGUp5IYBdhLWcg3w8bNB - Koustav Ray
@SideriteZackwehdex 是后者。 - Harry
你是在使用桌面端还是安卓端?我的假设是桌面端,因为没有安卓标签或提及安卓。 - Tim Penner
@Harry 我更新了我的答案并提供了另一个示例。新的示例使用 localStorage 将音频文件存储为 base64,然后播放嵌入的数据。 - Tim Penner
显示剩余2条评论
3个回答

8

对我有效的解决方案是在页面加载后播放一个小的空白声音(0.1秒就足够了)。之后,即使您切换到另一个选项卡,后台选项卡仍然可以在某些外部或内部事件上播放声音。


是的,我也这么做了。 - Harry
4
2019年这个还能用吗?我刚试了一下,在Chrome 71中不行。 - Juribiyan

7

示例1

这是一个示例,创建了一个 div 并使用 HTML5 <audio> 标签,如果不支持则回退到 <embed>,在点击按钮后 3 秒钟播放音频文件。

为了测试它,运行样例并点击按钮,然后切换标签并计数 3 秒钟。 即使此标签不是当前标签,您也应该在此标签上看到扬声器图标并在 3 秒钟后听到硬币掉落的声音。

function playCoinDrop() {
  soundDiv = document.createElement("div");
  soundDiv.innerHTML = '<audio autoplay="autoplay"><source src="http://themushroomkingdom.net/sounds/wav/smw/smw_coin.wav" type="audio/wav" /><embed hidden="true" autostart="true" loop="false" src="http://themushroomkingdom.net/sounds/wav/smw/smw_coin.wav" /></audio>';
}
<button onclick="setTimeout(playCoinDrop, 3000)">play sound</button>

你可以根据需要更换音频文件。

示例2 - localStorage

这里是一种更高级的方法,利用了localStorage,这可能是您最好的选择。这允许您通过将其下载为Base64并将其下载到localStorage中来预加载通知声音,然后可以在选项卡处于后台时调用播放它而不会导致额外的网络传输。

这种方法的一个主要优点是只有一个通知文件的下载,之后它就会从浏览器的localStorage本地播放。

downloadCoin()函数将文件存储在localStoarge中作为base64
playCoinDrop()动态创建一个div并播放base64数据
playCoinDropJS()播放base64数据而不创建任何div

function downloadCoin() {
  var coin = 'smw_coin.wav';
  var xhr = new XMLHttpRequest();
  xhr.open('GET', coin, true);
  xhr.responseType = 'blob';
  xhr.onload = function(e) {
    if (this.status == 200) {
      var blob = new Blob([this.response], {
        type: 'audio/wav'
      });
      var reader = new window.FileReader();
      reader.readAsDataURL(blob);
      reader.onloadend = function() {
        var coinB64 = reader.result;
        var myStorage = localStorage.setItem('coin_base64', coinB64)
      }
    }
  };
  xhr.send();
}

function playCoinDrop() {
  var coinB64 = localStorage.getItem('coin_base64');
  var soundDiv = document.createElement('div');
  soundDiv.innerHTML = '<audio autoplay="autoplay"><source src="' + coinB64 + '" type="audio/wav" />';
}

function playCoinDropJS(){
    var coinB64 = localStorage.getItem("coin_base64");
    var snd = new Audio(coinB64); 
    snd.play();
}

<button onclick="downloadCoin()">download</button>
<button onclick="setTimeout(playCoinDrop, 3000)">play sound</button>
<button onclick="setTimeout(playCoinDropJS, 3000)">play sound JS</button>

demo on github


1
这里,后台标签仍然可以播放来自<audio>元素的声音(Chrome 49.0.2623.87)。然而,如果Chrome阻止了这一点,解决方法是通知前台标签发生事件,并让它代替后台标签播放声音。
以下需要实现为用户脚本扩展程序,以便在任何标签上使用-作为演示,它仅在具有相同JSBin URL的两个标签之间工作:
var intercom = Intercom.getInstance();

document.addEventListener("visibilitychange", getVisible);

function getVisible (evt) {
  document.getElementById("fg-indicate").style.visibility = document.visibilityState;
  if (document.visibilityState == "visible") {    
     // tab comes to front => listen to intercom
     intercom.on('notice', play);
   } else {
     // kill callback
     intercom.off('notice', play);
     // call intercom with delay
     window.setTimeout(function f() {
       intercom.emit('notice', {message: 'Hello, all windows!'});
     }, 3000);
   }
}

function play() {
  document.getElementsByTagName("audio")[0].play();
}

它依赖于intercom.js库,并使用localstorage在打开的选项卡之间通信。
尝试一下:
- 在一个选项卡中打开https://jsbin.com/gerihijofe/1/edit?html,js,output - 然后在另一个选项卡中 - 切换选项卡 - 等待3秒钟,看看小扬声器图标出现在哪里 - 切换选项卡 - 等待3秒钟,看看小扬声器图标出现在哪里 - 以此类推。
代码和更多代码来注入<audio>元素可以被包装在用户脚本中,因此它可以运行在任何位于前台的网站上。

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