webrtc——浏览器里的音视频通话 -凯发k8官方网
背景
webrtc是google在2010年收购gip公司之后获得的一项技术。如下图所示,它提供了音视频的采集、处理(降噪,回声消除等)、编解码、传输等技术。
webrtc的目标是实现无需安装任何插件就可以通过浏览器进行p2p的实时音视频通话及文件传输,来看看google的demo,是不是很酷?本文将带你分析webrtc的原理,并逐步编写一个简单的demo。
原理
如图,浏览器之间媒体流的传输是p2p的,但是这并不意味着webrtc不需要服务器支持。建立p2p视频连接需要的信息,如用来初始化通信的session信息,双方的ip、端口,视频分辨率,编解码格式等等,还是需要通过服务器来传输的。webrtc没有规定这些信息传输的机制,xhr、websocket、socket.io等都是可以的,因为socket.io自带了房间的概念,便于双向视频的撮合,所以我在demo里选择了socket.io。
当然,连接建立的过程不会这么简单。首先,提到p2p就绕不开nat(network address translation),webrtc使用ice(interactive connectivity establishment)框架,ice是一种综合性的nat穿越技术,它整合了stun、turn。当穿越网络时,ice会先尝试stun,查出自己位于哪种类型的nat之后以及nat为某一个本地端口所绑定的internet端端口从而建立udp连接,如果失败了ice就会再尝试tcp(先尝试http,再尝试https),如果仍然失败就使用中继的turn服务器。
再来看看建立连接过程中的具体步骤:
api
- getusermedia: 获取本地视频、音频,可以传入constraints调整分辨率、帧率,返回一个promise;
 - rtcpeerconnection: 生成一个rtcpeerconnection实例,传输视频、音频流;
 - createoffer: 会话发起方生成sdp offer,包含了本地媒体流信息;
 - setlocaldescription:在此方法被调用之前oncandidate事件不会被触发;
 - setremotedescription: 接收到offer或者answer之后调用;
 - addicecandidate: 接收到icecandidate之后调用;
 
steps
获取媒体流
var constraints = {audio: false,video: true };navigator.mediadevices.getusermedia(constraints) .then(gotstream) .catch(function(e) {alert('getusermedia() error: ' e.name); });function gotstream(stream) {localvideo.srcobeject = stream;localstream = stream; }getusermedia存在兼容性问题,需要在项目中引用webrtc官方给出的adapter.js。constraints还可以配置video的分辨率、帧率、对移动端还可以选择前后摄像头:
var constraints = {video: {width: { min:640, ideal: 1280, max: 1920 },height: { min: 480 ideal: 720, max: 1080 },facingmode: 'user' // 前置摄像头} };定义rtcpeerconnection
var serverconfig = {'iceservers': [{'urls': 'stun:stun.l.google.com:19302'}] };function createpeerconnection() {var pc = new rtcpeerconnection(serverconfig);pc.onicecandidate = function(e) {if (e.candidate) {pc.addicecandidate(e.candidate);}};// 添加对方的媒体流pc.onaddstream = function(e) {remotevideo.srcobeject = e.stream;remotestream = stream;}; }由stun、turn配置生成对应的rtcpeerconnection实例,再定义相关的事件处理函数,如onicecandidate、onaddstream、onremovestream等。
创建连接
function start() {pc.addstream(localstream);if (iscaller) {pc.createoffer(function(sessiondescription) {pc.setlocaldescription(sessiondescription);send(sessiondescription); // 根据不同的signaling方式实现});if (receiveanswer) {pc.setremotedescription(answer.sessiondescription);}} else {if (receiveoffer) {pc.setremotedescription(offer.sessiondescription);}pc.createanswer(function(sessiondescription) {pc.setlocaldescription(sessiondescription);send(sessiondescription);});} }必须先getusermedia后才能生成sessiondescription,并且只有在setlocaldescription后onicecandidate事件才会触发。上面代码中的只是为了说明大致流程,实际项目中结合socket.io的事件更容易实现。
中断会话
function stop() {pc.stop();pc = null; }关于socket.io有关的代码本文没有贴出,详情可参考socket.io的用法。
可行性
按照上面的步骤可以成功地搭建webrtc的小demo,但是能否将webrtc运用到实际项目中去呢?下面从浏览器兼容性和webrtc本身的性能两个方面去分析。
兼容性
- ios: 只有最新的ios11支持webrtc,且仅限safari浏览器,微信内置浏览器尚不支持getusermedia,不支持datachannel,视频编解码格式为h.264;
 - android: 安卓4.4以上(不含4.4),经测试各大手机厂商自带浏览器均不支持getusermedia,但微信内置浏览器可以正常运行,另外61版本以上的chrome for android也都支持;
 - pc: chrome49以上,firefox55以上,edge支持,safari只有11支持,ie不支持。
 
性能
诚然webrtc在回声消除,图像编解码等方面已经做得十分出色,但它在性能上的问题还是不可忽视的:
- 由于需要进行视频编解码,所以cpu占用率非常高,尤其是在移动设备上;
 - 在移动设备上获取的视频分辨率有限,最高只能达到640 * 480;
 - 带宽有限时,音视频质量较差,延时明显;
 
综上所述,虽然webrtc具有不需安装插件或者客户端,开源免费,强大的网络穿透能力,出色的音视频处理技术等等优点,但由于兼容性及性能上的问题,要投入到生产中还需要时间,主要是ios11的普及以及cpu占用率和延时的问题。
参考文章
- webrtc in the real world: stun, turn and signaling
 - how to select a signaling protocol for your next webrtc project?
 - getting started with webrtc
 - 使用webrtc搭建前端视频聊天室——入门篇
 
总结
以上是凯发k8官方网为你收集整理的webrtc——浏览器里的音视频通话的全部内容,希望文章能够帮你解决所遇到的问题。
- 上一篇:
 - 下一篇: