React Web Audio API - 播放、暂停和导出加载的音频文件

React Web Audio API - Play, pause and export loaded audio file

我的目的是使用 WEB 音频上传和收听音频文件 API。我在选择音频文件时能够听到它,但在暂停和播放之后遇到问题。我还需要将文件导出为 WAV 格式。我创建了一个简单的例子,任何帮助将不胜感激

加载音频并从文件输入播放

const onFileChange = (e) => {
    let file = e.target.files[0];
    console.log(file);
    setFile(file);

    let fileReader = new FileReader();
    fileReader.onload = function (ev) {
      audioContext.decodeAudioData(ev.target.result).then(function (buffer) {
        playSound(buffer);
      });
    };
    fileReader.readAsArrayBuffer(file);
  };

使用缓冲源播放声音

  const playSound = (buffer, time) => {
    source = audioContext.createBufferSource();
    source.buffer = buffer;
    source.connect(audioContext.destination);
    source.start(time);
    setIsPlaying(true);
  };

我在暂停和播放时遇到问题:

  const onPlayPause = (e) => {
    console.log("audioState", audioContext.state);
    console.log("duration", audioContext.currentTime);
    if (!isPlaying) {
      //source.start();
      setIsPlaying(true);
    } else if (audioContext.state === "running") {
      setPlayDuration(audioContext.currentTime);
      audioContext.suspend();
      setIsPlaying(false);
    } else if (audioContext.state === "suspended") {
      audioContext.resume();
    }
  };

导出音频:

  const exportAudioFile = () => {

    offlineContext.render().then((buffer) => {
      setRenderState('encoding');
      const handleMessage = ({ data }) => {
        var blob = new window.Blob([new DataView(data)], {
          type: 'audio/wav',
        });

    //blob = new Blob([buffer], { type: "audio/wav" });
    const url = window.URL.createObjectURL(blob);
      }

    window.URL.revokeObjectURL(url);
  })};

代码和框链接: https://codesandbox.io/s/react-audiocontext-pause-play-fw20u?file=/src/App.js

我对 React 功能组件中的持久化问题感到相当头疼。幸运的是,useRef 是一个很棒的工具:

https://reactjs.org/docs/hooks-reference.html#useref

正如文档所说,它本质上是 returns 一个容器,.current 属性 持续存在 跨重新渲染

我将你的代码分叉到 useRef 中:

https://codesandbox.io/s/react-audiocontext-pause-play-forked-si59u?file=/src/App.js:120-159

基本上,当您加载文件时,将闪亮的新 AudioContext 存储在 ref 的 .current 字段中,并在整个组件的其余部分引用它。您可以稍微清理一下,IE 将 .current 存储在一个常量范围内,以供您在其中使用它的函数使用。

两个关键点:

export default function App() {
   const audioCtxContainer = useRef(null);
   ...

    audioCtxContainer.current = new AudioContext();
    audioCtxContainer.current
        .decodeAudioData(ev.target.result)
        .then(function (buffer) {
          playSound(buffer);
        });

useRef 对于您希望在组件的生命周期内保留的任何可变对象都很有用。

如果有帮助请告诉我!