使用 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,因此请随时查看。欢迎任何帮助!

解决方法

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

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

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

(在 line 52 开始录音后完成将 audionode 连接到录音)

您可以在这里进行现场测试: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 的现有源(但也可以不使用它)。