“易 +”开源计划丨基于 WebRTC 的低延时播放器设计和实践
前言
网易云信低延时直播(Low-Latency Streaming,LLS)是在网易云信标准直播的基础上,依托自研的全球实时传输网 WE-CAN 推出的低延时直播产品方案。在保障低延时的同时,具有极致秒开,低卡顿的特性。同时兼容标准直播的推流和云端媒体处理能力,方便客户从标准直播迁移到低延时直播上来。
云信低延时播放器 SDK 是一个传输层的 SDK,基于 WebRTC 进行开发,包含信令和媒体建联、音视频数据接收、弱网对抗等能力,具有较好的 QoE 性能。
低延时播放器框架
低延时播放器包含 3 个模块:
WebRTC
包含媒体建联,数据接收,数据包排序组帧,弱网对抗等能力。
RtdEngine
WebRTC 的封装层,包含 API,引擎创建,信令建联,媒体数据的回调等。
FFmpeg plug-in
将 RtdEngine 的 API 封装成 FFmpeg 插件,扩展了 AVInputFormat 类型 ff_rtd_demuxer。
低延时播放器数据流向
低延时播放器 SDK 的 Tansport 模块从 WE-CAN 传输网接收到音视频的 RTP 包后,分别送到 NetEQ 和 JitterBuffer 中,进行排序、组帧、弱网对抗等操作,最终回调到 RtdEngine 模块进行存储,播放器通过 FFmpeg 插件 RtdDemuxer 从 RtdEngine 中读取音视频数据。其中视频回调格式为 H264/H265,音频回调的格式为 PCM。
低延时播放器 SDK 的接入
目前市面上的播放器可以分为 2 种,基于 FFmpeg 的播放器和非 FFmpeg 播放器,针对不同的播放器类型,我们提供了不同的接入方式,最大程度降低接入成本。
基于 FFmpeg 的播放器接入
目前市面上现有的播放器多数是基于 FFmpeg 开发的,为了方便接入,我们扩展了 FFmpeg 的 AVInputFormat 类型 ff_rtd_demuxer,实现其定义的接口,包含 rtd_probe,rtd_read_header,rtd_read_packet,rtd_read_close。
接入方式如下,以 ffmpeg 4.3 版本的 ffplay 为例:
将 SDK 中的 rtd_dec.c 文件拷贝到 ffmpeg/libavformat 目录下
修改 ffmpeg/libavformat/Makefile 文件,添加 rtd_dec.c 文件的编译
注册扩展的 AVInputFormat ff_rtd_demuxer,修改 ffmpeg/libavformat/allformats.c 文件,添加 ff_rtd_demuxer
添加 FFmpeg configure 时 SDK 头文件和库文件的依赖
编译 FFmpeg
将编译好的 FFmpeg 库文件和对应的 rtd.dll 文件一起放到播放器中,播放器就具备了低延时直播的能力。使用 nertc:// 开头的拉流地址,播放器不需要做任何修改,就可以使用低延时拉流的能力
非 FFmpeg 的播放器接入
针对非 FFmpeg 的播放器,我们直接调用 rtd_api.h 中提供的 API 接口,接入流程如下:
下面给出伪代码示例:
关键指标优化
针对播放首屏时间和弱网抗性,我们做了一些优化。
首帧优化
云信低延时播放器从开始建联到首帧数据回调耗时在 200ms 左右,具体优化如下:
服务器支持 GOP 缓存
服务器总是从关键帧开始发数据,当你订阅流的时候服务器不一定有关键帧,需要等待下一个关键帧到来,非常影响首帧时间。为此服务器缓存就近的 GOP,客户端订阅流的时候服务器直接从缓存的 GOP 开始发送关键帧,不需要等待。不过这样起播阶段端到端延时会大一些,需要播放器配合追帧逻辑来进行延时追赶。
首个关键帧丢包快速重传
首个关键帧前面几个包丢失,很难检测出前面丢了几个包,这样会造成首帧组帧不完整,影响出帧,进而影响首帧时长。我们在信令交互阶段服务器通知客户端首个包的序列号,这样客户端可以跟接收到的首个 rtp 包的序列号进行比较,能够快速检测出丢包个数,快速触发重传,降低首个关键帧组帧耗时。
首个关键帧快速出帧
jitterBuffer 组帧完成,在出帧的时候会有一个等待时间,为了让播放器快速拿到视频帧进行解码渲染,我们减小前面几帧的等待时间,让视频帧快速出帧,播放器快速接收到数据进行解码渲染。
抗性优化
在端到端延时 1s 的情况下能够抗 40% 左右的丢包,具体优化如下:
NACK 优化
WebRTC 默认没有开启音频的 nack,需要开启音频 nack,同时在 SDP 协商时带上 nack 能力。且音频发送 nack 请求的频率默认是 100ms 一次,效率较低,可以通过实时计算的 rtt 值来调整 nack 请求的发送频率,提高重传效率。
动态 jitterBuffer
播放过程中实时监控网络质量,根据丢包率、rtt、重传耗时、帧抖动等信息来动态调节 jitterBuffer 大小。在网络好的时候降低 jitterBuffer,保障低延时效果,网络较差的时候,拉伸 jitterBuffer,通过牺牲部分延时来换取流畅。
FEC/RED
通过 FEC 和 RED 携带冗余包的方式来对抗丢包,在 rtt 较大的时候,冗余包比重传效率更高。
效果展示
下图为 OBS 推流,jitterBuffer 设为 500ms,低延时播放的端到端延时在 900ms 左右。
目前云信低延时播放器 SDK 已经开源,接下来我们会持续的迭代和更新。后续的版本中我们会重点支持 H265 和 RSFEC,同时还会不断的优化首帧时长,端到端延时以及弱网抗性等核心指标。
在不久的将来,我们还会开源低延时推流 SDK,为开发者提供全链路低延时的解决方案。
网易智企【易+】开源计划已正式发布网易云信低延时直播方案。
查看网易云信低延时播放器源代码等:
https://github.com/GrowthEase/LLS-Player
https://gitee.com/GrowthEase/lls-player
其他已开源项目:
网易会议开源代码:
版权声明: 本文为 InfoQ 作者【网易智企】的原创文章。
原文链接:【http://xie.infoq.cn/article/24f8caa39a41f29d17e08ce71】。文章转载请联系作者。
评论