4 步实现基于 WebRTC 的多方视频会议





5.00/5 (4投票s)
4 步轻松实现多方视频会议
引言
Simple-peer 是一个优秀的库,可以使开发 WebRTC 解决方案变得易如反掌。它最好的地方在于它优雅地隐藏了所有的复杂性,并为您提供了一个易于使用的 WebRTC 接口,用于视频会议和数据传输。由于屏幕共享几乎与传递视频数据相同,因此您也可以将其用于屏幕广播。
让我将其分解为几个简单的步骤。
步骤 1
从 https://github.com/feross/simple-peer 获取 simplepeer.min.js,并将其包含在您的 HTML 文件中。
第二步
找到一个 websocket 库,用于来回传递数据进行初始通信。
在我的例子中,我使用了 easyrtc (https://github.com/priologic/easyrtc)。
步骤 3
围绕 websocket 层编写一个包装器,以便在主代码中,socket 库不会被暴露。这样,您就可以随时更改内部 websocket
库,而无需更改 WebRTC 通信建立的代码。
这是我创建的一个名为 hub (hub.js) 的包装器。在 hub.js 内部,.on
方法用于监听 custom/user-defined
事件。每当有新的 peer 加入时,我都会抛出带有 peer id 的 app.peer
事件(例如在步骤 4 中)。 同样,还有一些由内部 websocket 库引发的其他事件,这些事件会妥善传递到 hub。
var hub = {
msgMap: {},
connect:function connect(url){
easyrtcConnect(url);
},
send: function(peerid, msgType, content){
easyrtc.sendDataWS(peerid, msgType, content);
},
sendToAll: function(msgType, content){
easyrtc.sendDataWS({targetRoom:"default"}, msgType, content);
},
on: function(type, callback){
this.msgMap[type] = callback;
},
event: function(peerid, type, msg){
var callback = this.msgMap[type];
if(callback){
callback(peerid, msg);
};
},
peerMap: {},
setPeer: function(peerid, peer){
this.peerMap[peerid] = peer;
},
getPeer: function(peerid){
return this.peerMap[peerid];
},
removePeer: function(peerid){
delete this.peerMap[peerid];
},
iteratePeers: function(callback){
var value;
for (var key in this.peerMap) {
value = this.peerMap[key];
callback(key, value);
}
}
};
步骤 4
如前所述,当新的 peer/用户加入时(即,在线/连接到 socket),我会通知 hub。
hub.event(easyrtcid, "app.peer", userid);
为了进行多方会议,最好的方法是让最新在线的用户在登录时向所有其他 peer 发送一个“hello”消息。easyrtc
库在加入时会立即给我提供在线连接的列表。从内部层,我抛出带有 easyrtc
id(即 socket.id
)的 app.peer
事件。对于多个连接(即用户),会多次抛出 hub.event(easyrtcid, "app.peer", userid)
。
hub.on('app.peer', function(peerid, userid){
hub.send(peerid, 'hello'); // sending hello
});
稍微比喻一下,就会得到以下结果
-----------------------|- HELLO -> User A
User D-->Sends-->------|- HELLO -> User B
-----------------------|- HELLO -> User C
当收到呼叫请求时,用户默认接受。
在接受时,我们创建用于 WebRTC
连接的 SimplePeer
对象。
请查阅 simple-peer 的文档以了解初始化和事件。
hub.on('hello', function (peerid, msg) {
var peer = new SimplePeer({ initiator: false, stream: localStream });
hub.setPeer(peerid, peer);
peer.on('signal', function (data) {
hub.send(peerid, 'signal', data);
});
peerCreated(peerid, peer);
hub.send(peerid, 'ack', '1'); // sending acknowledgement
});
请注意,上述事件处理程序用于接收新连接用户的“hello”,作为回报,我们发送一个“ack
”。
ON HELLO 用户 A ---- 发送 ACK ----> 用户 D
ON HELLO 用户 B ---- 发送 ACK ----> 用户 D
ON HELLO 用户 C ---- 发送 ACK ----> 用户 D
剩下的很简单,当发起通信的用户收到 ack
时,他/她会创建一个作为发起者的 SimplePeer
对象。剩下的就是将 SDP Offer 信息传递给另一方,当 simple-peer 库优雅地通过其 signal 事件通知时:peer.on('signal' .. )
。
hub.on('ack', function (peerid, msg) {
//debugger;
if(msg == "1"){
var peer = new SimplePeer({ initiator: true, stream: localStream});
hub.setPeer(peerid, peer);
peer.on('signal', function (data) {
hub.send(peerid, 'signal', data);
});
peerCreated(peerid, peer);
}
});
在 peerCreated
方法内部,我们根据 simple-peer 文档执行必要的措施。
function peerCreated(peerid, peer){
peer.peerid = peerid; // you can choose to skip this
//debugger;
peer.on('connect', function () {
console.log('CONNECT')
peer.send('call established .. ' + selfID);
});
peer.on('error', function (err) { console.log('error', err) });
peer.on('data', function (data) {
console.log('data: ' + data)
});
peer.on('stream', function (stream) {
console.log('new stream arrived .. ', this.peerid);
createRemoteVideoElement(peerid, stream);
});
peer.on('track', function (track, stream) {
console.log('new track arrived .. ', this.peerid);
createRemoteVideoTrackElement(peerid, track, stream);
});
peer.on('removestream', function (stream) {
//removeRemoteVideoElement(peerid);
console.log("stream removed .. ", peerid); // hardly called
});
peer.on('close', function () {
console.log("connection closed .. ", peerid);
removeRemoteVideoElement(peerid);
});
}
但是,要开始进行操作,我们需要获取摄像头和麦克风访问权限(用户媒体流),并将其存储在 localStream
变量中
// get video/voice stream
navigator.getUserMedia({ video: true, audio: true }, gotMedia, function () {})
// This method starts of proceedings
function gotMedia (ownstream) {
localStream = ownstream;
connectToSocket(); // once socket connects we receive "app.peer" on hub
var video = document.getElementById('me');
video.srcObject = ownstream;
video.play();
}
历史
- 2018 年 4 月 23 日:文章上传