做直播的朋友都知道,延迟是个头疼的问题。用HLS做直播,延迟动不动就十几秒,观众在弹幕里互动,主播要过半天才能看到,体验非常割裂。我前前后后优化过好几个直播项目,把踩过的坑和有用的经验写一写。
首先得理解延迟是怎么产生的。HLS把直播流切成一段一段的TS文件,每段时长就是延迟的一大来源。如果切片时长是10秒,那光这一块就贡献了10秒延迟。
然后播放器为了流畅,不会只下载一个切片就开始播,通常会缓冲2到3个切片。这样一来,10秒的切片配上3个缓冲,理论延迟就到30秒了。还没算编码延迟、网络传输延迟、CDN缓存延迟。

优化HLS延迟,最直接的办法就是把切片时长改短。从10秒改成6秒,延迟立马降一截;改成4秒、2秒,延迟能进一步降低。
但也不是越短越好。切片太短,播放器频繁请求HTTP,服务器压力增大,而且每个切片都有MOOV头等冗余数据,太短会导致码率开销变大。一般建议控制在2到6秒之间,找个平衡点。
播放器默认的缓冲策略偏保守,为了保证不卡顿,宁可多缓冲几个切片。如果你确认观众的网速够快,可以把播放器的缓冲阈值调低。
比如hls.js里有个maxBufferLength参数,默认值可能到60秒,你改成15秒或者10秒,播放器就不会囤那么多数据了。副作用是弱网环境下更容易卡顿,这个要做好取舍。
很多人只改切片和播放器,忽略了CDN。如果CDN对M3U8索引文件和TS切片设置了很长的缓存时间,那观众拿到的可能是旧数据。
正确的做法是:M3U8索引文件缓存时间设得很短,比如1秒甚至不缓存,因为直播的索引是不断更新的;TS切片可以缓存久一点,比如1小时,因为切片生成后内容就不变了。
如果你的业务对延迟极度敏感,比如连麦、游戏直播、监控,那HLS再优化也有瓶颈。这时候该考虑WebRTC或者低延迟HLS(LL-HLS)了。
WebRTC延迟能做到500毫秒以内,但技术复杂度高,服务器成本也高。LL-HLS是苹果推出的改良版,延迟能压到2秒左右,兼容性比普通HLS差一些,需要比较新的系统和播放器支持。
总之,延迟优化是个系统工程,从推流、切片、CDN到播放器,每个环节都要配合。单改一个地方,效果有限。