我有个功能,就是网站中用户收到其他用户发送的消息时,会播放提示语音,但是突然有一天有个错误:
DOMException: play() failed because the user didn't interact with the document first.
懵B吧,看字面意思就是说用户还没有和浏览器进行交互,不能播放,也就是说只有用户进行了点击页面等等操作,才可以进行播放语音。
懵B吧,怎么搞。
今天说一个可以解决的方法,当然不排除以也不可用,解决方案就是通过iframe引入一个线上音频,再将iframe插入到页面,就可以自动播放了。
废话不多说,直接上代码:
<iframe src="这里是线上音频地址" allow="autoplay 'src'"></iframe>
重点:iframe的allow属性一定要是autoplay
就这么简单,以下是完整的vue版本的示例,实现的功能就是用户收到信息后播放通知音频
组件:index.vue
<template> <iframe v-show="visible" src="//video-static.com/FlQUl4Tvbu7Akyk8m7lySW" allow="autoplay 'src'"></iframe> </template> <script> export default { data() { return { duration: 3000, closed: false, visible: false } }, watch: { closed(newVal) { if (newVal) { this.visible = false } } }, mounted() { this.startTimer() }, methods: { close() { this.closed = true if (typeof this.onClose === 'function') { this.onClose(this) this.$destroy(true) this.$el.parentNode.removeChild(this.$el) } }, startTimer() { if (this.duration > 0) { this.timer = setTimeout(() => { if (!this.closed) { this.close() } }, this.duration) } } } } </script>
index.js
import Vue from 'vue' import Index from './index.vue' let IframeConstructor = Vue.extend(Index) let instance let instances = [] let seed = 1 const AudioIframe = function(options) { if (Vue.prototype.$isServer) return options = options || {} let id = 'iframe_' + seed++ options.onClose = function() { AudioIframe.close(id) } instance = new IframeConstructor({ data: options }) instance.id = id instance.$mount() document.body.appendChild(instance.$el) instance.visible = true instances.push(instance) return instance } AudioIframe.close = function(id) { let len = instances.length let index = -1 for (let i = 0; i < len; i++) { if (id === instances[i].id) { index = i instances.splice(i, 1) break } } } export default AudioIframe
调用方法
let audioEl = this.$refs.msgAudio
let audioEl = this.$refs.msgAudio
const audioPromise = audioEl.play() // 返回的是Promise
if (audioPromise && audioPromise instanceof Promise) {
audioPromise.then(_ => {}).catch(_ => {
audioNotify() // 当播放被禁止时,在这里调用iframe方式进行播放
})
}