WebRTC与3个用户连接

5
我现在正在实现来自WebRTC示例的源代码,使用网状拓扑结构将其变成3个用户的连接。
然而,我的代码并没有像我想象中的那样工作。我认为我卡在了调用函数iceCallBack#(#代表数字1、2、3)上,因为输出结果与原始结果相同。它只能连接两个用户。
我不知道如何以适当的方式修复它。

Here is some of my JavaScript code that I have been working on:

    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还不熟悉,可能会有些愚蠢,请见谅。

非常感谢。


抱歉,这不是一个调试网站。您可以提出一个问题吗? - jib
“RTCPeerConnection().addIceCandidate()” 可以同时使用两次吗?因为我想要双向通信。例如,A --> B,C。B --> A,C。C --> A,B。 - benji
你有一个可用的三方示例吗?我可能很蠢,我卡在你之前的地方,似乎无法超越它。 - kaioker2
@kaioker2 你成功理解了如何使其工作的想法吗? - Jatin Garg
@JatinGarg 不好意思,我没有。 - kaioker2
1个回答

11

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

如果您知道如何设置一个连接,那么您就知道如何设置两个连接。只需保持各自独立即可。


这个注释是关键,同时记得跟踪谁已连接和谁未连接,这样当新客户端加入时,您可以添加他们并直接流式传输,而无需重新发送邀请等内容。 - Kevin
我显然很无助,已经尝试了两周让三个用户使用它。我找不到任何教程或说明。你有一个可用的三方示例吗?每次我都会遇到信令问题,无法解开流。两台电脑很容易,但三台似乎几乎不可能。 - kaioker2

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接