使用 MediaRecorder 录制后,音频将不再在浏览器上播放

Audio won't play anymore on browser after recording it with MediaRecorder

(请参阅 https://github.com/norbjd/wavesurfer-upload-and-record 了解可重现的最小示例)。

我正在使用 wavesurfer.js 将用户上传的音频显示为波形,我正在尝试添加一个功能来记录上传的音频的一部分。

所以我创建了一个“录制”按钮(现在只录制 5 秒的音频),点击它时使用以下代码。我正在使用 MediaRecorder API :

document
    .querySelector('[data-action="record"]')
    .addEventListener('click', () => {
        // re-use audio context from wavesurfer instead of creating a new one
        const audioCtx = wavesurfer.backend.getAudioContext();
        const dest = audioCtx.createMediaStreamDestination();
        const audioStream = dest.stream;

        audioCtx.createMediaElementSource(audio).connect(dest);

        const chunks = [];
        const rec = new MediaRecorder(audioStream);
        rec.ondataavailable = (e) => {
            chunks.push(e.data);
        }
        rec.onstop = () => {
            const blob = new Blob(chunks, { type: "audio/ogg" });
            const a = document.createElement("a");
            a.download = "export.ogg";
            a.href = URL.createObjectURL(blob);
            a.textContent = "export the audio";
            a.click();
            window.URL.revokeObjectURL(a.href);
        }

        wavesurfer.play();
        rec.start();

        setTimeout(() => {
            rec.stop();
            wavesurfer.stop();
        }, 5 * 1000);
    });

单击录制按钮时,wavesurfer 应该会播放 (wavesurfer.play()),但我的浏览器听不到任何声音(但我可以看到光标在移动)。在录制结束时(5 秒,用 setTimeout 设置),我可以下载录制的音频(rec.onstop 功能)并且声音在 VLC 或任何其他媒体播放器中正确播放。

但是,我无法再通过浏览器在网页上播放音频。我还能录音,而且录音能正常下载播放。

我想知道为什么第一次点击“录制”按钮后浏览器无法播放音频。我认为这一行:

audioCtx.createMediaElementSource(audio).connect(dest);

是问题,但没有它,我无法录制音频。

我还尝试重新创建一个新的 AudioContext 而不是使用 wavesurfer 的那个 :

const audioCtx = new AudioContext();

但效果并不好(同样的问题)。

我已经在一个最小的可重现示例中重现了该问题:https://github.com/norbjd/wavesurfer-upload-and-record,请随时检查。欢迎任何帮助!

您不需要单独的 audiocontext,但您需要使用与要录制的 audionode 相同的 audiocontext(在您的情况下来自 wavesurfer.js)创建的 MediaStreamDestination,并且您需要将音频节点连接到该目的地。

您可以在此处查看捕获音频和屏幕视频的完整示例:

https://github.com/petersalomonsen/javascriptmusic/blob/master/wasmaudioworklet/screenrecorder/screenrecorder.js

(在 line 52 开始录制后,将音频节点连接到录制完成)

您可以在这里进行现场测试:https://petersalomonsen.com/webassemblymusic/livecodev2/?gist=c3ad6c376c23677caa41eb79dddb5485

(切换捕捉复选框开始录音并按下播放按钮开始音乐,再次切换捕捉复选框停止录制)。

并且您可以看到在此视频中进行的实际录制:https://youtu.be/FHST7rLxhLM

如您在该示例中所见,录制完成后仍然可以播放音频。

请注意,此示例仅针对 Chrome 和 Firefox 进行了测试。

并且特别针对您使用 wavesurfer 的情况:

而不只是 backend: 'MediaElement',切换到 backend: 'MediaElementWebAudio',

而不是 audioCtx.createMediaElementSource(audio).connect(dest);,您可以更改为 wavesurfer.backend.sourceMediaElement.connect(dest); 以重用来自 wavesurfer 的现有源(但没有它也可以工作)。