我正在构建一个显示视频音频信息的组件。我使用AudioContext接口从HTML5视频元素中获取音频样本。它在我第一次创建组件时工作正常,但是当卸载组件然后在以后重新创建时,我收到以下错误消息:
未捕获的InvalidStateError:无法执行 'AudioContext'上的'createMediaElementSource':HTMLMediaElement已经存在 先前连接到不同的MediaElementSourceNode。
以下是我获取音频的方式:
const video = document.querySelectorAll('video')[0]
if (!window.audioContext) {
window.audioContext = new (window.AudioContext || window.webkitAudioContext)
}
if (!this.source && !this.scriptNode) {
this.source = window.audioContext.createMediaElementSource(video)
this.scriptNode = window.audioContext.createScriptProcessor(4096, 1, 1)
}
this.scriptNode.onaudioprocess = (evt) => {
// Processing audio works fine...
}
this.source.connect(this.scriptNode)
this.scriptNode.connect(window.audioContext.destination)
当卸载组件时,我会这样做:
if (this.source && this.scriptNode) {
this.source.disconnect(this.scriptNode)
this.scriptNode.disconnect(window.audioContext.destination)
}
我认为这会让我处于可以安全地创建和连接新节点的状态。但是下次安装组件时,此块会抛出前面提到的错误:
if (!this.source && !this.scriptNode) {
this.source = window.audioContext.createMediaElementSource(video) // this throws the error
this.scriptNode = window.audioContext.createScriptProcessor(4096, 1, 1)
}
我可以通过让所有内容全局化来实现它,即将source
和scriptNode
放在window
而不是this
上。但是,如果我的视频元素发生变化,那将无效。这样做的正确方法是什么?
答案 0 :(得分:1)
您没有销毁使用context.createMediaSourceElement创建的节点。您的页面视频元素没有改变,您所做的一切都是从音频图表中断开视频音频流。因此,视频元素仍然绑定到AudioNode,在这种情况下是' this.source'。而不是尝试重新创建源只是检测源是否已经定义。
if (this.source == undefined) {
// Build element
this.source = window.audioContext.createMediaElementSource(video);
}
this.scriptNode = window.audioContext.createScriptProcessor(4096, 1, 1)
this.source.connect(this.scriptNode);
this.scriptNode.connect(window.audioContext.destination);