关于WebRTC的技术研究和实际运用

414 阅读9分钟

简介

研究了WebRTC技术,查阅各种资料了解它的各个方面,分析了其原理和工作流程,并发表了自己的看法,研究了它的实际项目的运用,写了一些demo,代码在github
本文包含很多我的想法观点,有不对的地方请指正

是什么?

结合官网的描述和我自己的看法 总结一下几点:

  • WebRTC,名称源自网页即时通信(英语:Web Real-Time Communication)的缩写
  • WebRTC是一个免费的开放项目
  • 通过简单的API为浏览器和移动应用程序提供实时通信(RTC)功能
  • 支持的浏览器和平台 Chrome firefox opera Android ios
  • 对于开发人员来说,WebRTC就是一组API
  • WebRTC是一组标准、协议
  • WebRTC是一个带有JavaScript API的媒体引擎
  • WebRTC并不止仅限于JavaScript。有很多系统是用C,Java,Python,C#,Erlang,Dart,甚至PHP所写。在移动端,原生软件在其客户端WebRTC SDK实现中使用的是Objective-C,Swift或者Java。但是最主要的是JavaScript。

为什么选择用WebRTC?

官网说法总结

  • Web成功的关键因素在于其核心技术(例如HTML,HTTP和TCP / IP)是开放的并且可自由实施。之前,没有免费的,高质量的,完整的解决方案可用于在浏览器中进行通信。WebRTC启用了此功能。
  • 已经与过去8年来部署在数百万个端点上的同类最佳的语音和视频引擎集成在一起。Google不向WebRTC收取版税。
  • 使用STUN,ICE,TURN,RTP-over-TCP并包括对代理的支持,包括并提取关键的NAT和防火墙穿越技术。
  • 基于Web浏览器的强大功能:WebRTC通过提供直接映射到的信令状态机来抽象信令PeerConnection。因此,Web开发人员可以为他们的使用场景选择选择的协议(例如,但不限于SIP,XMPP / Jingle等)

我的看法

因为它可以实现它所支持平台之间的实时通信

WebRTC历史

出现的条件

从历史上看,RTC一直是公司性的且复杂的,需要内部昂贵的音频和视频技术才能获得许可或自行开发。将RTC技术与现有内容,数据和服务集成在一起非常困难且耗时,尤其是在Web上。 但是这样的需求是真实的:

  • 许多Web服务使用RTC,但需要下载,本机应用程序或插件。包括Skype,Facebook和Google Hangouts。
  • 下载,安装和更新插件非常复杂,容易出错且令人讨厌。
  • 插件难以部署,调试,故障排除,测试和维护,并且可能需要许可以及与复杂,昂贵的技术的集成。首先说服人们安装插件通常很困难!

发展时间线

  • 2008年:Gmail视频聊天在2008年开始流行
  • 2011年 Google引入了Hangouts,它使用Google Talk服务(与Gmail一样)
  • 然后,Google收购了GIPS,这家公司开发了RTC所需的许多组件,例如编解码器和回声消除技术。Google开源了GIPS开发的技术,并与IETF和W3C的相关标准机构合作,以确保行业共识。
  • 2011年5月 Ericsson(爱立信公司)构建了WebRTC的第一个实现。

基本概念

不了解其基本概念无法理解其架构和工作流程

SDP

会话描述协议Session Description Protocol (SDP) 是一个描述多媒体连接内容的协议,例如分辨率,格式,编码,加密算法等。所以在数据传输时两端都能够理解彼此的数据。本质上,这些描述内容的元数据并不是媒体流本身。 从技术上讲,SDP并不是一个真正的协议,而是一种数据格式,用于描述在设备之间共享媒体的连接。
记录SDP远远超出了本文档的范围。但是,这里有几件事值得注意。
结构体
SDP由一行或多行UTF-8文本组成,每行以一个字符的类型开头,后跟等号(“ =”),然后是包含值或描述的结构化文本,其格式取决于类型。以给定字母开头的文本行通常称为“字母行”。例如,提供媒体描述的行的类型为“ m”,因此这些行称为“ m行”。

ICE

交互式连接设施Interactive Connectivity Establishment (ICE) 是一个允许你的浏览器和对端浏览器建立连接的协议框架
在实际的网络当中,有很多原因能导致简单的从A端到B端直连不能如愿完成。
这需要绕过阻止建立连接的防火墙,给你的设备分配一个唯一可见的地址(通常情况下我们的大部分设备没有一个固定的公网地址),如果路由器不允许主机直连,还得通过一台服务器转发数据。
ICE通过使用以下几种技术完成上述工作。

STUN

NAT的会话穿越功能Session Traversal Utilities for NAT (STUN) (缩略语的最后一个字母是NAT的首字母)是一个允许位于NAT后的客户端找出自己的公网地址,判断出路由器阻止直连的限制方法的协议。

客户端通过给公网的STUN服务器发送请求获得自己的公网地址信息,以及是否能够被(穿过路由器)访问。

NAT

网络地址转换协议Network Address Translation (NAT) 用来给你的(私网)设备映射一个公网的IP地址的协议

