详解 WebRTC 协议原理与框架

发布时间 2023-09-14 09:20:34作者: 阿风小子

一、WebRTC 是什么

WebRTC,名称源自网页即时通信(英语:Web Real-Time Communication)的缩写,是一个支持网页浏览器进行实时语音对话或视频对话的API。它于2011年6月1日开源并在Google、Mozilla、Opera支持下被纳入万维网联盟的W3C推荐标准。谷歌2011年6月3日宣布向开发人员开放WebRTC架构的源代码。这个源代码将根据没有专利费的BSD(伯克利软件发布)式的许可证向用户提供。开发人员可访问并获取WebRTC的源代码、规格说明和工具等。
WebRTC使用安全实时传输协议(Secure Real-time Transport Protocol,SRTP)对RTP数据进行加密,消息认证和完整性以及重播攻击保护。它是一个安全框架,通过加密RTP负载和支持原始认证来提供机密性。WebRTC的安全特性是其可靠性的重要组成部分,其基础全部围绕实时传输协议(Real-time Transport Protocol)进行。

我们先来看一下网上广为流传的webrtc架构图,这张图来自WebRTC官网,另外可以参考WebRTC中文网

总体上来说看上面图可以知道整个浅绿色部分都属于WebRTC核心架构层,它封装各种提供给web端使用的Web API层接口。紫色的部分属于应用层,使用核心层提供的API。你可以在应用层扩展相关API,调用WebRTC核心层的接口。

1.1 WebRTC核心层又分为四层:

  1. WebRTC C C++ API (PeerConnection): 这层的API相对比较少,最主要就是实现P2P连接。在PeerConnection里面又包含了很多接口,如传输质量,传输质量报告,统计数据,各种流都是封装在PeerConnection模块里面。除此之外主要有音视频采集,音视频传输,非音视频数据传输等。
  2. Session Management/ Abstract signaling (Session): 会话层,用来管理音视频,非音视频数据传输,处理相关逻辑。
  3. 最核心的第三层,包含:音频引擎,视频引擎,传输,3大核心模块。
  4. 最底层是与硬件相关的硬件适配层:这层包含:音频的采集和渲染,视频的捕捉,网络IO。注意到上图中底层的这个三个模块都是画的虚线,表示这些模块是可以自己去实现的,可以重载的,这样大大增加WebRTC的灵活性,为跨平台提供了基础。

1.2 WebRTC最核心的三大模块:

Voice Engine, Video Engine , Transport,这三个层中Voice Engine只处理音频相关的技术,Video Engine处理视频相关的技术,音频和视频是相互独立的,一个重要的技术:音视频同步并不包含在这里面。

1.2.1 Voice Engine 音频引擎包含3大模块:

iSAC/iLBC Codec: 这个模块主要是编解码,iSAC/iLBC 是jips公司开发的,另外有我们熟悉的音频G711, G726,AAC, Opus 目前使用的最多也是Opus,几年前AAC也是很火的,你可以自己把AAC模块加入到WebRTC里面.其中WebRTC中使用的是Opus,后面的会详细讲解这块的知识。
NetEQ for voice: NetEQ实际上是一个音频缓冲的buffer,用于做网络的适配。如我们做防止音频抖动,这里面涉及了很多相关的算法。
Echo Canceler/ Noise Reduction: 这里面解决了很多做音频头疼的问题:回音消除,降噪等问题处理算法。回音消除是困扰很多公司的一个头疼的技术,但WebRTC里面提供了非常成熟,稳定的回音消除算法,值得好好研究,应用到自己的产品中。其实很多算法工程师做的也是利用像WebRTC一样的开源代码,自己调一些参数,来提高音频质量。

1.2.2 Video Engine 视频引擎包含3大模块:

VP8 Codec: 这块主要是视频编解码器,VP8,VP9都是google开发出来的,之前WebRTC最先支持的是自己家的VP8,后面也支持了H264,H265, Open H264 , xh264(在官方的WebRTC里面是不支持的,如果你想支持可以自己安装Open H264的模块添加进去)
Video jitter buffer:视频jitter buffer跟音频buffer一样也是用来防止视频抖动的。
Image enhancements: 这块是图像处理相关的,如图像增加处理,WebRTC来说图像增强这一块做的比较薄。它把相应的接口也都留出来了,如果你想做一些美颜,贴图,滤镜处理,你也可以在提供的预留接口中去实现。像人脸视频这些接口都有,你都可以加入进去。

