浏览器拦截针对自动播放音频时的默认拦截行为(Uncaught (in promise) NotAllowedError: play() failed because the user didn’t interact with the document first. https://goo.gl/xX8pDD)的处理方式
为什么会有这个错误?
遇到 Uncaught (in promise) NotAllowedError: play() failed because the user didn’t interact with the document first 这个错误,通常是因为现代浏览器对于 自动播放 音频或视频存在限制。浏览器会拦截未经用户互动(如点击或按键)就调用 play() 方法的行为,这是一种防止恶意网页自动播放音频的措施。
项目条件
- VUE项目
- 谷歌浏览器高版本。(搜索出来的是谷歌66版本后就开始有针对浏览器自动播放音频的拦截设置,目前在同事的谷歌121版本下还能自动播放音频,但是在130以上则会出现上述拦截错误)
解决思路
vue项目是单页面,在用户登陆的操作按钮上绑定一个audio标签,并且一起执行播放事件与暂停事件,就是为了让浏览器通过用户的登录操作认为是用户操作授权播放音频,拿到这个用户授权后,界面上再自动播放报警音频时则不会被浏览器拦截。
// @/assets/audio/sound.wav 为音频文件位置
<audio v-show="false" ref="audio" src="@/assets/audio/sound.wav" muted></audio>
// 登录按钮
<el-button @click.native.prevent="handleLogin" ></el-button>
methods: {
handleLogin() {
this.bypassBrowserSecurity();
this.$refs.loginForm.validate((valid) => {/*登录逻辑*/})
},
bypassBrowserSecurity() {
// Cookies是引用的一种缓存依赖,用法同 localStorage 或 sessionStorage
Cookies.remove('refreshAudio');
this.$refs.audio && this.$refs.audio.play();
this.$refs.audio && this.$refs.audio.pause();
}
}
如果用户再登录界面后刷新了,那么自动播放音频则会重新被浏览器拦截这个时候就需要增加一个全局的点击事件(或者是监听按键事件)来重新获取用户授权
// 在一个全局的vue界面中,监听浏览器的刷新事件,设定一个值
<audio ref="audio" src="@/assets/audio/sound.wav" controls loop></audio>
created() {
window.addEventListener('beforeunload', (event) => {
console.log('页面刷新或关闭');
Cookies.set('refreshAudio', 'yes');
});
},
mounted() {
this.refreshAudio();
},
methods: {
refreshAudio() {
let autoAudio = Cookies.get('refreshAudio');
if (autoAudio === 'yes') {
// 播放音频前需要用户主动与页面进行交互
const autoPlayAfterAnyClick = () => {
/*音频播放逻辑*/
this.$refs.audio && this.$refs.audio.play();
Cookies.remove('refreshAudio');
document.removeEventListener('click', autoPlayAfterAnyClick);
};
document.addEventListener('click', autoPlayAfterAnyClick);
}
}
}