1. 首页
  2. >
  3. 技术专题
  4. >
  5. WebRTC

WebRTC网页实时通信

WebRTC 是争取开放和无阻碍Web 的漫长战争中一条新战线。JavaScript 之父 Brendan Eich

WebRTC前世今生

让人类通过网络进行音视频通信是网络最后的巨大挑战:实时通信(RTC),实时通信就像网络上在文本框中输入文本一样自然,没有它,就限制了我们新的方式使人们互动交流起来。
从历史上看,RTC 变化很大很复杂,需要昂贵的音视频技术授权或话费巨大代价去开发,RTC 技术与现有的内容、数据、服务整合一直都很困难和耗时,在网络上尤其如此。
Gmail 视频聊天在2008年开始流行,在2011年 Google 推出视频群聊,它使用 GoogleTalk 服务就像 Gmail 一样。Google 收购了 GIPS,它是一个为 RTC 开发出许多组件的一个公司,例如编解码回声消除技术。Google 开源了 GIPS 开发的技术,与相关机构 IET 和 W3C 制定行业标准。在2011年5月,爱立信实现了第一个 WebRTC应用。
WebRTC已经实现了对于实时通信,免插件音频数据传输的标准制定。

  • 许多网路服务已经使用了 RTC 但需下载,本地应用或是插件,包括 Skype、Facebook、Google Hangouts。
  • 下载安装升级插件是复杂的可能出错的,令人厌烦的。
  • 插件可能很难部署、调试、故障排除等
    WebRTC指导原则是 APIs 应该是开源的、免费的、标准化的,浏览器内置的,比现有技术更高效的。

WebRTC现状

随着移动互联网和智能硬件的快速发展,音视频技术从独立应用普及到嵌入式应用中,不管是智能硬件、手机应用或是 web 程序中许多模块越来越依赖音视频技术。
2011年 Google 将 WebRTC 项目开源,WebRTC 在被 Google 开源之前,价值已得到充分认可,比如 QQ 中使用 WebRTC 部分技术。
WebRTC 发展情况可从标准规范和浏览器支持两个方面看,WebRTC 标准是由 W3C 和 IETF 联合制定了,2016年1月28日,W3C 公布最新的 WebRTC 标准,标准中定义了 WebIDL 中一系列的 ECMAScript API 来允许使用合适的 RTP 的浏览器或设备来接收/发送媒体。
WebRTC 很多参数都由 GIPS 工程师依靠经验所设定的值,这会出现卡顿、延时、回声、丢包、多人视频不稳定等问题,由于公网的稳定性或机型适配等外在因素,以上问题在项目上线后更为严重。
总之 WebRTC 虽然提供了一套音视频实时通讯的解决方案,但是实际应用中,由于网络传输、设备适配以及多方通话都存在问题,效果并不理想。
由于 WebRTC 复杂性和尚未完善,建议结合自己的实际参考:

  • 音视频不是公司核心方向,建议使用第三方。
  • 项目时间紧、有多人视频场景,使用场景依赖于手机端建议使用第三方。
  • 公司没音视频人才建议使用第三方 SDK 或技术外包。
  • 若公司实力、财力、人力雄厚,时间也不紧急,可考虑 WebRTC 继承开发。
  • 若音视频技术是公司核心放心,若不想花太多时间研究 WebRTC 可寻找熟悉 WebRTC 的人来培训。
  • 项目时间不紧急,无人视频需求且音频质量要求不高可考虑 WebRTC 集成开发。

即时通信和实时通信的区别

即时通信和实时通信都是一套网络通信系统,其本质都是对信息进行转发。最大不同点是对信息传递的时间规定。二者的区别为
1.应用场景

  • 即时通信:文字聊天、语音消息发送、文件传输、音视频播放等。通俗的说就是发短信。
  • 实时通信:语音、视频电话会议、网络电话等。通俗的说就是打电话。