1.2.3 Transport 传输模块包含3大模块:

传输底层用的是UDP 协议,因为音视频传输对及时性要求更高,允许部分丢帧,WebRTC充分利用的UDP的不管控能力,利用各种成熟的算法保证高质量的音视频传输,可以自动适配码率变换。所有音视频的数据的发送,接收都是通过传输层去做的,从图中可以看出来,WebRTC的架构层次是非常清晰的。

  • SRTP: 一般正常视频传输都是使用RTP协议,但是由于浏览器对安全性要求比较高,增加了加密这块的处理,采用SRTP协议。还有控制流的传输的协议RTCP,将相应的数据发送,接收报告发送给对方,这样对方就可以做流控处理。
  • Multplexing:这里主要是多个流复用同一个通道。
  • P2P (STUN + TURN + ICE) : 这里主要是P2P相关的技术,这是WebRTC最核心的技术,像以前做安防这块的P2P技术都是属于各个公司最核心的技术,现在WebRTC的源码这里面这块技术非常成熟,后面也会详细介绍这块打洞的技术。
    整个传输层包括了对线路的检测,网络丢包,抖动,流控 ,NAT穿透打洞等等非常复查的技术都实现了非常成熟的方案。学好这块技术是非常有用的。

WebRTC传输层这块还实现了通过计算去估算你的网络带宽,不仅仅可以实现稳定的音视频传输,还可以传输其他非音视频数据,如文件,文本等二进制数据都可以传输。

需要注意的是,在WebRTC的核心层是没有视频的渲染的,视频的渲染需要应用层去做。
通过上面讲解,我们对WebRTC具备哪些能力,有了一个大致的理解,接下来我们来细分每个模块的功能项,讲解里面涉及的相关技术,知识,最后通过分析源码的方式更深入的理解,这样我们就可以自己编写代码,在项目实战中再次体认WebRTC框架魅力。

二、WebRTC 能做什么

  1. WebRTC实现了基于网页的视频会议,标准是WHATWG 协议,目的是通过浏览器提供简单的javascript就可以达到实时通讯(Real-Time Communications (RTC))能力。
  2. WebRTC(Web Real-Time Communication)项目的最终目的主要是让Web开发者能够基于浏览器(Chrome\FireFox…)轻易快捷开发出丰富的实时多媒体应用,而无需下载安装任何插件,Web开发者也无需关注多媒体的数字信号处理过程,只需编写简单的Javascript程序即可实现,W3C等组织正在制定Javascript 标准API,目前是WebRTC 1.0版本,Draft状态;另外WebRTC还希望能够建立一个多互联网浏览器间健壮的实时通信的平台,形成开发者与浏览器厂商良好的生态环境。同时,Google也希望和致力于让WebRTC的技术成为HTML5标准之一,可见Google布局之深远。
  3. WebRTC提供了视频会议的核心技术,包括音视频的采集、编解码、网络传输、显示等功能,并且还支持跨平台:windows,linux,mac,android。

三、如何使用 WebRTC 框架进行编程

3.1 Web API 接口

Web开发者可以基于集成WebRTC的浏览器提供的web API开发基于视频、音频的实时通信应用。面向第三方开发者的 WebRTC 标准API(Javascript),使开发者能够容易地开发出类似于网络视频聊天的web应用,这些API可分成Network Stream API、 RTCPeerConnection、Peer-to-peer Data API三类。

3.2 WebRTC Native C++ API 接口

本地C++ API层,使浏览器厂商容易实现WebRTC标准的Web API,抽象地对数字信号过程进行处理。提供给浏览器开发者使用来开发JavaScript API。

四、WebRTC 架构

4.1 基本的三角形WebRTC架构

 


在这个架构中,移动电话用“浏览器M”表示,笔记本电脑用“浏览器L”表示,通过Web服务器将它们连接起来。要建立一个实时媒体通讯,两台设备需要了解彼此的媒体功能,通过交换呼叫信令控制协议实现。

