如何避免 AudioContext 接口中的“HTMLMediaElement 先前已连接到不同的 MediaElementSourceNode”?

Bro*_*Lee 7 javascript audio visualizer reactjs audiocontext

我在 React 中使用 AudioContext 接口制作了一个音频可视化工具,我希望用户能够启用和禁用它。
可视化工具工作正常,我也可以禁用它(我只是删除了 vis 组件)

但是,当我想再次启用它时,它告诉我:“InvalidStateError:无法在“AudioContext”上执行“createMediaElementSource”:HTMLMediaElement 之前已连接到不同的 MediaElementSourceNode。”
我想我不能在一个音频元素上同时有 2 个 ElementSource。但我无法解决这个错误。
我尝试在 useEffect 挂钩中返回audiocontext.close() ,以便我可以创建一个新的MediaElementSource(不确定它是否以这种方式工作),但它不会改变任何内容。
也许音频元素上有一个属性可以告诉我是否已经存在 MediaElementSource ?(我什么也没找到)

或者,AudioContext 接口对我来说有点太难了,因为我只是 React 的初学者,而且我只是复制粘贴现有的可视化工具......

谢谢您的帮助!

这是我的可视化组件中的一些代码:

useEffect(() => {
  var context = new AudioContext(); //Some visualiser stuff
  var src = context.createMediaElementSource(audio);// The error is here
  src.crossOrigin = "anonymous";
  var analyser = context.createAnalyser();
  src.connect(analyser);
  analyser.connect(context.destination);
  analyser.fftSize = 1024;

  // Some canvas stuff here
  //

  return () => {
    context.close() // doesn't work ?
  };
}, [somedeps]);

return  <canvas>...</canvas>
Run Code Online (Sandbox Code Playgroud)

小智 2

我有完全相同的问题。

\n

根据错误消息,您不需要 useEffect 中的依赖项(因为src只需要定义一次,否则您将收到错误)。

\n

相反,保存src到状态并在音频更改时使用两个useEffect来访问更改:src

\n

\r\n
\r\n
import React, { useEffect, useState } from "react";\n\n  const [source, setSource] = useState(null);\n\n  useEffect(() => {\n    if (window !== undefined) {\n      const AudioContext = window.AudioContext || window.webkitAudioContext;\n      const ctx = new AudioContext();\n      \n      //declare source just once\n      const src = ctx.createMediaElementSource(audio);\n      setSource(src);\n      \n      //connect analayser to source\n      const analayser = ctx.createAnalyser();\n      src.connect(analayser);\n      analayser.connect(ctx.destination);\n    }\n  }, []);\n  \n    useEffect(() => {\n    console.log(source);\n    //result : MediaElementAudioSourceNode\xc2\xa0{mediaElement: audio, context: AudioContext, numberOfInputs: 0, numberOfOutputs: 1, channelCount: 2,\xc2\xa0\xe2\x80\xa6}\n    \n  }, [//use dependency here]);
Run Code Online (Sandbox Code Playgroud)\r\n
\r\n
\r\n

\n