前言
也许很多前端遇到过这个需求:消息提醒。一般来说,可以简单的实现绝不会用复杂的方式,audio 标签提供了这个功能。但是,新版的 chrome 浏览器禁止了 js 自动播放音频的功能,见鬼了。
音频播放
<audio src=”../audio.mp3″ id=”myaudio” class=”hide”></audio>
<script>
var audio = document.getElementById(‘myaudio’);
audio.play();
</script>
这是最简单的音频播放脚本,但是在 chrome 下,抛出异常:Uncaught (in promise) DOMException,原因是这种操作必须由用户发起。当然,这不是特例,像 F11 全屏操作,浏览器也是禁止脚本操作的。但是我们有这个需求,怎么破?
绝不屈服的脑洞
能否不操作 play 呢?chrome 不仅禁止了脚本自动调用 play,还禁止了 audio 的 autoplay 属性。但是,如果音频是静音状态,autoplay 属性还是可以生效的。意思是,你可以播放,但是不能干扰用户的视听。这就给我们提供了一个 hack 的方法:默认开启音频的静音播放,而且是循环播放,当我们需要提醒用户的时候,把声音打开,播放时间设置为 0 秒,播放完毕,关掉声音,继续循环。是的,音频一直在播放,但是用户听不见。只有我们想让用户听见的时候才能听见,客观上也能实现需求。
具体实现
<audio src=”../audio.mp3″ muted autoplay loop id=”myaudio” style=”display: none”></audio>
<script>
/*
* muted 静音
* autoplay 自动播放
* loop 循环播放
*/
var audio = document.getElementById(‘myaudio’);
var t1 = 3e3;// 如果是轮询,这个时间必须大于音频的长度。如果是 webscoket,应该设置一个状态 play,避免重复播放,如下:
var t2 = 2500;// 音频的长度,确保能够完整的播放给用户
var play = false;
funcrion run(){
if(play){
return false;
}
audio.currentTime = 0;// 设置播放的音频的起始时间
audio.volume = 0.5;// 设置音频的声音大小
audio.muted = false;// 关闭静音状态
play = true;
setTimeout(function(){
play = false;
audio.muted = true;// 播放完毕,开启静音状态
},t2);
}
setInterval(function(){
run();// 假装在轮询服务器,或者从 websocket 拉取数据
},t1);
</script>
结语
这个方法经过在 chrome 上的实测,可以使用。但是其他浏览器未做测试,据说有的浏览器,似乎是 IE 不支持 muted 属性,限于操作系统,没做测试,如果在 IE 运行有问题,可以给我提个醒。