诸如这样的信令协议在WebRTC标准中并非事先规定,而是由开发者自行制定。在浏览器RTC会话的步骤如下:

  • 首先,两个浏览器都从Web服务器下载了WebRTC程序(HTML5/JavaScript);
  • 其次,两个浏览器通过Web服务器交换控制信令信息(使用嵌入式信令服务器),建立媒体功能功能互通。
  • 最后,两个浏览器直接建立RTC媒体的音频、视频和数据通道。

4.2 基于P2P的WebRTC架构

WebRTC使用P2P媒体流,音频、视频和数据的连接直接通过浏览器实现。但是,浏览器却隐藏在NAT(网络地址翻译)和防火墙的后面,这增加了建立P2P媒体会话的难度。这些流程和协议,如ICE或Trickle ICE,STUN和TURN,在建立P2P媒体流都是必不可少的。

 

五、WebRTC 协议栈是什么样子?

WebRTC 的协议栈是几个协议的集合,如RTP、SETP、SCTP等,协议栈框架如下:


转载者注:
协议栈主要分为Transport 和 Session 两个部分,Session 是负责WebRTC网络建立协议集,Transport 是负责WebRTC数据传输的协议集。

原文内容:
Session 组件是基于libjingle (会话协商 + NAT穿透组件库 )开发,传输/会话层: 会话层组件采用了libjingle库的部分组件实现,无须使用xmpp/jingle协议。

  • RTP Stack协议栈: Real Time Protocol
  • P2P(ICE + STUN + TURN):用来实现点对点传输,可以用来建立不同类型网络间的呼叫连接。
  • Session Management:一个抽象的会话层,提供会话建立和管理功能。该层协议留给应用开发者自定义实现。

六、webrtc源码结构概况

WebRTC 源码作为 Chromium 的一部分,更新速度非常快,这得益于 Google 对音视频通信的大力推广。WebRTC 源码的结构也变化很快,主要体现在以下几方面:

  • 比较源码版本 m50 和 m66,在编译工具上发生了变化。老版本是通过 GYP 来生成 ninja 文件,新版本是通过 gn 生成 ninja 文件。
  • 在目录结构上发生了变化,老版本中支持的一些功能在新版本中删除了。
  • 随着 c++11,c++14,c++17 新标准的推出,WebRTC 在新版本中逐渐支持了新标准中的语法功能,使得代码变得更简洁、易维护。

其实webrtc在每个对应的平台上的源码都不相同,只是整体协议框架是一样的,在每个平台上的实现方式不一样,如android,ios ,js都实现了同样的协议功能,但是编码是使用每个平台自己的特性。

6. 1 目录结构

如果按照通常层次化的思维来组织,从下到上,大概分以下几个层次:

  • OS 跨平台适配、硬件设备访问、第三方库 Wrapper 层:
    包括网络层、操作系统 API 的跨平台封装,音频设备、视频设备封装,音频、视频 codec,DTLS 的第三方实现等。
  • 网络传输层:
    这里包括 candidate 收集,stun/turn 协议的实现,dtls、rtp 网络连接的建立,sctp 连接的建立等。
  • 通道层:
    主要包含传输通道也就是 BaseChannel 层 和 媒体通道 也就是 MediaChannel 层。BaseChannel 是和 PeerConnection、Transport 层对接。MediaChannel 实现其实在音视频引擎里面,是 BaseChannel 和引擎的桥梁。
  • RTP_RTCP : 主要是流控
  • Audio Engine、Video Engine 是音视频引擎层,音视频处理。
  • 音视频编解码器,这也是 WebRTC 自己的一个抽象,真正的编解码库还是依赖第三方库。
  • PeerConnection、MediaStream 主要是对 jsep 协议的实现。
  • PeerConnectionInterface 是一个对外抽象接口类设计。

6.2 核心模块

6.2.1 PeerConnection:

PeerConnection 的主要实现逻辑就是在 WebRTC 源码的 pc 目录下。

一切都从 PeerConnectionFactory 和 PeerConnection 开始,对外提供 PeerConnectionFactoryInterface 和 PeerConnectionInterface 两个接口类。Factory 类,顾名思义就是创建 PeerConnection 的,下来我们只讨论 PeerConnection。

