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

基于AppRTC的P2P屏幕共享异常:仅本地可见如何修复?

问题描述

我基于AppRTC仓库(主仓库及src/collider模块)搭建了源码,当前音视频通话功能正常,但缺少屏幕共享选项。自行添加屏幕共享按钮后,仅共享者本地能看到画面,远端无法显示,相关代码如下,请问该如何修复?

Call.prototype.maybeGetMediaForScreenSharing_ = function() {
  var needStream = (this.params_.mediaConstraints.audio !== false || this.params_.mediaConstraints.video !== false);
  var mediaPromise = null;
  if (needStream) {
    var mediaConstraints = '{"audio":true,"video":{"optional":[{"minWidth":"1280"},{"minHeight":"720"},{"mediaSource":"screen"}],"mandatory":{}}}';
    mediaPromise = navigator.mediaDevices.getDisplayMedia({
      audio: true,
      video: true
    }).catch(function(error) {
      if (error.name !== 'NotFoundError') {
        throw error;
      }

      return navigator.mediaDevices.getDisplayMedia({
        audio: true,
        video: true
      });
    }).then(function(stream) {
      var videoTracks = this.localStream_.getVideoTracks();
      var audioTracks = this.localStream_.getAudioTracks();

      //this.onlocalstreamadded(stream);
      this.onremotestreamadded(stream);
    }.bind(this)).catch(function(error) {
      alert("Error");
      this.onError_('Error getting user media: ' + error.message);
      this.onUserMediaError_(error);
    }.bind(this));
  } else {
    mediaPromise = Promise.resolve();
  }
  return mediaPromise;
};
修复方案

你的代码存在几个核心问题,导致远端无法接收屏幕共享流,以下是具体修复步骤:

1. 修正本地流处理方法

你错误调用了this.onremotestreamadded(stream),这个方法是用来处理远端传入的媒体流的。本地屏幕共享流应该调用this.onlocalstreamadded(stream)完成本地渲染,同时关键是要将流的轨道更新到RTCPeerConnection中,才能推送给远端。

2. 更新RTCPeerConnection的媒体轨道

AppRTC在通话建立后,本地流已经和PeerConnection绑定,新增屏幕共享流需要将其轨道添加到PeerConnection,并发送新的会话描述(SDP)通知远端:

修改后的核心代码如下:

Call.prototype.maybeGetMediaForScreenSharing_ = function() {
  var needStream = (this.params_.mediaConstraints.audio !== false || this.params_.mediaConstraints.video !== false);
  var mediaPromise = null;
  if (needStream) {
    mediaPromise = navigator.mediaDevices.getDisplayMedia({
      audio: true,
      video: {
        width: 1280,
        height: 720
      }
    }).then(function(stream) {
      // 先处理本地屏幕共享流的显示
      this.onlocalstreamadded(stream);
      
      // 获取当前的PeerConnection实例(AppRTC中通常通过this.pcClient_.pc_获取)
      var pc = this.pcClient_.pc_;
      
      // 可选:移除原有的摄像头视频轨道(如果需要替换而非新增流)
      const existingVideoSenders = pc.getSenders().filter(sender => sender.track?.kind === 'video');
      existingVideoSenders.forEach(sender => pc.removeTrack(sender));
      
      // 将屏幕共享的音视频轨道添加到PeerConnection
      stream.getTracks().forEach(track => {
        pc.addTrack(track, stream);
      });
      
      // 创建新的Offer并更新本地SDP,然后发送给远端
      return pc.createOffer().then(offer => {
        return pc.setLocalDescription(offer);
      }).then(() => {
        // 通过AppRTC的信令通道发送更新后的SDP
        this.sendSdp_(pc.localDescription);
      });
    }.bind(this)).catch(function(error) {
      alert("获取屏幕共享失败: " + error.message);
      this.onError_('获取用户媒体错误: ' + error.message);
      this.onUserMediaError_(error);
    }.bind(this));
  } else {
    mediaPromise = Promise.resolve();
  }
  return mediaPromise;
};

3. 确保远端正确处理轨道更新

远端需要监听PeerConnection的ontrack事件,接收新的媒体轨道并更新渲染元素。在AppRTC现有逻辑基础上,可补充或调整远端流处理逻辑:

// 集成到AppRTC的远端流处理逻辑中
pc.ontrack = function(event) {
  const remoteVideo = document.getElementById('remote-video');
  if (event.track.kind === 'video') {
    remoteVideo.srcObject = event.streams[0];
  }
};

关键注意事项

  • 必须将屏幕共享轨道添加到RTCPeerConnection,并发送新的SDP通知远端,这是远端能收到流的核心前提
  • 不要混淆本地流和远端流的处理方法,本地流用onlocalstreamadded,远端流处理逻辑负责接收渲染
  • 若需要在摄像头和屏幕共享之间切换,记得移除旧轨道再添加新轨道,避免远端出现多个流

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.22 22:36:20