前言
前几天了解了 WebRTC 服务,并且基于 webrtc 官方的 apprtc 项目搭建一个1v1的音视频对话,参见尝鲜:如何搭建一个简单的webrtc服务器。有了1v1的实战,再来看多方音视频通信的方案,看看和1v1的方案的关系与不同。
多方音视频通信三种架构方案
一、Mesh 方案
即多个终端之间两两进行连接,形成一个网状结构。这种方案是1v1 WebRTC 通信模型的扩展版,任何两个结点都可以看成一个1v1 WebRTC 通信模型。
优势:不需要服务器中转数据,STUN/TUTN 只是负责 NAT 穿越,这样利用现有 WebRTC 通信模型就可以实现,而不需要开发媒体服务器。
劣势:需要给每一个参与人都转发一份媒体流,这样对上行带宽的占用很大。参与人越多,占用的带宽就越大。客户端的机器资源的占用与参与人数成正比,当参与人数过多时,此方案就不可用了。通过实践来看,这种方案在超过 4 个人时,就会有非常大的问题。 另外,由于STUN/TUTN 只是负责 NAT 穿越,如果有部分人不能实现 NAT 穿越,就无法连接。
二、MCU(Multipoint Conferencing Unit)方案
该方案由一个服务器和多个终端组成一个星形结构。MCU 主要的处理逻辑是:接收每个共享端的音视频流,经过解码、与其他解码后的音视频进行混流、重新编码,之后再将混好的音视频流发送给房间里的所有人。
实际上服务器端就是一个音视频混合器,这种方案服务器的压力会非常大。MCU 技术在视频会议领域出现得非常早,目前技术也非常成熟,主要用在硬件视频会议领域。
三、SFU(Selective Forwarding Unit)方案
该方案也是由一个服务器和多个终端组成,但与 MCU 不同的是,SFU 不对音视频进行混流,收到某个终端共享的音视频流后,就直接将该音视频流转发给房间内的其他终端。
它实际上就是一个音视频路由转发器,并且它可以根据终端下行网络状况做一些流控,可以根据当前带宽情况、网络延时情况,选择性地丢弃一些媒体数据,保证通信的连续性。下面详细介绍一下。
总结
相比 Mesh方案,SFU 和 MCU 都需要中转服务器。由于 MCU 方案需要将多路视频混合成一路,需要大量的运算,对 CPU 资源的消耗很大,一般需要专门的硬件进行处理。而 SFU 方案由于不需要多路视频混编,所以对 CPU 的需求没有那么大,但它可能导致在多路视频的情况下,会有在同一时刻,不同的人看到的画面不一致的问题。
所以,如果你不想用中转服务器,就选择 Mesh方案;如果你对多路视频的一致性要求高,有专门硬件,建议选择 MCU 模式;其他情况建议使用 SFU 模式。
SFU方案
SFU 方案根据在网络延时时丢弃媒体数据的方式不同,分为 Simulcast 模式和 SVC 模式,
Simulcast 模式
所谓 Simulcast 模式就是指视频的共享者可以同时向 SFU 发送多路不同分辨率的视频流(一般为三路,如 1080P、720P、360P)。而 SFU 可以将接收到的三路流根据各终端的情况而选择其中某一路发送出去。
例如,由于 PC 端网络特别好,给 PC 端发送 1080P 分辨率的视频;而移动网络较差,就给 Phone 发送 360P 分辨率的视频。
SVC 模式
SVC 是可伸缩的视频编码模式。它在视频编码时将视频分成多层 —— 核心层、中间层和扩展层。上层依赖于底层,而且越上层越清晰,越底层越模糊。在带宽不好的情况下,可以只传输底层,即核心层,在带宽充足的情况下,可以将三层全部传输过去。
部署多方视频会议服务
基于上面的分析,我们实现一个基于SFU 方案的项目。开源项目包括 Licode、Janus-gateway、MediaSoup、Medooze。这儿我们部署基于 Medooze的 Demo 项目SFU。
运行环境准备
- 操作系统:Ubuntu 18.04
- 语言环境:NodeJS
apt-get update && apt-get install -y nodejs npm git-core
安装依赖
git clone https://github.com/medooze/sfu.git
cd sfu
npm install
生成证书
生成证书这部分参考尝鲜:如何搭建一个简单的webrtc服务器。证书这块未来有时间集成整理一下。
启动服务
node index.js IP
Docker 服务
Dockerfile 文件
FROM ubuntu:18.04
WORKDIR /
RUN apt-get update && apt-get upgrade && apt install -y nodejs npm git-core python3 wget curl && npm install -g n && n stable
RUN hash -r && npm install -g npm@8.5.5
RUN git clone https://github.com/medooze/sfu
WORKDIR /sfu
RUN npm install
RUN openssl req -x509 -out ./server.cert -keyout ./server.key -newkey rsa:2048 -nodes -sha256 -subj '/CN=*'
ENTRYPOINT ["node" "index.js"]
Docker 镜像
// 可以用上面的 Dockerfile 文件自己打镜像,也可用用我已经打包好的镜像
docker pull zhaowg/sfu:v1
Docker 版使用方法
docker run -it --net=host zhaowg/sfu:v1 <IP>
参考
- 极客时间-从 0 打造音视频直播系统: https://time.geekbang.org/column/intro/100031801