You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

屏幕共享问题:更换Track后接收端流未更新的技术咨询

屏幕共享更换Track后接收端流不更新的解决方案

我实现了WebRTC屏幕共享功能,退出共享并更换Track后,发送端的流已完成更新,但接收端的流无变化。尝试使用replaceTrack方法时接收端能正常更新,但会抛出“轨道类型不同”的TypeError。

原代码1(仅更新本地流,接收端无变化)

this.videoHeight = 200
if(this.$store.rtcmConnection.streamEvents[this.screenId]){
    const test = await navigator.mediaDevices.getDisplayMedia();
    const track = this.$store.rtcmConnection.streamEvents[this.screenId].stream.getTracks()[0]
    this.userIds.forEach(e => {
        Object.keys(this.$store.rtcmConnection.streamEvents).forEach((streamid) => {
            const event = this.$store.rtcmConnection.streamEvents[streamid];
            if(typeof event !== 'function'){
                if (event.userid == e){
                    if(event.stream.isVideo)
                    {
                        event.stream.removeTrack(track)
                        event.stream.addTrack(test.getTracks()[0])
                    }
                }
            }
        });
    })
}else{
    this.$store.rtcmConnection.addStream({
        screen: true,
        oneway: true,
    }) 
}

原代码2(replaceTrack有效但报错)

if (this.$store.rtcmConnection.streamEvents[this.screenId]) {
    const test = await navigator.mediaDevices.getDisplayMedia({ video: true, audio: false });
    const streamTrack = test.getVideoTracks()[0]
    const track = this.$store.rtcmConnection.streamEvents[this.screenId].stream.getVideoTracks()[0]
    const event = this.$store.rtcmConnection.streamEvents[this.screenId];
    if (event.stream.isVideo) {
        this.userIds.forEach(async e => {
            const peerContainer = this.$store.rtcmConnection.peers[e]
            if (typeof peerContainer != 'undefined') {
                const connection = peerContainer.peer
                connection.getSenders().forEach(sender => {
                    sender.replaceTrack(streamTrack, event.stream)
                })
            }
        })

        event.stream.removeTrack(track)
        event.stream.addTrack(streamTrack)
    }
} else {
    this.$store.rtcmConnection.addStream({
        screen: true,
        oneway: true,
    })
}

问题分析

  1. 第一段代码仅修改了本地MediaStream,但WebRTC不会自动将本地流的轨道变更同步到远端,因此接收端无法感知到轨道替换。
  2. 第二段代码使用replaceTrack是正确的同步方式,但错误地遍历了所有sender(包括音频sender),将视频轨道替换到音频sender上,导致“轨道类型不同”的TypeError。

修正后的代码

if (this.$store.rtcmConnection.streamEvents[this.screenId]) {
    // 获取新的屏幕共享视频轨道
    const test = await navigator.mediaDevices.getDisplayMedia({ video: true, audio: false });
    const newVideoTrack = test.getVideoTracks()[0];
    const event = this.$store.rtcmConnection.streamEvents[this.screenId];
    const oldVideoTrack = event.stream.getVideoTracks()[0];

    if (event.stream.isVideo) {
        // 遍历所有需要同步的远端Peer
        this.userIds.forEach(e => {
            const peerContainer = this.$store.rtcmConnection.peers[e];
            if (peerContainer) {
                const connection = peerContainer.peer;
                // 仅筛选视频类型的sender,避免替换音频轨道报错
                connection.getSenders().forEach(sender => {
                    if (sender.track?.kind === 'video') {
                        // 替换对应的视频轨道
                        sender.replaceTrack(newVideoTrack)
                            .catch(err => console.error('替换轨道失败:', err));
                    }
                });
            }
        });

        // 更新本地流(用于本地预览)
        event.stream.removeTrack(oldVideoTrack);
        event.stream.addTrack(newVideoTrack);
        // 停止旧轨道的采集,释放资源
        oldVideoTrack.stop();
    }
} else {
    this.$store.rtcmConnection.addStream({
        screen: true,
        oneway: true,
    });
}

关键修改点

  • 筛选视频Sender:通过sender.track?.kind === 'video'只处理视频发送器,避免操作音频sender导致类型不匹配错误。
  • 简化replaceTrack调用:无需传入第二个参数(stream),仅传入新轨道即可,WebRTC会自动关联到对应的流。
  • 释放旧资源:替换后调用oldVideoTrack.stop()停止旧轨道的采集,避免不必要的系统资源占用。

核心逻辑说明

WebRTC的PeerConnection不会自动同步本地MediaStream的轨道变更,必须通过RTCRtpSender.replaceTrack()方法主动将新轨道推送到远端。只要确保找到对应的视频sender并替换轨道,接收端会自动触发ontrack事件更新流,无需额外操作接收端代码。

内容的提问来源于stack exchange,提问作者Adares

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.06 04:46:29