使用 AudioContext (Web Audio API) 断开节点的问题

tob*_*sen 7 html javascript audio web-audio-api

我正在构建一个显示有关视频音频的信息的组件。我使用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)
Run Code Online (Sandbox Code Playgroud)

当组件被卸载时,我会这样做:

if (this.source && this.scriptNode) {
  this.source.disconnect(this.scriptNode)
  this.scriptNode.disconnect(window.audioContext.destination)
}
Run Code Online (Sandbox Code Playgroud)

我认为这会让我处于可以安全地创建和连接新节点的状态。但是下次挂载组件时,这个块会抛出前面提到的错误:

if (!this.source && !this.scriptNode) {
  this.source = window.audioContext.createMediaElementSource(video) // this throws the error
  this.scriptNode = window.audioContext.createScriptProcessor(4096, 1, 1)
}
Run Code Online (Sandbox Code Playgroud)

我可以做的一切全球性的,即把它去工作source,并scriptNodewindow而不是this。但如果我的视频元素发生变化,这将不起作用。这样做的正确方法是什么?

小智 3

您不会销毁使用 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);
Run Code Online (Sandbox Code Playgroud)