
本文共 5777 字,大约阅读时间需要 19 分钟。
【网络通信 -- 直播】WebRTC -- 多人音视频通讯架构与主流服务器简介
【0】WebRTC 一对一通信流程
WebRTC 本身提供的是 1 对 1 的通信模型,在 STUN/TURN 的辅助下,若能实现 NAT 穿越,那么两个浏览器便可以直接进行媒体数据交换;若不能实现 NAT 穿越,那么只能通过 TURN 服务器进行数据转发的方式实现通信;
在 1 对 1 通信中,WebRTC 首先尝试两个终端之间是否可以通过 P2P 直接进行通信,若终端之间无法直接通信,则会通过 STUN/TURN 服务器进行中转;若端与端之间可以直接通信,那么 STUN/TURN 服务器的作用便只是用于各终端收集 reflx 类型的 Candidate;
图示可以分为 4 部分
- 两个 WebRTC 终端,负责音视频采集、编解码、NAT 穿越、音视频数据传输;
- 一个 Signal(信令)服务器,负责信令处理,如加入房间、离开房间、媒体协商消息的传递等;
- 一个 STUN/TURN 服务器,负责获取 WebRTC 终端在公网的 IP 地址,以及 NAT 穿越失败后的数据中转;
大致交互流程概述
- 当一端(WebRTC 终端)进入房间之前,首先会检测自己的设备是否可用;若此时设备可用,则进行音视频数据采集;采集到的数据一方面可以做预览,另一方面,可以将其录制下来保存成文件,等到视频通话结束后,上传到服务器供用户回看;
- 在获取音视频数据就绪后,WebRTC 终端要发送 “加入” 信令到 Signal 服务器;Signal 服务器收到该消息后会创建房间;在另外一端,也要做同样的事情,只不过它不是创建房间,而是加入房间;待第二个终端成功加入房间后,第一个用户会收到 “另一个用户已经加入成功” 的消息;
- 此时,第一个终端将创建 “媒体连接” 对象,即 RTCPeerConnection,并将采集到的音视频数据通过 RTCPeerConnection 对象进行编码,最终通过 P2P 传送给对端;
- 在进行 P2P 穿越时很有可能失败,当 P2P 穿越失败时,为了保障音视频数据仍然可以互通,则需要通过 TURN 服务器进行音视频数据中转;
- 当音视频数据来到对端后,对端首先将收到的音视频数据进行解码,最后再将其展示出来,这样就完成了一端到另一端的单通;
- 若双方要互通,两方都要通过 RTCPeerConnection 对象传输自己一端的数据,并从另一端接收数据;
【1】多人音视频通讯架构
【1.1】Mesh 方案
Mesh 方案,即多个终端之间两两进行连接,形成一个网状结构;比如 A、B、C 三个终端进行多对多通信,当 A 想要共享媒体(比如音频、视频)时,A 需要分别向 B 和 C 发送数据;同样的道理,B 想要共享媒体,就需要分别向 A、C 发送数据,依次类推;该方案对各终端的带宽要求比较高;
在上图中,B1、B2、B3、B4 分别表示 4 个浏览器,它们之间两两相连,同时还分别与 STUN/TURN 服务器进行连接;
优势
- 不需要服务器中转数据,STUN/TUTN 只是负责 NAT 穿越,这样利用现有 WebRTC 通信模型就可以实现,而不需要开发媒体服务器;
- 充分利用了客户端的带宽资源;
- 节省了服务器资源,由于服务器带宽往往是专线,价格昂贵,这种方案可以很好地控制成本;
劣势
- 共享端共享媒体流时,需要给每一个参与人都转发一份媒体流,这样对上行带宽的占用很大;并且占用较大的 CPU、Memory 等资源;
- 一般来说,客户端的机器资源、带宽资源往往是有限的,资源占用和参与人数呈线性相关;导致多人通信的规模非常有限;
- 在多人通信时,若存在部分人不能实现 NAT 穿越,但还想让这些人与其他人互通,就显得很麻烦,需要做出更多的可靠性设计;
【1.2】MCU(Multipoint Conferencing Unit)方案
MCU(Multipoint Conferencing Unit)方案,该方案由一个服务器和多个终端组成一个星形结构;各终端将自己要共享的音视频流发送给服务器,服务器端会将在同一个房间中的所有终端的音视频流进行混合,最终生成一个混合后的音视频流再发给各个终端,这样各终端就可以看到 / 听到其他终端的音视频;实际上服务器端就是一个音视频混合器,这种方案服务器的压力会非常大;
MCU 方案的模型是一个星形结构,如下图所示
- B1 与 B2 同时共享音视频流,它们首先将流推送给 MCU 服务器,MCU 服务器收到两路流后,分别将两路流进行解码,之后将解码后的两路流进行混流,然后再编码,编码后的流数据再分发给 B3 和 B4;
- 对于 B1 由于其是其中一个共享者,因此 MCU 给 B1 推的是没有混合其共享流的媒体流,此例中是直接推 B2 的流给 B1
- 对于 B2 来说 MCU 给 B2 发的是 B1 的共享流;
MCU 主要的处理逻辑如下图所示
处理过程
- 1. 接收共享端发送的音视频流;
- 2. 将接收到的音视频流进行解码;
- 3. 对于视频流,要进行重新布局,混合处理;
- 4. 对于音频流,要进行混音、重采样处理;
- 5. 将混合后的音视频进行重新编码;
- 6. 发送给接收客户端;
优势
- 1. 技术成熟,在硬件视频会议中应用非常广泛;
- 2. 作为音视频网关,通过解码、再编码可以屏蔽不同编解码设备的差异化;
- 3. 将多路视频混合成一路,所有参与人看到的是相同的画面;
劣势
- 1. 重新解码、编码、混流,需要大量的运算,对 CPU 资源的消耗很大;
- 2. 重新解码、编码、混流还会带来延迟;
- 3. 由于机器资源耗费很大,所以 MCU 所提供的容量有限,一般十几路视频就是上限了;
【1.3】SFU(Selective Forwarding Unit)方案
SFU(Selective Forwarding Unit)方案,该方案由一个服务器和多个终端组成,SFU 不对音视频进行混流,收到某个终端共享的音视频流后,就直接将该音视频流转发给房间内的其他终端,实际上是一个音视频路由转发器;
图中,B1、B2、B3、B4 分别代表 4 个浏览器,每一个浏览器都会共享一路流发给 SFU,SFU 会将每一路流转发给共享者之外的 3 个浏览器
优势
- 1. 由于是数据包直接转发,不需要编码、解码,对 CPU 资源消耗很小;
- 2. 直接转发也极大地降低了延迟,提高了实时性;
- 3. 带来了很大的灵活性,能够更好地适应不同的网络状况和终端类型;
劣势
- 1. 由于是数据包直接转发,参与人观看多路视频的时候可能会出现不同步;相同的视频流,不同的参与人看到的画面也可能不一致;
- 2. 参与人同时观看多路视频,在多路视频窗口显示、渲染等会带来很多麻烦,尤其对多人实时通信进行录制,多路流也会带来很多回放的困难;
【1.3.1】SFU -- Simulcast 模式
所谓 Simulcast 模式就是指视频的共享者可以同时向 SFU 发送多路不同分辨率的视频流,SFU 可以将接收到的三路流根据各终端的情况选择其中某一路发送出去;Simulcast 模式对移动端的终端类型非常有用,可以灵活而又智能地适应不同的网络环境;
【1.3.2】SFU -- SVC 模式
SVC 是可伸缩的视频编码模式,其在视频编码时将视频分成多层,即核心层、中间层和扩展层;上层依赖于底层,而且越上层越清晰,越底层越模糊;在带宽不好的情况下,可以只传输底层,即核心层,在带宽充足的情况下,可以将三层全部传输过去;
图示,PC1 共享的是一路视频流,编码使用 SVC 分为三层发送给 SFU;SFU 根据接收端的情况,发现 PC2 网络状况不错,于是将 0、1、2 三层都发给 PC2;发现 Phone 网络不好,则只将 0 层发给 Phone;从而可以适应不同的网络环境和终端类型;
【2】主流服务器简介
【2.1】LicodeLicode
源码地址,
LicodeLicode 既可以用作 SFU 类型的流媒体服务器,也可以用作 MCU 类型的流媒体服务器;一般情况下,用于 SFU 类型的流媒体服务器;
Licode 不仅仅是一个流媒体通信服务器,而且还是一个包括了媒体通信层、业务层、用户管理等功能的完整系统,并且该系统支持分布式部署; Licode 是由 C++ 和 Node.js 语言实现,其中,媒体通信部分由 C++ 语言实现,而信令控制、用户管理、房间管理用 Node.js 实现;整体框架- Nuve 是一个 Web 服务,用于管理用户、房间、产生 token 以及房间的均衡负载等相关工作;它使用 MongoDB 存储房间和 token 信息,但不存储用户信息;
- ErizoController,用于管理控制,信令和非音视频数据都通过它接收;它通过消息队列与 Nuve 进行通信,即 Nuve 可以通过消息队列对 ErizoController 进行控制;
- ErizoAgent,用于音视频流媒体数据的传输,可以分布式布署;ErizoAgent 与 ErizoController 的通信也是通过消息队列,信令消息通过 ErizoController 接收到后,再通过消息队列发给 ErizoAgent,从而实现对 ErizoAgent 的控制;
劣势
- 1. 在 Linux 下目前只支持 Ubuntu 14.04 版本,在其他版本上很难编译通过;
- 2. Licode 不仅包括了 SFU,而且包括了 MCU,其代码结构比较重,学习和掌握比较复杂;
- 3. Licode 的性能一般
【2.2】Janus-gatewayJanus
源码地址,
Janus-gatewayJanus 是一个非常有名的 WebRTC 流媒体服务器,它是以 Linux 风格编写的服务程序,采用 C 语言实现,支持 Linux/MacOS 下编译、部署,但不支持 Windows 环境;
整体框架
插件层/应用层
插件层又称为应用层,每个应用都是一个插件,可以根据用户的需要动态地加载或卸载掉某个应用;
在 Janus 中默认支持的插件包括- SIP:这个插件使得 Janus 成了 SIP 用户的代理,从而允许 WebRTC 终端在 SIP 服务器(如 Asterisk)上注册,并向 SIP 服务器发送或接收音视频流;
- TextRoom:该插件使用 DataChannel 实现了一个文本聊天室应用;
- Streaming:允许 WebRTC 终端观看 / 收听由其他工具生成的预先录制的文件或媒体;
- VideoRoom:实现了视频会议的 SFU 服务,实际就是一个音 / 视频路由器;
- VideoCall:这是一个简单的视频呼叫的应用,允许两个 WebRTC 终端相互通信;
- RecordPlay:可以将发送给 WebRTC 的数据录制下来,可以通过 WebRTC 进行回放;
传输层
- 媒体数据传输层主要实现了 WebRTC 中需要的流媒体协议及其相关协议,如 DTLS 协议、ICE 协议、SDP 协议、RTP 协议、SRTP 协议、SCTP 协议等;
- 信令传输层用于处理 Janus 的各种信令,支持的传输协议包括 HTTP/HTTPS、WebSocket/WebSockets、NanoMsg、MQTT、PfUnix、RabbitMQ;
【2.3】Mediasoup
源码地址,
Mediasoup 由应用层和数据处理层组成;应用层通过 Node.js 实现;数据处理层由 C++ 语言实现,包括 DTLS 协议实现、ICE 协议实现、SRTP/SRTCP 协议实现、路由转发等;
整体架构
Mediasoup 把每个实例称为一个 Worker,在 Worker 内部有多个 Router,每个 Router 相当于一个房间;在每个房间里可以有多个用户或参与人,每个参与人在 Mediasoup 中由一个 Transport 代理;即对于房间(Router)一个 Transport 就相当于一个用户;
- WebRtcTransport 用于与 WebRTC 类型的客户端进行连接,如浏览器;
- PlainRtpTransport 用于与传统的 RTP 类型的客户端连接,通过该 Transport 可以播放多媒体文件、FFmpeg 的推流等;
- PipeTransport 用于 Router 之间的连接,即一个房间中的音视频流通过 PipeTransport 传到另一个房间;
在每个 Transport 中可以包括多个 Producer 和 Consumer
- Producer 表示媒体流的共享者,它分为两种类型,即音频的共享者和视频的共享者;
- Consumer 表示媒体流的消费者,它分为两种类型,即音频的消费者和视频的消费者;
【2.4】MedoozeMedooze
源码地址,
MedoozeMedooze 是一款综合流媒体服务器,它不仅支持 WebRTC 协议栈,还支持很多其他协议,如 RTP、RTMP 等;
整体架构
核心层
- Medooze 支持 RTP/RTCP、SRTP/SRCP 等相关协议,可以实现与 WebRTC 终端进行互联;
- Medooze 可以接入 RTP 流、RTMP 流等,可以使用 GStreamer/FFmpeg 向 Medooze 推流;
- Medooze 还支持录制功能,以便后期回放;
控制逻辑层
- Medooze 的控制逻辑层通过 Node.js 实现,Medooze 通过 Node.js 对外提供了完整的控制逻辑操作相关的 API,通过这些 API 可以很容易的控制 Medooze 的行为;
缺点
- Medooze 使用的异步 IO 事件处理的 API 是 poll,poll 在处理异步 IO 事件时,与 Linux 下最强劲的异步 IO 事件 API epoll 相比要逊色不少
参考致谢
本博客为博主的学习实践总结,并参考了众多博主的博文,在此表示感谢,博主若有不足之处,请批评指正。
【1】
【2】
【3】
发表评论
最新留言
关于作者
