如何在使用 navigator.mediaDevices.getUserMedia 录制音频时修复广泛的回声?

How to fix an extensive echoing while recording audio using navigator.mediaDevices.getUserMedia?

所以,我正在开发一个小型电子桌面应用程序,可以捕获桌面屏幕并录制视频和音频。 当我尝试向流中添加音频时,它开始出现非常糟糕的回声,我不确定为什么。

我正在使用:

这是一些代码。

当我只想捕获和录制视频时,我创建了这些约束:

const constraints = {
        audio: false,
        video: {
            mandatory: {
                chromeMediaSource: 'desktop',
                chromeMediaSourceId: source.id
            }
        }
    }

然后我将 is 传递给流:

const stream = await navigator.mediaDevices.getUserMedia(constraints)

它就像一个魅力。然而,当我开始添加音频时,它给了我回声:

const constraints = {
        audio: {
            mandatory: {
                chromeMediaSource: 'desktop',
            }
        },
        video: {
            mandatory: {
                chromeMediaSource: 'desktop',
            }
        }
    }

此外,我不能只将音频设置为 true。然后它给了我这个错误:

Uncaught (in promise) DOMException: Error starting screen capture

一个有趣的事实。当我在音频限制上转到 Mozilla documentation page 并使用演示按钮时,它也给了我回声。我尝试在 Edge 上进行,结果更好,但仍然有回声。那么它可以是音频编解码器吗?

Here 它表示从 Chrome 版本 62 开始默认支持 echoCancellation 约束。

Here 是 Github 上的分支,我试图在其中找到解决方案,但失败了。

Here 是我的 git 回购协议,如果您想更仔细地查看它。

PS:这是我第一次post来这里。如果我在这里做错了什么并且可以改进 post,请告诉我。谢谢!

我认为这里的简单解决方法是在页面上的播放中添加静音元素。

 // Preview the source in a video element
    videoElement.srcObject = stream
    videoElement.muted = true
    videoElement.play()

这将适用于所有浏览器,您仍然可以录制音频。

问题来自于尝试同时启动麦克风音频和计算机屏幕视频的单个流。要解决此问题,您需要先创建一个音频流,然后单独创建一个捕获计算机屏幕的视频流,最后将这些流合并为一个。

// create audio and video constraints
const constraintsVideo = {
    audio: false,
    video: {
        mandatory: {
            chromeMediaSource: 'desktop',
            chromeMediaSourceId: source.id
        }
    }
}
const constraintsAudio = {audio: true}

// create audio and video streams separately
const audioStream = await navigator.mediaDevices.getUserMedia(constraintsAudio)
const videoStream = await navigator.mediaDevices.getUserMedia(constraintsVideo)

// combine the streams 
const combinedStream = new MediaStream([...videoStream.getVideoTracks(), ...audioStream.getAudioTracks()])

合并流后,您可以使用 combinedStream,就像它起源于单个流一样。

我知道一个很晚的答案,但我试图理解你的问题,因为我目前正在通过 WebRTC 处理关于桌面捕获的回声消除问题,我想知道为什么你的初始方法(添加 chromeMediaSource: 'desktop' 作为对视频和音频的 mandatory 约束)导致回声,因为这是正确的用法,如 Electron 文档中所述。我认为标记为正确答案的 post 并不能真正解决问题。相反,在这种情况下,第二个答案是正确的。该问题与约束/流的使用无关。您听到回声的原因是,您通过将捕获的音频分配给 <video> 元素,再次隐式地将其添加到扬声器输出中。这创建了回声循环。为避免这种情况,正确的解决方案是像您在存储库中所做的那样将 <video> 元素静音。我尝试了你的代码并且记录工作正常(也使用静音 <video> 元素),当 re-enabling 代码部分立即捕获 video/audio 时(通过上述约束)。