问题 Chrome背景选项卡中的自动播放声音


我有一个使用音频通知的HTML5游戏。

当用户搜索匹配的其他玩家时,他们经常更改标签以执行其他操作,并依赖音频通知来知道何时返回。 Chrome(桌面)更改为禁止音频通知后,此功能不再有效。

如何确保音频通知仍然在后台运行?


12872
2018-02-20 16:36


起源

我有Chrome 49.0.2623.75米,从2016-03-03,和 这个 适用于我的后台标签与setTimeout。 - Serge Seredenko
参考: stackoverflow.com/questions/14917531/... - Koustav Ray
这里有两个概念,我需要了解你需要哪些:首先​​是Notification API,它允许网站发送通知,即使它们没有被打开并且它们有声音选项,然后有一个概念背景选项卡发出声音。你需要哪些? - Siderite Zackwehdex
@SideriteZackwehdex是后者。 - Harry
您使用的是桌面还是Android ...我的假设是桌面,因为没有Android标签或提及Android。 - Tim Penner


答案:


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


3
2017-11-08 13:16



是的,我做了同样的事。 - Harry


例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() function存储文件 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>

在github上演示 


6
2018-03-22 22:34





在这里,背景标签仍然可以播放声音 <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在打开的选项卡之间进行通信。

试试吧

等等。

代码和一些注入的代码 <audio> 元素可以包装在用户脚本中,因此它可以在碰巧在前面的任何站点上运行。


1
2018-03-22 22:34