一般情况下,路由器的WAN口有一个公网IP,所有连接这个路由器LAN口的设备会分配一个私有网段的IP地址(例如192.168.1.3)。私网设备的IP被映射成路由器的公网IP和唯一的端口,通过这种方式不需要为每一个私网设备分配不同的公网IP,但是依然能被外网设备发现。

一些路由器严格地限定了部分私网设备的对外连接。这种情况下,即使STUN服务器识别了该私网设备的公网IP和端口的映射,依然无法和这个私网设备建立连接。这种情况下就需要转向TURN协议。

TRUN

一些路由器使用一种“对称型NAT”的NAT模型。这意味着路由器只接受和对端先前建立的连接(就是下一次请求建立新的连接映射)。

NAT的中继穿越方式Traversal Using Relays around NAT (TURN) 通过TURN服务器中继所有数据的方式来绕过“对称型NAT”。你需要在TURN服务器上创建一个连接,然后告诉所有对端设备发包到服务器上,TURN服务器再把包转发给你。很显然这种方式是开销很大的,所以只有在没得选择的情况下采用。

WebRTC 架构

image.png

  1. 紫色部分是Web开发者API层;
  2. 蓝色实线部分是面向浏览器厂商的API层
  3. 蓝色虚线部分浏览器厂商可以自定义实现

对于我们开发者,WebRTC就是一组API

WebRtc工作流程

简单流程图

image.png 总体来说可以分为3步:

  1. 浏览器获取媒体设备(摄像头和麦克风)。
  2. 通过信令过程,每一个peer和其它所有peer交换信息。
  3. 发信之后,peers可以直接连接,并开始通信交流。为了实现这个过程,对于交换信息需要一个信令服务器。同样需要一对STUN/TURN服务器来实现NAT穿透。

比较详细的流程图

image.png

  1. 步骤1-2中主叫(Caller) 先配置会话的基本参数,比如本次会话是否包含音频流或者视频流等参数;再根据会话的参数创建Offer SDP(Session Description Protocol)后通过信令服务器转发给被叫(Callee)。
  2. 步骤3,5,6中被叫保存主叫的Offer SDP, 并依据Offer SDP创建Answer SDP,发送给主叫。
  3. 步骤8中主叫保存了被叫的Answer SDP,至此主叫和被叫双方都保存了己方和对方的SDP。
  4. 步骤9,10中主叫发送自己的IceCandidate给被叫方。
  5. 步骤11,12中被叫发送自己的IceCandidate给主叫。
  6. 主叫和被叫双方都接收到对方的IceCandidate后,就可以建立连接了。

生成SDP流程图

image.png

  1. 调PeerConnectionInterface::CreateOffer()生成的 Offer SDP会异步通知给Conductor::OnSuccess()。

  2. 被叫生成的Answer SDP 会从Conductor::OnMessageFromPeer传过来,然后通过PeerConnectionInterface::SetRemoteDescription接口设置。

  3. 被叫调用 PeerConnectionInterface的对应接口以及顺序和主叫有一定区别,具体为:SetRemoteDescription() -> CreateAnswer() -> SetLocalDescription()。

  4. 对于主叫,SetLocalDescription()的参数为Offer SDP,SetRemoteDescription()的参数为Answer SDP。

  5. 对于被叫,SetRemoteDescription()的参数为为Offer SDP, SetLocalDescription()的参数为Answer SDP。

我的看法和结论

  • 无论是主叫或被叫,想要通信成功都需要获得的重要参数: Local SDP;Remote SDP;Remote IceCandidate;
  • 与上述对应的PeerConnectionInterface的接口:SetLocalDescrpition(), SetRemoteDescription(), AddIceCandidate()。
  • 主叫和被叫调用上述接口的顺序有一些差别。
  • 获取Local SDP 与Local IceCandidate的回掉接口分别为: Conductor::OnSuccess();Conductor::OnIceCandidate()。

项目里实际运用

视频通话

我的github例子

  • 包括了用 node socket.io 做的服务端
  • 包括了两人多个通话的例子

播放WebRtc视频流(延迟很低)

可以参考 github 上的 JSWebrtc 库
JSWebrtc 对浏览器的 Webrtc 做了简单的封装,支持 SRS 的 RTC 流的播放.

用法

具体用法可以参考下面这个地址
jswebrtc

工作原理(个人分析)

关于服务端(没深入研究,猜测)

  1. srs服务器端应该是创建了一个RTCPeerConnection,并通过某种方式把从摄像头拿到的流添加进了通道
  2. 创建 服务器端的sdp,当前端播放的时候就交互sdp信息,建立连接通道
  3. 约定一种地址格式,把这个地址抛给前端如:webrtc://172.16.200.157/live/54020000001320000001@54020000001320000001

关于前端浏览器

  1. 创建 RTCPeerConnection
  2. 和上述的工作流程差不多
  3. 但是要用 addTransceiver("audio", {direction: "recvonly"}),addTransceiver("video", {direction: "recvonly"}),把连接方式设置为只接收流,并不需要添加本地流
  4. 解析服务端给的约定好的url格式,拿到里面的请求地址,然后交互sdp信息
  5. 连接建立起来,把接收到的视频流放到本地播放即可

参考资料

官网