随着互联网高速发展,以及即将到来的5G时代,WebRTC做为前端互动直播和实时音视频的利器,也是将前端开发者们不可错过的学习领域。若是你如今只是听过而已,那你可能要好好学习一番。javascript
WebRTC 全称是(Web browsers with Real-Time Communications (RTC)前端
大概2011年,谷歌收购了 GIPS,它是一个为 RTC 开发出许多组件的公司,例如编解码和回声消除技术。Google 开源了 GIPS 开发的技术,并但愿将其打造为行业标准。java
收购花了一大笔钱,谷歌说开源就开源,确实不得不佩服,但显然对于Googl来讲,打造音视频的开源生态有着更大的价值。“浏览器 + WebRTC”就是 Google 给出的一个答案。其愿景就是能够在浏览器之间快速地实现音视频通讯。git
发展至今日,简单来讲:WebRTC是一个免费、开放的项目。使web浏览器经过简单的JavaScript api接口实现实时通讯功能。github
通常谈WebRTC架构都会拿出这张图,WebRTC从上往下架构依次是:web
Web API层:面向开发者提供标准API(javascirpt),前端应用经过这一层接入使用WebRTC能力。ajax
C++ API层:面向浏览器开发者,使浏览器制造商可以轻松地实现Web API方案。api
音频引擎(VoiceEngine):音频引擎是一系列音频多媒体处理的框架,包括从视频采集卡到网络传输端等整个解决方案。浏览器
视频引擎(VideoEngine): 是一系列视频处理的总体框架,从摄像头采集视频、视频信息网络传输到视频显示整个完整过程的解决方案。服务器
传输(Transport):传输 / 会话层,会话协商 + NAT穿透组件。
硬件模块:音视频的硬件捕获以及NetWork IO相关。
这个类并不彻底属于WebRTC的范畴,可是在本地媒体流获取,及远端流传到vedio标签播放都与WebRTC相关。 MS 由两部分构成: MediaStreamTrack 和 MediaStream。
MediaStreamTrack 媒体轨,表明一种单类型数据流,能够是音频轨或者视频轨。
MediaStream 是一个完整的音视频流。它能够包含 >=0 个 MediaStreamTrack。它主要的做用就是确保几个媒体轨道是同步播放。
关于MediaStream,还有一个重要的概念叫作: Constraints(约束)。它是用来规范当前采集的数据是否符合须要,并能够经过参数来设置。
// 基本
const constraint1 = {
"audio": true, // 是否捕获音频
"video": true // 是否捕获视频
}
// 详细
const constraint2 = {
"audio": {
"sampleSize": 8,
"echoCancellation": true //回声消除
},
"video": { // 视频相关设置
"width": {
"min": "381", // 当前视频的最小宽度
"max": "640"
},
"height": {
"min": "200", // 最小高度
"max": "480"
},
"frameRate": {
"min": "28", // 最小帧率
"max": "10"
}
}
}
复制代码
其中本地媒体流获取用到的是navigator.getUserMedia()
,它提供了访问用户本地相机/麦克风媒体流的手段。
var video = document.querySelector('video');
navigator.getUserMedia({
audio : true,
video : true
}, function (stream) {
//拿到本地媒体流
video.src = window.URL.creatObjectURL(stream);
}, function (error) {
console.log(error);
});
复制代码
以上这段demo,就是经过getUserMedia
获取stream
,浏览器弹窗向用户索要权限,当容许后才能拿到stream
传给video标签进行播放。
getUserMedia
的第一个参数就是Constraint
,第二个参数传入回调函数拿到视频流。固然你可使用以下Promise的写法:
navigator.mediaDevices.getUserMedia(constraints).
then(successCallback).catch(errorCallback);
复制代码
RTCPeerConnection,用于实现peer跟peer之间的NAT穿透,继而无需服务器就能传输音视频数据流的链接通道。
这么说过于抽象,为了帮助理解,能够用一个不太恰当但有助于理解的比喻:RTCPeerConnection
就是一个高级且功能强大的用于传输音视频数据而创建相似Websocket连接通道,只不过它能够用来创建浏览器
之因此说是高级且强大,是由于它做为WebRTC web层核心API,让你无须关注数据传输延迟抖动、音视频编解码,音画同步等问题。直接使用PeerConnection 就能用上这些浏览器提供的底层封装好的能力。
var pc = new RTCPeerConnection({
"iceServers": [
{ "url": "stun:stun.l.google.com:19302" }, //使用google公共测试服务器
{ "url": "turn:user@turnserver.com", "credential": "pass" } // 若有turn服务器,可在此配置
]
};);
pc.setRemoteDescription(remote.offer);
pc.addIceCandidate(remote.candidate);
pc.addstream(local.stream);
pc.createAnswer(function (answer) {
// 生成描述端链接的SDP应答并发送到对端
pc.setLocalDescription(answer);
signalingChannel.send(answer.sdp);
});
pc.onicecandidate = function (evt) {
// 生成描述端链接的SDP应答并发送到对端
if (evt.candidate) {
signalingChannel.send(evt.candidate);
}
}
pc.onaddstream = function (evt) {
//收到远端流并播放
var remote_video = document.getElementById('remote_video');
remote_video.src = window.URL.createObjectURL(evt.stream);
}
复制代码
你会疑问这里ice Server配置是什么? signalingChannel又是什么? answer和offer又是什么? candidate又是什么?
咱们能够经过new RTCPeerConnection()
建立RTCPeerConnection。以上代码只是展现RTCPeerConnection的API和设置方法,但并不能运行。
要完成一个RTCPeerConnection须要设置ICE Server(STUN服务器或TURN服务器),在链接前还要交换信息,为此须要借助一个信令服务器(signaling server)来进行,主要交换SDP会话描述协议和ICE candidate,咱们后面段落介绍。
RTCDataChannel能够创建浏览器之间的点对点通信。经常使用的通信方式有websocket, ajax和等方式。websocket虽然是双向通信,可是不管是websocket仍是ajax都是客户端和服务器之间的通信,你必须配置服务器才能够进行通信。
而因为RTCDATAChannel借助RTCPeerConnection无需通过服务器,就能够提供点对点之间的通信,无需/(避免)服务器了这个中间件。
var pc = new RTCPeerConnection();
var dc = pc.createDataChannel("my channel");
dc.onmessage = function (event) {
console.log("received: " + event.data);
};
dc.onopen = function () {
console.log("datachannel open");
};
dc.onclose = function () {
console.log("datachannel close");
};
复制代码
咱们说WebRTC的RTCPeerConnection是能够作到浏览器间(无服务)的通讯。
但这里有个问题,当两个浏览器不经过服务器创建PeerConnection时,它们怎么知道彼此的存在呢?进一步讲,它们该怎么知道对方的网络链接位置(IP/端口等)呢?支持何种编解码器?甚至于何时开始媒体流传输、又该何时结束呢?
所以在创建WebRTC的RTCPeerConnection前,必须创建️另外一条通道来交这些协商信息,这些也被称为信令,这条通道成为信令通道(Signaling Channel)。
两个客户端浏览器交换的信令具备如下功能:
其中主要涉及SDP(offer、answer)会话描述协议,以及ICE candidate的交换。
这里须要注意的一点:
WebRTC标准自己没有规定信令交换的通信方式,信令服务根据自身的状况实现
通常会使用websocket通道来作信令通道,好比能够基于socket.io来搭建信令服务。固然业界也有不少开源且稳定成熟的信令服务方案可供选择。
在交换SDP后,webrtc就开始真正的链接来传输音视频数据。这个创建链接的过程至关复杂,缘由是webrtc既要保证高效的传输性,又要保证稳定的连通性。
因为浏览器客户端之间所处的位置每每是至关复杂的,可能处于同一个内网段内,也可能处于两个不一样的位置,所处的NAT网关也可能很复杂。所以须要一种机制找到一条传输质量最优的道路,而WebRTC正具有这种能力。
首先简单了解如下三个概念。
ICE链接大体的原理及步骤以下:
以上,WebRTC便能找到一条传输质量最优的链接道路。 固然实际状况并非这么简单,整个过程包含着更复杂的底层细节。
经过以上了解了,结合WebRTC的API,信令服务,SDP协商、ICE链接等内容。咱们用一段代码来讲明WebRTC的使用流程步骤。
var signalingChannel = new SignalingChannel();
var pc = null;
var ice = {
"iceServers": [
{ "url": "stun:stun.l.google.com:19302" }, //使用google公共测试服务器
{ "url": "turn:user@turnserver.com", "credential": "pass" } // 若有turn服务器,可在此配置
]
};
signalingChannel.onmessage = function (msg) {
if (msg.offer) { // 监听并处理经过发信通道交付的远程提议
pc = new RTCPeerConnection(ice);
pc.setRemoteDescription(msg.offer);
navigator.getUserMedia({ "audio": true, "video": true }, gotStream, logError);
} else if (msg.candidate) { // 注册远程ICE候选项以开始链接检查
pc.addIceCandidate(msg.candidate);
}
}
function gotStream(evt) {
pc.addstream(evt.stream);
var local_video = document.getElementById('local_video');
local_video.src = window.URL.createObjectURL(evt.stream);
pc.createAnswer(function (answer) { // 生成描述端链接的SDP应答并发送到对端
pc.setLocalDescription(answer);
signalingChannel.send(answer.sdp);
});
}
pc.onicecandidate = function (evt) {
if (evt.candidate) {
signalingChannel.send(evt.candidate);
}
}
pc.onaddstream = function (evt) {
var remote_video = document.getElementById('remote_video');
remote_video.src = window.URL.createObjectURL(evt.stream);
}
function logError() { ... }
复制代码
一开始各个浏览器厂商,都会实现本身的一套API,诸如webkitRTCPeerConnection
和mozRTCPeerConnection
这样的差别,对于前端开发者固然是苦不堪言。
而adapter.js正是为了消除这种差别,帮助咱们能够按照规范来写咱们的WebRTC代码。能够参考 github.com/webrtcHacks…
关于标准的另外一个关键点是:W3C在2018年发布的 WebRTC 1.0标准(candidate recommendation) www.w3.org/TR/webrtc 使得WebRTC也将成为视频通讯商业应用场景爆发的主要技术推进力。因此你能看到,目前绝大多数的实施通信厂商,在web浏览器侧的方案基本都是WebRTC了。
标准的发展,必然推进兼容支持性的提高。 本人在大概2017年作H5在线夹娃娃的预研,当时发现不少浏览器,尤为移动端和IOS彻底不可用的状态,所以不得不放弃了WebRTC方案。
目前看来浏览器支持的很不错了,除了IE仍然不支持外,PC浏览器基本已经支持。移动端上IOS在11以上已经支持。
这里有个关键在于:别光看caniuse的浏览器,还要看移动端各定制浏览器是否支持,我这里没有普遍的兼容性测试数据。
但能够给出一点结论,WebRTC在最新的IOS和安卓的手Q和微信都是可使用的。
上图给的大体的学习攻略,能够从webRTC核心API开始着手,按照demo实现诸如本地音视频获取及展现。 其次搭建简单信令服务,在内网实现简单的浏览器间的通信,是个不错的尝试。 当用起来后,再深刻李珏其链接穿越、传输的原理和相关协议,最后再尝试深刻挖掘webrtc内部音视频相关知识。
以上就是对于web前端而言比较容易理解且全面的webrtc基础介绍。
参考文章