2.产品需求

  • 即使通信:要求可靠考核送达率
  • 实时通信:要求低延时和接通率

3.技术环节

  • 即时通信:消息接收和确认
  • 实时通信:采集、前处理、编码、解码、播放渲染

4.传输协议

  • 即使通信:为保证连接的可靠性常用的 TCP ,此类协议的特点是追求连接的可靠性,而造成了延迟的不可控,超过2秒的延迟响应是常态,甚至几十分钟的延迟响应,而电信级的实时通信标准是400ms,而基于互联网的实时通信需另辟蹊径,开创出新的传输解决方案。
  • 实时通信:在设计延时的实时通信服务时,UDP 表现要比 TCP 好得多,实时通信中低延时的效果,特别是在互联网中超过30%丢包时,TCP 延时可到几十分钟,超过50%丢包时很容易断开。在同样丢包30%的链路上,UDP 还可传输数据,TCP 就无法进行实时通信了。

搭建 WebRTC 数据通道服务

WebRTC可让数据、视频、屏幕共享通过 P2P 连接形式进行传播的技术,这意味着数据无需通过服务器进行传输。

WebRTC网页实时通信

WebRTC架构

WebRTC API

WebRTC 是一系列协议和 API 的大集合,WebRTC 协议被内置在 Chrome 和 Firefox 浏览器中,包括三部分:

  • getUserMedia 允许网页浏览器获取摄像头和麦克风的使用权限,并且捕获媒体。通过 MediaStream 的 API 能够通过设备的摄像头及话筒获得音视频的同步流。
  • RTCPeerConnection 负责管理端到端连接,RTCPeerConnection 是 WebRTC 用于构建点对点之间稳定、高效的流传输的组件。
  • RTCDataChannel 允许浏览器分享任意数据,RTCDataChannel 使得浏览器之间(点对点)建立一个高吞吐量、低延时的信道,用于传输任意数据。

MediaStream(getUserMedia)

MediaStream API为 WebRTC 提供了从设备的摄像头、话筒获取视音频数据的功能。

getUserMedia浏览器兼容性

navigator.getUserMedia || (navigator.getUserMedia = navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia);
if(!navigator.getUserMedia){
return;
}

Chrome21、Firefox17、Opera18支持,IE 尚不支持。

getUserMedia(streams, success, error)

//获取摄像头和麦克风的实时信息
var streams = {video:true, audio:true};
navigator.getUserMedia(streams, onSuccessFn, onErrorFn);

streams 表示包括哪些多媒体设备对象
约束对象可被设置在 getUserMedia()和 RTCPeerConnection 的 addStream()中,这个约束是 WebRTC用来指定接受什么样的流的,可定义如下属性:

  • video 是否接受视频流
  • audio 是否接受音频流
  • MinWidth 视频流的最小宽度
  • MaxWidith 视频流的最大宽度
  • MinHeight 视频流的最小高度
  • MaxHeight 视频流的最大高度
  • MinAspectRatio 视频流的最小宽高比
  • MaxAspectRatio 视频流的最大宽高比
  • MinFramerate 视频流的最小帧速率
  • MaxFramerate 视频流的最大帧速率

success 成功回调函数,获取多媒体设备成功调用,传递给它一个流对象。
网页使用 getUserMedia,浏览器会询问用户,是否许可提供信息。若用户拒绝就会调用 onErrorFn。发生错误时回调函数的参数是一个 Error 对象,它有 code 参数,取值如下:

  • PERMISSION_DENIED 用户拒绝提供信息
  • NOT_SUPPORTED_ERROR 浏览器不支持指定的媒体类型
  • MANDATORY_UNSATISHIED_ERROR 指定的媒体类型未收到媒体流

error 失败回调函数,获取多媒体设备失败时调用。

function onSuccessFn(stream){
var video = document.getElementById('video');
if(window.URL){
video.src = window.URL.createObjectURL(stream);
}else{
video.src = stream;
}
video.autoplay = true;
}

