我有个功能,就是网站中用户收到其他用户发送的消息时,会播放提示语音,但是突然有一天有个错误:
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方式进行播放
})
}