【问题标题】:Only works on one-to-one of which was to be many-to-many, webrtc仅适用于一对一,其中多对多,webrtc
【发布时间】:2015-07-17 15:28:19
【问题描述】:

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

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

但我的问题是这种架构不允许客户端与多个人连接,即,当客户端尝试与第三人连接时,附加流会失败。客户端只能一对一连接。

我不知道错误是在 JavaScript 中还是我需要改进服务器。我该怎么做才能连接到所有加入的客户?

查看我的代码:

HTML

<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);

【问题讨论】:

  • 我可以一对一连接,但是当我连接第三个人时,第三个人只连接第一个人。第一个与第二个和第三个连接。第二个与第一个相连。第三个与第一个相连。我迷失在解决这个僵局中

标签: javascript php webrtc peer-connection


【解决方案1】:

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

编辑:

SimpleWebRTC 工作原理的一个非常简单的解释是,这是创建连接客户端的网状网络的一种选择(所有客户端都连接到其他客户端):

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

此架构与您的关键区别在于您正在创建 单个 对等连接,但您需要创建、存储和跟踪 数组对等连接,你必须将你的 websocket 消息映射到特定的对等点。

【讨论】:

  • 你可以更解释一下吗?我了解您的主要想法,但想更具体地知道该怎么做。您想要修复我的代码的方法吗...
  • @user5128061 “您想要修复我的代码的方法吗...” 不,您的代码无法修复,因为它存在根本缺陷。需要重写,或者使用支持多连接的库。
  • 你可以例如创建一个 peerconnections 数组,例如使用 remotepeerID 对其进行索引,然后在所有交换的消息中,添加一个 sourceID 和 PeerID 以将消息映射到数组中正确的 peerconnection。
  • @Ghedipunk 出于个人原因我不想使用库,那么你能告诉我重构我的代码的方法吗?
  • @user5128061 假设您编写了原始代码,您似乎完全有能力重构它以允许多个用户。另一方面,如果你复制和粘贴它,我不会给你更多的代码来复制和粘贴,这对你没有任何好处。您将一无所获,最终会得到一个您不了解且完全无法维护的混乱项目。每一个在你之后接触项目的开发者都会诅咒你的名字,以及我的名字来支持你。
【解决方案2】:

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

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

对于比这更大的组,您可能需要一些特殊设置,例如 MCU or Router solution,其中本质上是一个特殊服务器充当每个人都连接到的超级参与者,然后将每个人的视频混合在一起(通常与以更大的视频说话),或将每个人的视频转发给每个人(因为上传速度通常是瓶颈)。

【讨论】:

  • 理论上你说的我明白了,但在实践中不能应用,你能帮帮我吗?
  • 我再次更新了我的代码,试图实现,我可以一对一连接,但是当我连接第三个人时,第三个人只连接第一个人。第一个与第二个和第三个连接。第二个与第一个相连。第三个与第一个相连。我迷失在解决这个僵局中
  • @user5128061 在网格上看到 my other answer
猜你喜欢
  • 2017-08-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-12-31
  • 2018-02-03
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多