F0ed2de07e0f2e0a0835f1bce168277e
Session 502 低延迟的 HLS

HLS(HTTP Live Streaming) 是苹果推出的、支持动态码率的流媒体技术。HLS 实现了通过常规的 http 服务器也能给客户端发送视频和音频内容。

HLS 常规的流程如下:

  • 视频采集设备采集到原始的音视频;
  • 服务端对原始数据进行转码,转出分片 MP4 (如 m3u8),以及存储分片信息的 index file;
  • 源服务器(这里的源指相对于 CDN 的 origin) 通过 HTTP 下发到播放端;
  • 运行 iOS 和 macOS 系统的端解析 index file 并根据具体当前的进度请求具体的 Segment 并解码播放。

苹果 AVPlayer 天生支持 HLS 协议的媒体

HLS 因为其简单,易于扩展,分片可以通过 CDN 缓存大幅减少源站服务器的压力,是一对多直播的理想协议。但存在最大的问题就是:普遍都有20~30 秒的延迟。

回到正题,今年 502 的 session 主要介绍了苹果推出了一种低延迟的 HLS 技术。

为什么要低延迟呢?

众所周知,虽然我们看 WWDC 这样的直播时延迟高些低些似乎并不影响体验,但一些直播内容却对延迟非常敏感。比如:

  • 体育类
  • 重大新闻
  • 实时交互的游戏直播
  • 新闻发布会、颁奖典礼等

那既然苹果这次推出了专门针对此类内容的低延迟的技术,那到底延迟能降到多低呢?我们看一下苹果官方给出的数据:

  • 实际应用和有线的卫星电视一样:2-8 秒;
  • 设计理论:1-2 秒(延迟不随着规模扩大而扩大);

pretty impressive!感觉已经是大规模直播能做到的极限了。而且虽然延迟被极限优化了,HLS 传统的向后兼容、动态码率、CDN 支持等特性都不会受到影响。

怎么做的?

要明白这次优化做了什么,首先要分析一下传统的 HLS 的延迟都来自于哪些地方。

延迟原因 1,HLS 本身的流程流转

下图是比较经典的 HLS 交互流程图:

  • 我们的摄像机拍到了新的一帧 frame#1, 并送到了服务器,服务器一般会把 6 秒的数据编码成一个 Segment,所以我们的 frame#1 最坏需要 6 秒才能编码完毕。
  • 客户端根据一定的策略向服务端请求 Playlist 是否有更新,最好的情况就是 6 秒编码完毕之后立即请求,最坏情况则是在 Segment编码完毕之后,过 5.9 秒客户端才来请求最新的 Playlist
  • 请求到 Playlist 以后,客户端会按照 Playlist 的信息请求最新的 Segment
  • 请求到最新的 Segment,解码播放

可见HLS 本身就自带了大概 10 秒+的延迟。

原因 2,CDN 缓存

考虑如下的 case,源站的 Playlist 中包含 3 个 Segment,在被客户端请求了一次后,被 CDN 缓存在节点中。


这样缓存机制的好处是,如果其他客户端发起请求,则直接从 CDN 节点返回即可,不需要再从源站请求。但也有坏处,考虑以下场景,源站此时新编码了一个 Segment4,2 号客户端发起请求发现命中了 CDN 的缓存,但 CDN 的缓存目前只有 3 个 Segment。故即便 2 号请求在 Segment4 生成之后发起,拿到的还是只有前三个 Segment。

思考

耗时点我们已经知道了,该如何优化呢?首先要确定几个基本原则

  1. 仍然需要坚持使用 HTTP
  2. 如果使用 HTTP,则意味着分段编码的延迟无法避免
    但是可以考虑更小的 Segment,比如 250ms 一个。
  3. 如果要规模化使用,CDN 也必须保留
    同理,cache 机制也必须保留
  4. 码率切换需要在 600ms 以内完成,而非 1 秒

基于以上思考,本次低延迟 HLS 主要带来了五大改进

五大改进

1. 降低发布延迟

新的 HLS 支持 Partial Segment 的概念,如图所示:

原本只有 1.ts完整编码完之后才能被客户端消费,而现在在完整的1.ts 准备好之前,会不断编码出 1.1.ts, 1.2.ts 等 Partial Segment 供客户端消费,极大程度降低了发布延迟

2. 优化发现机制

这里的发现机制指 CDN 对于源站新的 update 的发现机制。考虑一下场景,Client 1 请求 Playlist,CDN 从源站同步了1.1.ts 并返回

此时,Client 2 也发起请求,CDN 识别到 1.1.ts 已经存在,直接返回。

如果此时 Client 1 再次发起请求,URL 中会表示 Client 1 已经消费过1.1.ts 了,从而触发 CDN 回源,使得 Client 1 能够正确拿到1.2.ts

3. 消除多余的一次 RTT

这个很容易理解,之前的图中请求 Playlist 和 Segment 是分开的两次请求,而在新的 HLS 中,他们可以合并成一个。

top Created with Sketch.