只有在一对一的情况下才有效,而这是多对多的


Only works on one-to-one of which was to be many-to-many, webrtc

我正在为这种风格的视频通话开发一个会议风格的应用程序(多对多)。代码在GitHub上可用,但我没有太多的node.js经验,因此我决定使用PHP创建自己的服务器。

我使用WebSockets创建服务器。它很简单——它接收消息并将它们转发给所有其他连接的客户端(即,不是发送消息的客户端)。仅此而已——仅此而已;没有更少。

但是我的问题是,这个架构不允许客户端与不止一个人连接,也就是说,当客户端试图与第三人连接时,额外的流失败。客户端只能一对一连接。

我不知道错误是否在JavaScript或如果我需要改进服务器。我怎么做才能使它连接到所有加入的客户端?

查看我的代码:

<script type="text/javascript" src="http://127.0.0.1/scr/js/jquery.js"></script>
JavaScript

var Server = new WebSocket('ws://127.0.0.1:1805/'),
    myStream = null,
    peerConn = null,
    mediaConstraints = {
        'mandatory': {
            'OfferToReceiveAudio': true,
            'OfferToReceiveVideo': true
        }
    };

navigator.webkitGetUserMedia({
    audio: true,
    video: true
}, function(stream) {
    myStream = stream;
    $("body").append('<video width="320" height="240" muted="muted" autoplay="true" src="' + window.URL.createObjectURL(stream) + '"></video>');
    createPeerConnection();
    peerConn.addStream(myStream);
    peerConn.createOffer(function(sessionDescription) {
        peerConn.setLocalDescription(sessionDescription);
        console.log("Sending offer description");
        Server.send(JSON.stringify(sessionDescription));
    }, null, mediaConstraints);
}, function() {
    console.error('Error in my stream');
});
function createPeerConnection() {
    console.log('Creating peer connection');
    peerConn = new webkitRTCPeerConnection({
        'iceServers': [{
            'url': 'stun:stun.l.google.com:19302'
        }, {
            'url': 'turn:107.150.19.220:3478',
            'credential': 'turnserver',
            'username': 'subrosa'
        }]
    }, {
        'optional': [{
            'DtlsSrtpKeyAgreement': 'true'
        }]
    });
    peerConn.onicecandidate = function(event) {
        if (event.candidate) {
            Server.send(JSON.stringify({
                type: 'candidate',
                label: event.candidate.sdpMLineIndex,
                id: event.candidate.sdpMid,
                candidate: event.candidate.candidate
            }));
        } else {
            console.error('Candidate denied');
        }
    };
    peerConn.onaddstream = function(event) {
        console.log("Adding remote strem");
        $("body").append('<video width="320" height="240" autoplay="true" src="' + window.URL.createObjectURL(event.stream) + '"></video>');
    };
    peerConn.onremovestream = function(event) {
        console.log("Removing remote stream");
    };
}
Server.addEventListener("message", function(message) {
    var msg = JSON.parse(message.data);
    if(!myStream) {
        console.error('Error in my stream');
    }
    if (msg.type === 'offer') {
        createPeerConnection();
        console.log('Adding local stream...');
        peerConn.addStream(myStream);
        peerConn.setRemoteDescription(new RTCSessionDescription(msg));
        console.log("Sending answer to peer.");
        peerConn.createAnswer(function(sessionDescription) {
            peerConn.setLocalDescription(sessionDescription);
            Server.send(JSON.stringify(sessionDescription));
        }, null, mediaConstraints);
    } else if (msg.type === 'answer') {
        peerConn.setRemoteDescription(new RTCSessionDescription(msg));
    } else if (msg.type === 'candidate') {
        var candidate = new RTCIceCandidate({
            sdpMLineIndex: msg.label,
            candidate: msg.candidate
        });
        peerConn.addIceCandidate(candidate);
    }
}, false);

问题是您正在尝试使用单个对等连接,但这只适用于单个连接方。你必须为每一方都有一个额外的对等连接,并且能够将websocket消息与用户和特定的对等连接相关联。你可以自己做,或者使用像SimpleWebRTC这样的库来管理多个用户会话。

编辑:

SimpleWebRTC工作原理的一个非常简单的解释是这样的,这是创建连接客户端(所有客户端相互连接)的网状网络的一个选项:

  1. 客户端加入"房间"
  2. 客户端被通知之前加入房间的每个客户端
  3. 对于其他客户端,客户端创建一个新的对等连接并将其存储在已连接的对等端数组中
  4. 当消息通过websocket接收时,它们必须与Id相关联,用于映射到适当的对等连接

这个体系结构与您的体系结构的关键区别在于,您正在创建一个单个对等连接,但是您需要创建、存储和跟踪对等连接的数组,并且您必须将您的websocket消息映射到特定的对等体。

RTCPeerConnection本质上是两个客户端(对等体)之间的一对一连接,所以如果你想超越这一点,你必须聪明一点。

最简单的步骤是创建一个网格,本质上是为每个其他参与者设置一个PeerConnection,所有参与者都做同样的事情。这样你就会在客户端上传速度上遇到瓶颈,通常是3-4个参与者,通常是基于上传速度最低的参与者。

对于更大的小组,你可能需要一些特殊的设置,如MCU或路由器解决方案,其中本质上是一个特殊的服务器作为每个人连接的超级参与者,然后将每个人的视频混合在一起(通常是与任何人说话作为一个更大的视频),或者将每个人的视频转发给每个人(因为上传速度通常是瓶颈)。