1、首先要了解HLS延时的机制,也就是为什么会延时,延时主要发生在什么地方。
HTTP Live Streaming 并不是一个真正实时的流媒体系统,这是因为对应于媒体分段的大小和持续时间有一定潜在的时间延时。在客户端,至少在一个分段媒体文件被完全下载后才能够开始播放,而通常要求下载完两个媒体文件之后才开始播放以保证不同分段音视频之间的无缝连接。此外,在客户端开始下载之前,必须等待服务器端的编码器和流分割器至少生成一个TS文件,这也会带来潜在的时延。服务器软件将接收到的流每缓存一定时间后包装为一个新的TS文件,然后更新m3u8文件。m3u8文件中只保留最新的几个片段的索引,以保证观众任何时候连接进来都会看到较新的内容,实现近似直播的效果。这种方式的理论最小延时为一个ts文件的时长,一般为2-3个ts文件的时长。
所以,hls的延时主要由以下三个部分组成:
(1)服务器端的编码器和流分割器生成TS文件的时间
(2)客户端下载TS文件的时间,而通常要求下载完两个TS媒体文件
(3)客户端解码并播放时间
这三个方面里面,前两个方面我们是可以控制调节的,对于第三个方面只能取决于客户端的性能。
2、具体优化方法
由于服务器端生成TS流段需要时间,那么我们可以调节每段TS文件的大小,让其小些,那么服务器生成它的速度就加快,时间缩短。这样一来,客户端下载第一段或者前两段的时间就会减少,延时就会降低。根据上述的方式可以更改HLS的分段大小,方法是修改nginx配置文件nginx.conf,默认情况下nginx.conf文件的hls配置部分如下:
rtmp { server { listen 1935; chunk_size 4096; application live { live on; } hls on; hls_path /tmp/hls; } }
文件并没有设置HLS 分段长度,添加设置:
hls_fragment 1s;
将每段的长度限定为1s,HLS官方推荐的是10s,但是在我这里10s延时太大。但是段的时长越短,服务器的负载越大,延时越少。对于这句话我不是十分理解,至少我并没有发现服务器负载增加。当每段的长度固定之后,播放列表的长度也会影响延时时间,而且会对再次播放时的开始时间产生影响,非首次播放时,客户端会在播放列表的开头开始播放,所以总的延时时间等于播放列表长度加上上述的延时时间。所以将播放列表长度不要设置太大:
hls_playlist_length 3s;
这样设置完之后的配置文件RTMP模块配置部分为:
rtmp { server { listen 1935; chunk_size 4096; application live { live on; } hls on; hls_path /tmp/hls; hls_fragment 1s; hls_playlist_length 3s; } }
配置完成后重新启动nginx,重新使用ffmpeg推流,结果延时时间降到7~8s。
优化前测试结果:26S
优化后VLC播放测试结果:11s