在 MediaStream 上切换麦克风设备会导致自己声音的回声

Switching microphone device on MediaStream causes echo of own voice

我正在构建一个 Angular 应用程序,它允许 2 个用户使用 Openvidu 呼叫解决方案相互视频通话。

在此应用程序中,我开发了一项功能,可以更改您在通话中主动使用的摄像头或麦克风。

选择新麦克风后,在添加新麦克风之前,先前的麦克风轨道会停止并从流中删除。这个过程封装在下面的代码中:

async onMicrophoneSelected(event: any) {
        var currentMediaStream: MediaStream = this.localUsersService.getWebcamPublisher().stream.getMediaStream();
        var currentAudioTrack: MediaStreamTrack;
        var currentVideoTrack: MediaStreamTrack;

        var newAudioInfo: MediaDeviceInfo; // type here is MediaDeviceInfo as it will be specified from enumerateDevices()
        var newAudioTrack: MediaStreamTrack;
        var newVideoTrack: MediaStreamTrack;

        // Specifying current video & audio track being used on call
        currentMediaStream.getTracks().forEach((track) => {
            if (track.kind === 'audio') {
                currentAudioTrack = track;
                currentAudioTrack.stop();  // stopping old audio track here 
            }

            if (track.kind === 'video') {
                currentVideoTrack = track;
            }
        });

        // Looping through available devices
        await navigator.mediaDevices.enumerateDevices().then((res) => {
            res.forEach((device) => {
                // Checking for: the current inactive device
                if (device.kind === 'audioinput' && device.deviceId === event.value) {
                    newAudioInfo = device;
                }
            });
        });

        // Passing constraints that contain new deviceId for audio, then using replaceTrack() to replace audio  // this also promps user for new device permissions
        await navigator.mediaDevices.getUserMedia({ audio: { deviceId: { exact: newAudioInfo.deviceId } } }).then((stream) => {
            newAudioTrack = stream.getAudioTracks()[0];
        });

        // replaceTrack() used here to notify OpenVidu of new devices, where they will then be published and thus changes also seen by the other-end-user
        this.localUsersService
            .getWebcamPublisher()
            .replaceTrack(newAudioTrack)
            .then(() => {
                console.log(currentMediaStream.getTracks(), '<<<-- checking stream after changes');
            });
    }

以上代码成功运行后,最终结果应该是我在通话中主动使用的麦克风应该已更改为我选择的麦克风。

情况是这样,但是我面临的问题是这种变化也伴随着我自己的非常响亮的回声,这意味着一旦我切换麦克风,活动麦克风就会改变,我也可以通过那个麦克风听到自己的声音。

任何关于此的想法将不胜感激,感谢阅读。

注意:echoCancellation没有解决这个问题。

所以我已经在 Firefox、Safari 和 Google 浏览器上运行了,所以请随意使用此代码。

我遇到回声问题的原因是因为我是 运行 设置组件 ngOnInit() 中的 initwebcamPublisher()...此功能在启动时已经运行一次应用程序,再做一次会导致网络摄像头发布者出现某种重复。

删除我剩下的工作 onMicrophoneSelect():

async onMicrophoneSelected(event: any) {
        const audioSource = event?.value;

        if (!!audioSource) {
            // Is New deviceId different than older?
            if (this.oVDevicesService.needUpdateAudioTrack(audioSource)) {
                const mirror = this.oVDevicesService.cameraNeedsMirror(this.camSelected.device);
                this.openViduWebRTCService.unpublishWebcamPublisher();
                this.openViduWebRTCService.replaceTrack(null, audioSource, mirror);
                this.openViduWebRTCService.publishWebcamPublisher();
                this.oVDevicesService.setMicSelected(audioSource);
                this.micSelected = this.oVDevicesService.getMicSelected();
            }
            // Publish microphone
            this.publishAudio(true);
            this.isAudioActive = true;

            return;
        }

        // Unpublish microhpone
        this.publishAudio(false);
        this.isAudioActive = false;
    }

因此,一旦用户选择了新的麦克风,他们当前的摄像头和麦克风就会取消发布,导致它们对其他用户显示大约 5 毫秒的空白,然后重新出现来自新选择的麦克风的相同视频和音频

这里最重要的 3 个部分是:

  1. 正在使用 unpublishWebcamPublisher()
  2. 取消发布旧发布者
  3. 使用replaceTrack()方法更换麦克风
  4. 重新发布新发布者this.openViduWebRTCService.publishWebcamPublisher();

然而,这是一个很好的改进方法,可以消除由于 this.openViduWebRTCService.publishWebcamPublisher();

而导致相机和麦克风未发布时发生的瞬间空白屏幕