客户端播放 hls 的流程如上图:
综上,传统 hls 延时时间为 12s+2rtt;
在 CDN 场景下,当客户端 1 第一次请求到 CDN 时,由于 m3u8 尚未被缓存,此时回源获取到包含 1-3 分片的 m3u8 播放列表。之后,源站生成了分片 4,客户端 2 再请求 CDN 时,还是只会返回 1-3 分片,因为 CDN 不知道源站的播放列表已经更新。此时延时会更大。
源站、CDN 和客户端支持 HTTP/2
低延迟 hls 是对传统 hls 的扩展,并向后兼容。主要做了一下五个方面的提升:
降低发布延时的方式是允许服务器在主分片准备好之前,先发布其中部分内容。假设当前一个分片时长为 6s,可将其切成 30 个小部分,每部分包含 200ms,可独立被客户端获取并播放。且当一个分片被全部生成后,其部分片段会被删除。
具体来说,就是在服务器上还没有新分片之前,客户端就已经发起对该分片的请求。一旦服务器上生成了该分片,就可以立即推送给客户端。此种方式可以在小于 1rtt 的时间内发现新分片。
客户端第一次请求到全量播放列表后,会和服务器建立起一条连接。此后当有新分片生成时,服务器会主动将 m3u8 和 ts 分片推送给客户端,减少了一次轮询的 rtt 时间。
由于服务器推送方式在 CDN 推送场景下不友好,因此该方案已废除。取而代之的是请求阻塞方式。具体来说,就是客户端根据现有序号,计算出下一个 ts 分片的序号并请求服务器,服务器会阻塞请求,直到该分片准备好再返回。
客户端第一次请求 m3u8 时,服务器会返回全量分片列表。此后客户端只会关心 m3u8 的增量部分,因此发起的是增量请求。返回数据相比原始全量数据会大大减少,以便于放在一个 MTU 数据包内返回。
由于是增量更新 m3u8,当 CDN 上有两种码率的流时,每次返回时可以携带额外信息。因此当客户端需要切换到不同码率时,就可以直接切换。