【问题标题】:WebRTC - how to switch between getUserMedia and getDisplayMedia tracks inside RTCPeerConnectionWebRTC - 如何在 RTCPeerConnection 内的 getUserMedia 和 getDisplayMedia 轨道之间切换
【发布时间】:2020-12-01 12:04:35
【问题描述】:

我正在尝试开发一个应用程序,用户可以在其中使用 WebRTC 技术相互进行视频通话并共享他们的屏幕。我已经成功使用视频通话或屏幕共享应用程序,现在我正在尝试使其能够在同一个 RTCPeerConnection 内的通话期间通过按钮单击在 getUserMedia 和 getDisplayMedia 之间切换,但它不起作用。

这就是我认为它可以工作的方式:

            function onLogin(success) { 

                var configuration = { offerToReceiveAudio: true, offerToReceiveVideo: true, "iceServers" : [ { "url" : "stun:stun.1.google.com:19302" } ] }; 

                myConnection = window.RTCPeerConnection ? new RTCPeerConnection(configuration, { optional: [] }) : new RTCPeerConnection(configuration, { optional: [] }); 

                myConnection.onicecandidate = function (event) { 
                    console.log("onicecandidate");
                    if (event.candidate) send({ type: "candidate", candidate: event.candidate });
                };
                
                myConnection.ontrack=function(e){
                    try{remoteVideo.src = window.webkitURL?window.webkitURL.createObjectURL(e.streams[0]):window.URL.createObjectURL(e.streams[0])}
                    catch(err){remoteVideo.srcObject=e.streams[0]}
                }
                
                myConnection.ondatachannel=openDataChannel
                openDataChannel();
                
                startAVStream();
                //startSStream()
            };

            function startAVStream(enable){
                if(sStream)sStream.getTracks().forEach( function (track) {
                            try{myConnection.removeTrack( track, sStream );}
                            catch(e){}
                        } );
                        
                navigator.mediaDevices.getUserMedia({ video: true, audio: true }).then(s => {
                    if(!avStream){
                        avStream = s;
                        avStream.getTracks().forEach( function (track) {
                            myConnection.addTrack( track, avStream );
                        } );
                    }
                }, function (error) { console.log(error); }); 
            }
            
            function startSStream(enable){
                if(avStream)avStream.getTracks().forEach( function (track) {
                            try{myConnection.removeTrack( track, avStream );}
                            catch(e){}
                        } );
                        
                navigator.mediaDevices.getDisplayMedia({ video: true }).then(s => {
                    if(!sStream){
                        sStream = s;
                        sStream.getTracks().forEach( function (track) {
                            myConnection.addTrack( track, sStream );
                        } );
                    }
                }, function (error) { console.log(error); }); 
            }

谁能告诉我如何在同一个 RTCPeerConnection 内的轨道之间切换,或者我应该创建 2 个单独的 RTCPeerConnection - 一个用于视频/音频流,另一个用于屏幕共享?

任何帮助表示赞赏!谢谢!

【问题讨论】:

    标签: stream webrtc getusermedia


    【解决方案1】:

    您可以使用RTCRtpSender.replaceTrack 拼接屏幕捕获轨道。这不需要重新协商,因此延迟非常低。

    let newstream = navigator.mediaDevices.getDisplayMedia({});
    let newtrack = newstream.getTracks()[1];
    if(newtrack.kind !== 'video')
        throw new Error('Eek!?');
    pc.getSenders().forEach(async s => {
        if(s.track && s.track.kind === 'video')
            await s.replaceTrack(newtrack);
    });
    

    s.track 不是null 的测试处理您之前调用replaceTrack(..., null) 的情况。

    【讨论】:

    • 是的!有用!非常感谢!但现在我有另一个问题 - 当我只使用音频流时我会做什么?因为当我尝试添加 getDisplayMedia 流时它给了我一个错误。
    • 只需将两个出现的video 替换为audio
    • 不明白你的意思:(
    • 哪个流是纯音频流?如果要替换音轨,请执行与上述相同的操作,但使用“音频”而不是“视频”。如果您想将视频轨道添加到纯音频流中,则需要在 PC 上调用 addTrack,这需要重新协商。
    • 你好,这适用于我的 chrome。但是当我从 chrome 屏幕共享按钮停止屏幕共享时,我的远程流卡住了。请问有什么想法吗?
    【解决方案2】:
     shareScreen = () =>{
    const success = (stream) => {
      window.localStream = stream
      // this.localVideoref.current.srcObject = stream
      // localStream.replaceStream(stream);
      this.setState({
        localStream: stream
      })
    
      Object.values(this.state.peerConnections).forEach(pc => {
        pc.getSenders().forEach(async s => {
          console.log("s.track ",s.track);
          if(s.track && s.track.kind === 'video'){
            stream.getTracks().forEach(track => {
              // pc.addTrack(track, this.state.localStream)
              s.replaceTrack(track);   
            });
          }
        });
      });
    }
    const failure = (e) => {
      console.log('getUserMedia Error: ', e)
    }
    navigator.mediaDevices.getDisplayMedia({ cursor: true }).then(success).catch(failure)}
    

    【讨论】:

      猜你喜欢
      • 2018-10-13
      • 1970-01-01
      • 1970-01-01
      • 2019-05-09
      • 1970-01-01
      • 2020-04-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多