什么是WebRTC?
WebRTC已经在我们的浏览器中
三个接口
MediaStream(getUserMedia)
MediaStream API为WebRTC提供了从设备的摄像头、话筒获取视频、音频流数据的功能
W3C标准
如何调用
浏览器兼容性
由于浏览器实现不同,他们经常会在实现标准版本之前,在方法前面加上前缀,所以一个兼容版本就像这样
var getUserMedia = (navigator.getUserMedia ||
navigator.webkitGetUserMedia ||
navigator.mozGetUserMedia ||
navigator.msGetUserMedia);
一个超级简单的例子
这里写一个超级简单的例子,用来展现getUserMedia的效果:
<!doctype html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>GetUserMedia实例</title>
</head>
<body>
<video id="video" autoplay></video>
</body>
<script type="text/javascript">
var getUserMedia = (navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia);
getUserMedia.call(navigator, {
video: true,
audio: true
}, function(localMediaStream) {
var video = document.getElementById('video');
video.src = window.URL.createObjectURL(localMediaStream);
video.onloadedmetadata = function(e) {
console.log("Label: " + localMediaStream.label);
console.log("AudioTracks" , localMediaStream.getAudioTracks());
console.log("VideoTracks" , localMediaStream.getVideoTracks());
};
}, function(e) {
console.log('Reeeejected!', e);
});
</script>
</html>
将这段内容保存在一个HTML文件中,放在服务器上。用较新版本的Opera、Firefox、Chrome打开,在浏览器弹出询问是否允许访问摄像头和话筒,选同意,浏览器上就会出现摄像头所拍摄到的画面了
约束对象(Constraints)
详情见Resolution Constraints in Web Real Time Communications draft-alvestrand-constraints-resolution-00
RTCPeerConnection
信令
需要信令来交换的信息有三种:
* session的信息:用来初始化通信还有报错
* 网络配置:比如IP地址和端口啥的
* 媒体适配:发送方和接收方的浏览器能够接受什么样的编码器和分辨率
这些信息的交换应该在点对点的流传输之前就全部完成,一个大致的架构图如下:
通过服务器建立信道
NAT/防火墙穿越技术
我们可以使用Google的STUN服务器:stun:stun.l.google.com:19302
,于是乎,一个整合了ICE框架的架构应该长这个样子
浏览器兼容
var PeerConnection = (window.PeerConnection ||
window.webkitPeerConnection00 ||
window.webkitRTCPeerConnection ||
window.mozRTCPeerConnection);
创建和使用
//使用Google的stun服务器
var iceServer = {
"iceServers": [{
"url": "stun:stun.l.google.com:19302"
}]
};
//兼容浏览器的getUserMedia写法
var getUserMedia = (navigator.getUserMedia ||
navigator.webkitGetUserMedia ||
navigator.mozGetUserMedia ||
navigator.msGetUserMedia);
//兼容浏览器的PeerConnection写法
var PeerConnection = (window.PeerConnection ||
window.webkitPeerConnection00 ||
window.webkitRTCPeerConnection ||
window.mozRTCPeerConnection);
//与后台服务器的WebSocket连接
var socket = __createWebSocketChannel();
//创建PeerConnection实例
var pc = new PeerConnection(iceServer);
//发送ICE候选到其他客户端
pc.onicecandidate = function(event){
socket.send(JSON.stringify({
"event": "__ice_candidate",
"data": {
"candidate": event.candidate
}
}));
};
//如果检测到媒体流连接到本地,将其绑定到一个video标签上输出
pc.onaddstream = function(event){
someVideoElement.src = URL.createObjectURL(event.stream);
};
//获取本地的媒体流,并绑定到一个video标签上输出,并且发送这个媒体流给其他客户端
getUserMedia.call(navigator, {
"audio": true,
"video": true
}, function(stream){
//发送offer和answer的函数,发送本地session描述
var sendOfferFn = function(desc){
pc.setLocalDescription(desc);
socket.send(JSON.stringify({
"event": "__offer",
"data": {
"sdp": desc
}
}));
},
sendAnswerFn = function(desc){
pc.setLocalDescription(desc);
socket.send(JSON.stringify({
"event": "__answer",
"data": {
"sdp": desc
}
}));
};
//绑定本地媒体流到video标签用于输出
myselfVideoElement.src = URL.createObjectURL(stream);
//向PeerConnection中加入需要发送的流
pc.addStream(stream);
//如果是发送方则发送一个offer信令,否则发送一个answer信令
if(isCaller){
pc.createOffer(sendOfferFn);
} else {
pc.createAnswer(sendAnswerFn);
}
}, function(error){
//处理媒体流创建失败错误
});
//处理到来的信令
socket.onmessage = function(event){
var json = JSON.parse(event.data);
//如果是一个ICE的候选,则将其加入到PeerConnection中,否则设定对方的session描述为传递过来的描述
if( json.event === "__ice_candidate" ){
pc.addIceCandidate(new RTCIceCandidate(json.data.candidate));
} else {
pc.setRemoteDescription(new RTCSessionDescription(json.data.sdp));
}
};
实例
由于涉及较为复杂灵活的信令传输,故这里不做简短的实例,可以直接移步到最后
RTCDataChannel
使用DataChannel
我们可以使用channel = pc.createDataCHannel("someLabel");
来在PeerConnection的实例上创建Data Channel,并给与它一个标签
DataChannel使用方式几乎和WebSocket一样,有几个事件:
* onopen
* onclose
* onmessage
* onerror
两个暴露的方法:
* close(): 用于关闭channel
* send():用于通过channel向对方发送数据
通过Data Channel发送文件大致思路
一个综合的Demo
SkyRTC-demo,这是我写的一个Demo。建立一个视频聊天室,并能够广播文件,当然也支持单对单文件传输,写得还很粗糙,后期会继续完善
使用方式
- 下载解压并cd到目录下
- 运行
npm install
安装依赖的库(express, ws, node-uuid) - 运行
node server.js
,访问localhost:3000
,允许摄像头访问 - 打开另一台电脑,在浏览器(Chrome和Opera,还未兼容Firefox)打开
{server所在IP}:3000
,允许摄像头和话筒访问 - 广播文件:在左下角选定一个文件,点击“发送文件”按钮
- 广播信息:左下角input框输入信息,点击发送
- 可能会出错,注意F12对话框,一般F5能解决
功能
视频音频聊天(连接了摄像头和话筒,至少要有摄像头),广播文件(可单独传播,提供API,广播就是基于单独传播实现的,可同时传播多个,小文件还好说,大文件坐等内存吃光),广播聊天信息