前言
个人根据工作经验和文章总结,如有错误,请指正留言。
降低延时
首先,流媒体传输,涉及到很多步骤,每一步都可能产生延时,所以降低延时要从多方面考虑,但是降低延时,要小心影响画质。
从摄像头采集,到编码,到推流,到拉流,到解码,到渲染,中间很多过程都有可能带来延迟。
所以,降低延时,就应该从各个方面去思考如何降低:
-
采集方面:
-
如果是本地编码,最好是选择驱动摄像头,输出yuv420p常用于编码的格式
-
尽快少或者不做画面优化。如果非要优化,做好多线程
-
有些采集设备,自动编码输出rtp/rtsp流,比如海康威视的一些摄像头,如果不需要做任何处理就想得到低延时的编码码流,其实也是一个方案,就是可能价格上会有点贵
-
-
编码方面:
-
优先选择硬件编码。如果是软编码,可以设置为多线程编码。
-
设置合适的编码参数设置:例如合适的码率,合适的profile,加快编码速度,减少甚至不要B帧,设置合适的QP量化值等方法。
-
减少IDR帧和I帧间隔,保证IDR帧前都要有sps和pps信息,可以加快后续解析和解码速度
-
编码器设置低延时无缓存策略:比如x264编码器,将tune设置为zerolatency
-
-
图像处理:
-
使用延时低性能好的方法,尽量降低延时产生的可能
-
使用GPU加速。例如图片的缩放,使用GPU升采样、降采样加速速度。图片亮度调节、图片拼接、贴图等,也可以考虑OpenGL利用GPU实现。
-
-
传输方面:
-
选择合适的网络协议,不用延时高的协议。例如选择RTP/RTSP/SRT/RTMP/WebRTC等协议,避免HTTP-FLV,HLS,DASH等高延时的协议。
-
优先选择以UDP为基础相关的协议,实在不行再使用TCP相关的协议。不少协议是可以设置TCP/UDP传输的,比如RTSP就可以指定使用UDP还是TCP传输。
-
选用良好的传输路径,有线肯定是优于无线的。
-
如果是直播,部署CDN等。如果是复杂网络,需要配置好交换机参数。如果是组播,最好还要设置一下TTL。
-
优化网络环境,保证相关端口的开启。
-
-
解码方面:
-
优先选择硬件解码。如果是软解码,可以多线程。
-
合适的解码参数设置。
-
-
渲染方面:
-
使用性能更好的框架,比如opengl,Linux使用DRM/x11/wayland更加底层的渲染,window使用Direct3D渲染
-
将YUV和RGB的转换,放opengl里面处理,使用GPU计算,然后直接渲染
-
CPU和GPU性能不设限制 (有些芯片会给性能设限影响渲染,比如RK3588)
-
使用gstreamer的话,最好加上sync=false,不然有时候很卡,很多缓冲被丢弃
-
-
其他:
-
服务器关键帧缓存策略:可以在服务器缓存当前gop的关键帧,新用户解析流时候保障先拿到I帧在获取当前时间的b/p帧,则可以大大提高解析时间。
-
推流端降低gop间隔策略:缩短gop时间,可以很明显提高客户端首帧关键帧解析等待时间
-
拉流端probesize调节策略:这个主要是使用ffmpeg的时候,优先使用avformat_find_stream_info解析,直到刚好被解析的数据包含一个I帧,否则会进行循环解析。所以,可以调节AVFormatContext.probesize长度和时间,改善解析接口延迟,但并不是越短越好,应该有一个较为合适的范围。
-
解码端也设置为零延时无缓存策略,但是可能导致画质不太好。
-
主动丢帧策略:如果网络情况不好,在缓存的buffer中,如果超过一定阈值就清空,可能导致短暂的跳帧现象,但是很快恢复低延时。
-
提高质量
质量,一方面是延迟,一方面是画质和音质。降低延迟,可以参考上一个问题,以下说明提高质量:
可以参考 WebRTC 的机制:
-
NACK:通过丢包重传解决丢包问题,会增加延时。
-
FEC:通过冗余数据解决丢包问题,会增加带宽占用。
-
JitterBuffer:通过队列对接收到的数据进行缓冲,出队时将数据包均匀平滑的取出,解决视频的乱序与抖动。
-
NetEQ:类似 JitterBuffer,解决音频的乱序与抖动。