也许你已经非常熟悉 WebRTC 的 JavaScript 接口。比如,RTCPeerConnection,setLocalDescription、setRemoteDescription、createOffer、createAnswer 等,没错这些。JavaScript 接口的 Native 实现就是在 PeerConnection 中完成的,它也有对应的一套接口。JavaScript 这套接口实现规范是JSEP。 可以说是把这套规范的模型都给实现了。

WebRTC 终端之间的通信协议是 ICE 协议,书包格式采用 SDP 协议。PeerConnection 实现了 SessionDescription 的逻辑。

PeerConnection 抽象了 RtpTransceiver,RtpSender、RtpReceiver 模型,对应了 sdp 中描述的媒体的实现。

6.2.2 Module

WebRTC 将逻辑功能独立、内聚性、复用性强的部分单独抽象为模块。模块在 WebRTC 源码的 modules 目录下,主要是音视频设备、codec、流控等。

6.2.3 网络传输模块:libjingle

WebRTC重用了libjingle的一些组件,主要是network和transport组件

7、要学习WebRTC需要先理解一些基本网络协议概念。

什么是实时传输协议?

  • 实时传输协议(RTP)是专为多媒体电话(VoIP,视频会议,远程呈现系统),多媒体流(视频点播,直播)和多媒体广播而设计的网络协议。它最初由RFC1889中的IETF指定。RTC最初是为了协助IETF音频-视频传输工作组涉及寄给地理上分散的成员的视频会议而创建的。目前,RFC3550中指定的v2是过去15年中一直在使用的v2。
  • RTP的设计基于应用层框架和集成层处理的基本原理。它提供源和负载类型标识,流同步,丢包和重新排序以及媒体流监控。
  • RTP使用RTP控制协议(RTCP)报告媒体流的性能。
  • 在这个过程中,媒体发送端发送封装在RTP中的编码媒体。它还发送RTCP发送端报告,这有助于不同媒体流的额播放同步。接收端维护一个抖动缓冲区,对媒体数据包进行重新排序,并根据数据包中编码的定时信息进行播放。如果数据包丢失,接收端进行数据包恢复或者隐藏错误。最后,在RTCP接收端报告中接收机粗略或详细地对统计数据进行报告,使媒体发送端能够调整其媒体编码速率,变成更好的编解码器或改变前向纠错量。

RTP数据包报头格式

RTCP报告有三种:发送端报告,接收端报告和扩展报告。

  • RTCP发送端报告
    发送端使用RTCP发送端报告来帮助同步媒体流。为了实现这一点,它将各个媒体流的RTP时间戳与时钟时间相关联,并通知接收端当前的分组速率和比特率。
  • RTCP接收端报告
    接收端测量输入流并在RTCP接收端报告中报告粗粒度的传输统计。此报告包括当前的丢包比例,接收到的最高序列号,并有助于计算往返时间。
  • RTCP扩展报告
    RTCP扩展报告由端点用来描述复杂的度量标准,而不是RTCP接收端报告中所公开的。这包括相关的性能监控和拥塞控制指标,如抖动缓冲之后表,数据包延时变化,延时指标,丢弃数据包数量,体验质量等。新的度量标准也可以定义,只要它们涉及测量的内容,测量方式以及向其他端点报告的方式。

RTP负载格式是什么样的?

定义负载格式需要识别媒体数据包的编码。这些编码可以是两种方式中的一种:编解码器专用的,例如H.264,H.263,H.261,MPEG-2,JPEG,G.711,G.722或AMR;通用的,例如前向纠错(FEC),NACK或多路复用流。
负载文件通常为媒体编解码器指定一个定义明确的数据包格式,并描述编解码器的两种规则:聚合规则(aggregation rules)和碎片规则(fragmentation rules)。聚合规则是为编解码器定义的,与IP最大传输单元(例如音频)相比,这些编解码器产生几个小帧。碎片规则是为产生大帧的编解码器定义的,例如视频编解码器的I帧。将大型帧分成较小的数据包而不依赖于IP碎片,主要是因为IP碎片数据包通常在网络中被丢弃,尤其是通过NAT或防火墙的时候。

什么是RTP报头扩展?

RTP报头扩展旨在传送独立于媒体的信息。 更具体地说,它们携带的数据通常可以适用于多种负载格式,并且需要比发送RTCP报告更频繁地进行报告。

