最近在作RTMP直播,相关内容能够查看往期的文章。那么功能完成好了以后,才发现最难的一个问题还在后面,那就是RTMP的延迟如何下降?缓存
在具体分析前,首先咱们先要理清思路,若是是一个RTMP推拉流的过程:微信
那么针对这个流程,咱们能够看出主要的延迟只会在这三个地方发生,那么咱们来分析哪些地方可能形成延迟变大。网络
推流端并发
对于一个推流端,首先涉及到的就是编码,也就是对视频流进行封装。这里涉及到一个重要的概念GOP,指的是视频中两个I帧的间隔。那么咱们先了解一下视频编码中的I帧、B帧和P帧。
性能
I帧、B帧、P帧动画
咱们知道视频或者说是动画利用的是人眼的视觉残留的原理,经过一系列的图片,达成动画的效果。因此视频传输本质上也是传输了一帧帧的画面数据。ui
那么若是咱们每一帧的画面都是完整的画面,大概须要多少数据呢?咱们假设咱们呢传输的是1080P的8bit图组成的视频,那么每一帧就是1920x1080x8x3=49766400bit,也就是47.46MB,那么若是视频帧率是30Hz,那么每秒也就是1423.82MB。也就是在这种状况下,咱们每秒传输的数据就是1.39MB。这个数据量其实在不少状况下是比较大的,试想若是观看这样的视频10分钟,那么流量就是834MB。
编码
为了解决这个问题,目前视频传输和保存都采用了视频压缩技术,好比H.264。在这种技术下,编码器将图片分红三种,也就是I帧、B帧和P帧:spa
I帧:也就是关键帧(Intra-coded picture 内部编码帧),指的是完整的画面,在这个帧中,有着完整的画面信息。.net
B帧:双向内插帧(Bidirectional predicted picture 双向参考帧),这个画面是不完整的,若是想要依靠这个画面获得完整的画面信息,那么就须要参考前一帧和后一帧。这个是包含画面信息最少的帧。
P帧:前向预测帧(Predicted picture 预测帧),这个画面也是不完整的,若是想要依靠这个画面获得完整的画面信息,须要参考前一帧。
而视频编码就是生产一个个GOP(Group of Picture),也就是包含一个关键帧I帧的一组图片。而GOP长度就是两个I帧的距离。那么GOP对延迟有什么影响呢?由于GOP的存在,致使播放端的视频解码器须要拿到关键帧才能解码,若是一开始拿不到关键帧,那么解码器只能等待,这时就会出现黑屏,一直等到关键帧的到来。而这个最长时间是多少呢?就是一个GOP的长度。
因此为了防止黑屏的出现,不少时候服务端都会缓存前一个GOP,这就致使客户端始终从前一个I帧播放,那么延迟至少是一个GOP的长度。这时不少朋友确定会想那么咱们就减小GOP的长度不就能够了么?这个想法的确是对的,不少实时性要求很高的地方就是这么作的,之因此不是全部场景都这么作,是由于GOP过低会致使编码率压缩率变低,图像质量也没有那么好。
缓存
由于RTMP是基于TCP的,因此存在累积延迟的问题,也就是在网络条件很差的时候 ,为了保证传输的可靠性,会将失败的包保存起来,等待网络条件好的时候一并发出。可是对于直播来讲,这样无疑增长了延迟,若是网络波动较大,那么缓存反而是有害的,因此通常来讲都会将推流端的缓存设置到尽量的小。
RTMP服务端
对于服务端来讲,须要考虑的首先和上面同样,也就是缓存,若是是低延时要求,那么首先服务端的缓存也不能设计过大。那么除了缓存服务端还须要考虑上面呢?
Merged-Read
RTMP的读效率很是低,首先要先读一个字节,判断是哪一个chunk,而后读取header,再读取payload。因此通常为了提升性能,服务端会采用merged-read,也就是一次读取几毫秒的数据,进行一次读取。这样的坏处就是服务端至少要接受到这么多数据才能进行读取,而这个就是延迟的大小。因此若是是低延时的场景,那么就须要关闭这个功能,让服务端每次收到一个包就解析。
Merged-Write
一样,服务端为了提供效率,也会进行merged-write,也就是一次发送几毫秒的数据到客户端,这个一样也会致使延迟。好处是能够支持的客户端会变多。因此在低延迟的场景中咱们须要根据要求进行权衡,将这个设置到较小的值。
GOP
结果推流端的内容,服务端应当关闭GOP缓存,不缓存前一个GOP。
累积延迟
一样,由于拉流端可能采用RTMP或者HTTP-FLV,也都是基于TCP的,因此会存在累积延迟,处理这个问题的解决方法就是减小缓存区的大小,若是发现太多的缓存就丢弃。
拉流端
拉流端要考虑的其实就是一个,那就是缓存的设置以及缓存的策略。这里由于不是专业的,只能说一下思路,就是获取缓存的长度和当前播放的位置,而后二者的差就是具体的延迟。因此须要设置个阈值,当大于这个值时,就进行动态的快进。这样就能够达到无感知的延迟缩小。
总结
经过上面分析,咱们能够看出,RTMP中的延迟是没法避免的问题,咱们能作的就是尽可能根据需求来权衡延迟和性能。而这里面最重要的就是缓存,缓存的好处就是稳定,可是它的坏处也很明显,那就是带来延迟的增长。
本文分享自微信公众号 - 雨夜随笔(yuye_suibi)。
若有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一块儿分享。