基于WebRTC的直播CDN
1 背景
本文介绍一下我们这两年做的直播系统架构,系统中媒体相关服务直接叠加在搜狐视频的点播CDN之上,业务相关服务依托于大搜狐云。
2 功能
主要特性:
- 支持WebRTC、RTMP推流;
- 支持WebRTC、FLV、HLS、FMP4拉流;
- 最优用户接入;
- 最短回源路径;
- 全平台SDK,包括H5、iOS、Android、PC。
3 架构
整体上这个系统是一个典型的CDN结构,主要包含调度系统、CDN源节点和CDN边缘节点。
节点服务列表:
服务 | 功能 |
---|---|
Transfmtd | 转格式服务,主要负责WebRTC的RTP流与RTMP流的互转。 |
Janus | WebRTC流转发服务,主要负责WebRTC流的推、拉。 |
Merge | 合流服务,主要负责多个流的合流,用于使用MCU的场景。 |
Segmentd | 切片服务,用于推RTMP流时的转封装、切片,可以切成FLV、HLS、FMP4等格式。 |
Controld | 控制服务,主要用于管理节点内的所有服务,流的管理,并负责与Masterd服务的交互。 |
Edged | 边缘服务,主要用于拉FLV、HLS、FMP4流。 |
所有节点内部的服务都由Nginx代理。
调度系统服务列表:
服务 | 功能 |
---|---|
Named | 流名服务,流名的生成、校验。 |
Masterd | 主控服务,用于管理所有的节点,并自动生成最短回源路径。 |
Schedule | 调度服务,用于管理用户地域与节点的关系,管理流与节点的关系。 |
4 主要业务
4.1 推流
不同的推流模式由推流地址中携带的参数决定。
4.1.1 推WebRTC
- 推流端请求Named,请求、校验流名,并获得schedule地址;
- 推流端请求schedule,获得地域、运营商匹配的推流Janus;
- 推流端请求Janus,开始推流;
- Janus请求Controld,创建一路流,并开始传输RTP;
- Controld请求Masterd,通知流信息;
- Masterd请求Schedule,通知流与节点信息;
4.1.2 推RTMP
使用Nginx RTMP模块接收RTMP流:
- 推流端请求Named,请求、校验流名,并获得schedule地址;
- 推流端请求schedule,获得地域、运营商匹配的推流地址;
- 推流端开始推流到推流地址,Nginx RTMP模块收到RTMP流;
- Nginx 上的一个自定义模块会请求Segmentd服务,Segmentd服务使用ffmpeg拉RTMP流并根据推流的参数进行切片;
- Segmentd请求Controld,创建一路流,并开始传输切片数据(FLV/HLS/FMP4);
- Controld请求Masterd,通知流信息;
- Masterd请求Schedule,通知流与节点信息。
4.1.3 推WebRTC转RTMP
- 推流端请求Named,请求、校验流名,并获得schedule地址;
- 推流端请求schedule,获得地域、运营商匹配的推流Janus;
- 推流端请求Janus,开始推流;
- Janus检查推流参数判断需要转成RTMP,则请求Transfmtd服务,传递sdp,开始进行转换;
- Transfmtd使用ffmpeg,根据sdp以及转换参数将RTP转成RTMP,并推流给Segmentd切片服务;
- Segmentd请求Controld,创建一路流,并开始传输切片数据(FLV/HLS/FMP4);
- Controld请求Masterd,通知流信息;Controld请求Masterd,通知流信息;
- Masterd请求Schedule,通知流与节点信息;
4.1.4 推RTMP转WebRTC
- 推流端请求Named,请求、校验流名,并获得schedule地址;
- 推流端请求schedule,获得地域、运营商匹配的推流地址;
- 推流端开始推流到推流地址,Nginx RTMP模块收到RTMP流;
- Nginx 上的一个自定义模块会请求Transfmtd服务,Transfmtd服务使用ffmpeg拉RTMP流并根据推流的参数转换成RTP;
- Transfmtd请求Controld,创建一路流,并开始传输RTP;
- Controld请求Masterd,通知流信息;
- Masterd请求Schedule,通知流与节点信息。
4.2 拉流
4.1.1 拉WebRTC
- 拉流端请求Masterd,获得流相关信息,并获得schedule地址;
- 拉流端请求schedule,获得地域、运营商匹配的拉流Janus;
- 拉流端请求Janus,开始拉流;
- Janus请求本地Control,请求流数据,如果Controld上已经缓存该流,则直接返回数据,否则到5;
- Controld请求Masterd,请求回源路径,Masterd将根据当前的整体网络路由状态返回一个最短路径;
- 每个Controld向路径上的下一跳请求数据,直到请求到达某个命中的Controld并返回数据,回源路径上的所有Controld都将缓存该流。
4.2.2 拉FLV/HLS/FMP4
- 拉流端请求Masterd,获得流相关信息,并获得schedule地址;
- 拉流端请求schedule,获得地域、运营商匹配的拉流地址;
- 拉流端请求拉流地址,也就是Edged,如果Edged已经缓存该流,则直接返回数据,否则到4;
- Edged请求本地Control,请求流数据,如果Controld上已经缓存该流,则直接返回数据,否则到5;
- Controld请求Masterd,请求回源路径,Masterd将根据当前的整体网络路由状态返回一个最短路径;
- 每个Controld向路径上的下一跳请求数据,直到请求到达某个命中的Controld并返回数据,回源路径上的所有Controld都将缓存该流。
5 最短回源路径
- Masterd服务管理所有Controld的连接;
- Masterd周期性地向Controld服务发起网络探测请求,获得链路参数(丢包、延迟);
- Controld服务在实际媒体数据传输过程中,获得链路参数(丢包、延迟);
- Mastered构建Controld有向全通图,顶点为Controld,边为链路参数;
- 在拉流需要回源时,使用dijkstra算法计算最短回源路径。
6 业务系统
上面未涉及业务系统,业务系统主要包含:
- 流的管理;
- 用户管理;
- 应用授权管理等。
我们开始的目标是做成平台,同时针对业务系统的可定制的需求,我们将APP SDK设计成了可以热加载定制业务的模式,后面会在另外一篇文章中介绍。
7 一些特性/问题
7.1 WebRTC与其他格式的兼容性
WebRTC默认的流控策略会修改分辨率,在RTP转换成其他格式时,分辨率的变化会导致播放出问题,可选的做法是在Janus上强制转码成固定分辨率。另外一种办法是固定推流分辨率,但是目前在浏览器上,如果不是抓屏业务,WebRTC接口无法设置为固定分辨率,而在APP上可以做到,具体参考我这篇文章。
7.2 Janus的优化以及丢包
我们修改了Janus的默认带宽检测、NACK模块,跟WebRTC保持兼容,并在SDK上做了优化,有效降低了卡顿率,参考我这篇文章,目前在30%的丢包下可以流畅进行视频通话。
7.3 延迟
延迟主要依赖于CDN的部署情况、用户侧的网络条件,据不完全测试,目前的端到端延迟可以达到250ms。
7.4 秒开
参考我这篇文章,在我们默认的业务环境下,所有平台端可以达到600ms的首开时间。
7.5 安全性
传输层面有以下加密措施。
- 对WebRTC流,从信令到媒体都是加密的;
- RTMP推流,本身是不加密的,但是可以添加扩展支持RTMPS;
- FLV、HLS、FMP4拉流,可以通过HTTPS。
在应用层面,可以集成我们的DRM模块,这样即使盗播者拿到最终播放地址也无法播放,只有我们的私有播放器才能播放。当然这个特性只是针对APP,对浏览器来说不存在DRM,因为谷歌的widevine服务无法使用。