【问题标题】:Audio won't play anymore on browser after recording it with MediaRecorder使用 MediaRecorder 录制后,音频将不再在浏览器上播放
【发布时间】:2021-01-01 14:51:58
【问题描述】:

(请参阅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,因此请随时检查。欢迎任何帮助!

【问题讨论】:

    标签: javascript audio mediastream wavesurfer.js


    【解决方案1】:

    您不需要单独的音频上下文,但您需要使用与要录制的音频节点相同的音频上下文(在您的情况下来自 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 中的现有源(但没有这个也可以工作)。

    【讨论】:

    • 感谢您的回答。实际上,我已经用 wavesurfer.js 的现有上下文替换了新上下文:wavesurfer.backend.getAudioContext() 并遇到了同样的问题。但是我怎样才能得到“你已经拥有的 MediaStreamDestination”?再次感谢:)
    • 您应该使用来自 wavesurfer.js 的音频上下文创建媒体流目标:wavesurfer.backend.getAudioContext().createMediaStreamDestination()
    • 感谢您的快速回答。我已经更新了代码:github.com/norbjd/wavesurfer-upload-and-record/blob/e37bbd7/…,但仍然有问题。您还发现其他可能出错的地方吗?
    • 不只是backend: 'MediaElement',而是切换到backend: 'MediaElementWebAudio',,而不是audioCtx.createMediaElementSource(audio).connect(dest);,改为wavesurfer.backend.sourceMediaElement.connect(dest);
    • 哇,非常感谢!只需将 backend: 'MediaElement' 更改为 backend: 'MediaElementWebAudio' 就可以了!您能否更新您的答案,以便我接受?非常感谢!
    猜你喜欢
    • 1970-01-01
    • 2017-07-12
    • 2015-12-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-06-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多