【问题标题】:Switching microphone device on MediaStream causes echo of own voice在 MediaStream 上切换麦克风设备会导致自己的声音回声
【发布时间】:2021-12-29 10:34:59
【问题描述】:

我正在构建一个 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 没有解决这个问题。

【问题讨论】:

  • 您好,您是否已经在不同的浏览器中测试过?如果结果不同?您能否测试一下注释掉 currentAudioTrack.stop() 行,因为 OV 的 Publisher.replaceTrack() 方法具有相同的功能。
  • 我可以建议先不要将 async/await 与 then 混合使用吗?它会解开你的代码中很多不清楚的东西(至少对我来说)。也看看developer.mozilla.org/en-US/docs/Web/API/RTCRtpSender/… - 应该非常相似。

标签: angular typescript webrtc openvidu


【解决方案1】:

所以我在 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. 使用replaceTrack()方法更换麦克风
  3. 重新发布新发布者this.openViduWebRTCService.publishWebcamPublisher();

不过,这是一个很好的改进方法,可以消除由于this.openViduWebRTCService.publishWebcamPublisher();而导致相机和麦克风未发布时出现的瞬间空白屏幕

【讨论】:

    猜你喜欢
    • 2012-01-22
    • 2013-04-13
    • 1970-01-01
    • 1970-01-01
    • 2014-10-31
    • 2011-08-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多