javascript - 具有 3 个用户连接的 WebRTC

标签 javascript webrtc p2p

我现在正在实现来自 WebRTC Samples 的源代码通过使用网状拓扑成为 3 个用户连接。

但是,我的代码并没有像我想象的那样工作。我想我卡在调用函数 iceCallBack# (# 指的是数字 1、2、3),因为输出结果与原始结果相同。它只能连接 2 个用户。

我不知道如何以正确的方式修复它。

这是我一直在处理的一些 JavaScript 代码:

    var audio2 = document.querySelector('audio#audio2');
    var audio3 = document.querySelector('audio#audio3');
    var pc1;
    var pc2;
    var pc3;

    function call() {
      callButton.disabled = true;
      codecSelector.disabled = true;
      trace('Starting call');
      var servers = null;
      var pcConstraints = {
        'optional': []
      };
      pc1 = new RTCPeerConnection(servers, pcConstraints);
      trace('Created local peer connection object pc1');
      pc1.onicecandidate = iceCallback1;

      pc2 = new RTCPeerConnection(servers, pcConstraints);
      trace('Created remote peer connection object pc2');
      pc2.onicecandidate = iceCallback2;
      pc2.onaddstream = gotRemoteStream;
      trace('Requesting local stream');

      pc3 = new RTCPeerConnection(servers, pcConstraints);
      trace('Created remote peer connection object pc2');
      pc3.onicecandidate = iceCallback3; 
      pc3.onaddstream = gotRemoteStream2;
      trace('Requesting local stream');

      navigator.mediaDevices.getUserMedia({
        audio: true,
        video: false
      })
      .then(gotStream)
      .catch(function(e) {
        alert('getUserMedia() error: ' + e.name);
      });
    }


    //Description of pc1 creating offer to pc2
    function gotDescription1(desc) {
      desc.sdp = forceChosenAudioCodec(desc.sdp);
      trace('Offer from pc1 \n' + desc.sdp);
      pc1.setLocalDescription(desc, function() {
        pc2.setRemoteDescription(desc, function() {
          pc2.createAnswer(gotDescription2, onCreateSessionDescriptionError);
        }, onSetSessionDescriptionError);
      }, onSetSessionDescriptionError);
    }

    //Description of pc1 creating offer to pc3
    function gotDescription3(desc) {
      desc.sdp = forceChosenAudioCodec(desc.sdp);
      trace('Offer from pc1 \n' + desc.sdp);
      pc1.setLocalDescription(desc, function() {
        pc3.setRemoteDescription(desc, function() {
          pc3.createAnswer(gotDescription4, onCreateSessionDescriptionError); //Must edit gotDescription4
        }, onSetSessionDescriptionError);
      }, onSetSessionDescriptionError);
    }

    //Creating answer from pc2
    function gotDescription2(desc) {
      desc.sdp = forceChosenAudioCodec(desc.sdp);
      pc2.setLocalDescription(desc, function() {
        trace('Answer from pc2 \n' + desc.sdp);
        pc1.setRemoteDescription(desc, function() {
        }, onSetSessionDescriptionError);
      }, onSetSessionDescriptionError);
    }

    //Creating answer from pc3
    function gotDescription4(desc) {
      desc.sdp = forceChosenAudioCodec(desc.sdp);
      pc3.setLocalDescription(desc, function() {
        trace('Answer from pc2 \n' + desc.sdp);
        pc1.setRemoteDescription(desc, function() {
        }, onSetSessionDescriptionError);
      }, onSetSessionDescriptionError);
    }

    function iceCallback1(event) {
      if (event.candidate) {
        pc2.addIceCandidate(new RTCIceCandidate(event.candidate),
            onAddIceCandidateSuccess, onAddIceCandidateError);
        pc3.addIceCandidate(new RTCIceCandidate(event.candidate),
            onAddIceCandidateSuccess, onAddIceCandidateError);
        trace('Local ICE candidate: \n' + event.candidate.candidate);
      }
    }

    function iceCallback2(event) {
      if (event.candidate) {
        pc1.addIceCandidate(new RTCIceCandidate(event.candidate),
            onAddIceCandidateSuccess, onAddIceCandidateError);
        pc3.addIceCandidate(new RTCIceCandidate(event.candidate),
            onAddIceCandidateSuccess, onAddIceCandidateError);
        trace('Remote ICE candidate: \n ' + event.candidate.candidate);
      }
    }

    function iceCallback3(event) {
      if (event.candidate) {
        pc1.addIceCandidate(new RTCIceCandidate(event.candidate),
            onAddIceCandidateSuccess, onAddIceCandidateError);
        pc2.addIceCandidate(new RTCIceCandidate(event.candidate),
            onAddIceCandidateSuccess, onAddIceCandidateError);
        trace('Remote ICE candidate: \n ' + event.candidate.candidate);
      }
    }
<div id="audio">
      <div>
        <div class="label">Local audio:</div><audio id="audio1" autoplay controls muted></audio>
      </div>
      <div>
        <div class="label">Remote audio2:</div><audio id="audio2" autoplay controls></audio>
      </div>
      <div>
        <div class="label">Remote audio3:</div><audio id="audio3" autoplay controls></audio>
      </div>
</div>

注意:我是 webRTC 的新手。我可能在某些方面很愚蠢,请原谅我。

非常感谢。

最佳答案

3 个用户组成的网格意味着每个用户建立两个连接,一个连接到另外两个用户。在每个客户端,这是两个完全不同的 RTCPeerConnections,您不能在它们之间重复使用候选者,因为每个候选者都包含专门为媒体分配的端口号和它要发送到的目标。

如果您知道如何建立一个连接,那么您就知道如何建立两个连接。把事情分开。

关于javascript - 具有 3 个用户连接的 WebRTC,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36885362/

相关文章:

webrtc - Kurento/elasticRTC 上的多个 stun/turn 服务器

html - HTML5 Websockets 可以不使用服务器直接连接 2 个客户端(浏览器)吗? (点对点)

ruby - 使用 ruby​​ 连接到 torrent "swarm"或 DHT

javascript - Paper.js 无法正确调整 Canvas 大小

javascript - 使用 For 循环时图像未正确对齐

javascript - iPad 滚动 - 滚动期间会触发哪些事件?

javascript - 重新排序提交网址上的表单字段

ios - WebRTC工作流程

libjingle - webrtc如何使用libjingle?

node.js - 使用 socket.io、socket.io-p2p、socket.io-p2p-server 自动配对对等连接