例如,在为交互媒体发送NACK数据包时,每隔几十毫秒会产生双向媒体流和RTP数据包。在这种情况下,RTP报头扩展可以指示哪些序列号被正确接收或丢失。因此,他们不完全依赖RTCP接收端报告发送NACK或ACK。
使用报头扩展可能非常有用,因为它们向后兼容。不了解它们的端点可能会忽略它们。此外,它们是通用的,因为不需要为每个媒体编解码器重新定义相同的扩展名。
RTP报头扩展有多种用途,包括报告网络发送时间戳和媒体会议中跨多个流均衡客户端的音频级别。

什么是RTCP报告间隔?

使用RTP,通过发送RTP媒体数据包和接收RTCP反馈数据包创建一个闭环。RTCP反馈间隔通常是会话带宽的一小部分,不会影响媒体流量。RTCP报告间隔由会话中的同步源数量和会话带宽决定。

  • 虽然会话带宽预计将在参与者之间进行分配,但实际上通常是预期同时活动的发送端的平均吞吐量的总和。例如,在音频会议中,会话带宽将是一个发送端的带宽。但是,对于视频会议,会话带宽取决于显示的用户数量。为了管理这个,会话带宽由会话管理层给出,因此为每个参与者计算相同的RTCP间隔值。
  • 会话带宽的5%应该分配给控制流量。
  • 在具有大量接收端和少量发送端的场景中,四分之一的报告带宽应由发送端平均分配,其余四分之三专用于接收端。这允许新的参与者快速从发件人报告接收CNAME和同步时间戳。对于新的参与者,RTCP时间间隔减半以快速声明他们的存在。
    推荐的RTCP最小值为5秒。这适用于单向链路,或适用于不需要检测接收质量到的会话。
  • 减少的最小值是360除以会话带宽(以秒为单位)。它适用于单播双向多媒体会话的参与者,并适时发送反馈消息来执行拥塞控制或错误修复。

基于RTCP反馈的扩展RTP文件

在端点检测到数据包丢失或者通过报告间隔中途发生拥塞的情况下,RTCP报告不能提前发送,端点必须等待下一个计划的RTCP报告。这会导致媒体比特率不稳定和振荡。为了解决这个问题,端点实现了基于RTCP的反馈的扩展RTP配置文件。这是RTP默认时间规划的扩展,可以实现快速反馈。
通过此文件,只要报告间隔平均保持不变,端点就可以调整RTCP报告间隔,以便早于下一个计划的RTCP报告发送报告。此外,它还定义了一套错误恢复反馈消息,包括否定确认(NACK),图像丢失指示(PLI),切片丢失指示(SLI)和参考图像选择指示(RPSI)。

八、WebRTC学习资料

8.1 书籍

  • 《WebRTC权威指南》: 本书适用于初学者,可以快速理解WebRTC相关的理论知识。
  • 《Learning WebRTC》 中文版:对于前端开发人员是一个很好的入门书籍。对相关传输层的开发介绍需要读者参考更多相关资料。

8.2 Demo实例

下面几个是WebRTC开发者社区的:

  • STUN服务器与客户端:这个项目在Windows、Linux和Solaris上实现了一个简单的STUN服务器和客户机。STUN协议(通过NATs简单遍历UDP)在IETF RFC 3489中描述,可在ietf.org/rfc/rfc3489.tx获得
  • WebRtcRoom Server:使用Node js开发,信令服务器使用 Socket.IO ,Android,iOS,Html,Server均做了实现

几个跨平台开发中可用的 WebRTC Demo:

  • Flutter + WebRTC Demo:Flutter WebRTC plugin ,支持 iOS、Android。 有比较高的星星哦。
  • React Native + Webrtc Demo:一个 React Native 的 WebRTC module , 支持 iOS 和Android平台;支持Video / Audio / Data Channels… 有不错的星星数2.8k
  • RTCStartupDemo :一套超级简单的信令服务器,以及配套的完全基于 WebRTC 官方 API 的客户端 demo 示例代码(含:Web/Android/iOS/Windows 全平台)。这是一个针对webrtc初学者的启动演示,包括一个基于socket.io套接字的简单信号服务器和一些客户端在Web/Android/iOS/Windows平台上演示。