WebRTC是一种支持网页浏览器进行实时语音对话或视频对话的技术。它允许直接在浏览器中进行点对点的通信,而无需任何插件。本文将介绍如何使用 WebRTC 实现视频会议和数据传输,包括屏幕共享功能。
首先,需要获取一个名为 simplepeer.min.js 的库,它提供了一个简洁的接口来处理WebRTC的复杂性。可以从以下 GitHub 地址获取这个库:
https://github.com/feross/simple-peer
然后,需要在 HTML 文件中包含这个库。
为了进行初始通信,需要一个 WebSocket 库。在这个例子中,使用了 easyrtc 库:
https://github.com/priologic/easyrtc
接下来,将编写一个包装器(wrapper)来隐藏 WebSocket 层的复杂性,这样就可以在不改变 WebRTC 通信建立代码的情况下,随时更换内部的 WebSocket 库。
创建了一个名为 hub.js 的包装器。在这个包装器中,使用 .on 方法来监听自定义事件。每当有新的对等方(peer)加入时,会触发一个名为 app.peer 的事件,并传递对等方的 ID。
var hub = {
msgMap: {},
connect: function(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);
}
}
};
当有新的对等方加入时,通过内部层通知 hub。例如,当 easyrtcid 获得时,触发 app.peer 事件。为了实现多方会议,最好的方式是让新上线的用户在登录时向所有其他对等方发送问候消息。
hub.on('app.peer', function(peerid, userid) {
hub.send(peerid, 'hello');
});
当呼叫请求到来时,用户默认接受。在接受的同时,创建一个 SimplePeer 对象用于WebRTC连接。请参考 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');
});
当用户收到问候消息后,他们将创建一个 SimplePeer 对象作为发起者。剩下的就是将 SDP Offer 信息传递给另一方,当 simple-peer 库通过其 signal 事件优雅地通知时。
hub.on('ack', function(peerid, msg) {
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;
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) {
console.log('stream removed ..', peerid);
removeRemoteVideoElement(peerid);
});
peer.on('close', function() {
console.log('connection closed ..', peerid);
removeRemoteVideoElement(peerid);
});
}
navigator.getUserMedia({ video: true, audio: true }, gotMedia, function() {});
function gotMedia(ownstream) {
localStream = ownstream;
connectToSocket();
var video = document.getElementById('me');
video.srcObject = ownstream;
video.play();
}