实时数据交换
WebRTC另外两个 API, RTCPeerConnection 用于浏览器之间点对点的连接,RTCDataChannel 用于点对点的手通道。

RTCPeerConnection

WebRTC使用 RTCPeerConnection 在浏览器之间传递流数据,这个流数据通道是点对点的,无需经过服务器进行中转。但并不意味着能抛弃服务器,仍需它为传递信令(signaling)来建立信道。WebRTC 没有定义用来建立信道的指令协议,信令并不是 RTCPeerConnection API的一部分。

信令
即使没有定义具体的信令协议,可选择任意方式(AJAX、WebSocket),采用任意的协议(SIP、XMPP)来传递指令,建立信道。

信令交换信息应用场景

  • session:用来初始化通信还有报错
  • 网络配置:比如 IP 地址和端口
  • 媒体适配:发送方和接收方的浏览器能接受什么样的编码器和分辨率

通过服务器建立信道
虽然 WebRTC 提供浏览器之间的点对点信道进行数据船速,但建立这个信道必须有服务器参与。WebRTC 需服务器对其进行四方面的功能支持:

  • 用户发现以及通信
  • 信令传输
  • NAT/防火墙穿越
  • 若点对点通信建立失败可作为中转服务器

NAT/防火墙穿越技术
建立点对点信道的问题是 NAT 穿越技术,在处于使用了 NAT 设备的私有 TCP/IP 网络中的主机之间需建立连接时需使用 NAT 穿越技术。
由于 NAT 的行为是非标准化的,在 RTCPeerConnection 中使用 ICE 框架来保证 RTCPeerConnection 能实现 NAT 穿越。

ICE
ICE(Interactive Connectivity Establishment)交互式连接建立,一种综合性的 NAT 穿越技术,是一种框架,可整合各种 NAT 穿越技术如 STUN、TURN(Traversal Using Relaying NAT,中继NAT实现的穿透)。ICE 会先使用 STUN,尝试建立一个基于 UDP 的连接,如失败了就会去 TCP(先尝试 HTTP,然后尝试 HTTPS),若依旧失败 ICE 就会使用一个中继的 TURN 服务器。

在 P2P 连接被创建前,首先必须进行信令处理。为了完成让用户都具有另一端用户的 IP 以及其他任何用户想要共享的涉及数据/视频的信息,信令会在用户和信令服务器之间进行多次往返。

RTCDataChannel

既然能建立点对点的信道来传递实时的视频、音频数据流,为什么不能用这个信道传一点其他数据呢?
RTCDataChannel API就是用来干这个的,基于它我们可在浏览器之间传递任意数据。DataChannel 是建立在 PeerConnection 上,不能单独使用。

使用 DataChannel

可使用channel=pc.createDataChannel("someLabel") 来在 PeerConnection 的实例上创建 Data Channel,并给与它一个标签。
DataChannel 使用方式几乎与 WebSocket 一样,有如下事件:

  • onopen
  • onclose
  • onmessage
  • onerror

DataChannel 拥有几个状态,可通过 readState 获取:

  • connecting 浏览器之间正在试图建立 channel
  • open 建立成功可使用 send()发送数据
  • closing 浏览器正在关闭 channel
  • closed channel 已经被关闭了

两个暴露的方法

  • close() 用于关闭 channel
  • send() 用于通过 channel 向对方发送数据

WebRTC网页实时通信

端到端的连接

端到端连接流程

  • 对等端 A 向对等端 B 发送“连接请求”(offer)
  • 对等端 B 向对等端 A 发送“应答响应”(answer)
  • 对等端 A 向对等端 B 发出“候选”(candidate)
    候选告知另一端用户如何将信息传递到本地浏览器中,它是在幕后完成的。

注意事项

  • 信令是不对称的,其中一个用户必须发起它,另一端必须接收。
  • STUN 和 TURN 服务器在不同本地网络的两用户之间连接建立起到至关重要的作用。