Discover HLS Blocking Preload Hints
Audio & Video 高级 20m

了解 HLS Blocking Preload Hints

Discover HLS Blocking Preload Hints

2020年6月25日

在 Apple 官方观看视频

一句话判断

如果你想理解 Low-Latency HLS 如何做到”服务器有数据就立即推给客户端”,Blocking Preload Hints 就是核心机制——它让播放器可以预请求还没准备好的分段。

这场 Session 讲了什么

这场 Session 深入剖析了 Low-Latency HLS 中 Blocking Preload Hints 的工作原理。在传统 HLS 中,播放器通过周期性轮询 playlist 来发现新的 segment,这种方式在直播场景下造成了大量不必要的延迟。Blocking Preload Hints 改变了这个模型。

核心思路是:服务器在 playlist 中通过 #EXT-X-PRELOAD-HINT 标签告诉播放器”即将有一个新的 partial segment 会在某个 URI 生成”。播放器可以立即向这个 URI 发起请求,服务器会保持这个连接打开(blocking),直到数据准备好再返回。这样播放器不需要轮询,新数据产生后立即就能获取。

演讲者详细讲解了 Preload Hints 的两种类型:PART(partial segment)和 MAP(初始化 segment)。通过一系列 playlist 示例展示了 Preload Hint 如何与 Blocking Playlist Reload 配合工作。Session 还讨论了客户端和服务端的实现考量,包括超时处理、连接管理,以及如何处理 Preload Hint 失败的情况。

值得深挖的点

  • Preload Hint 与 CDN 的协作:Preload Hints 本质上是一个 HTTP 请求,这意味着它需要通过 CDN。但 CDN 通常会缓存 404 响应,这在 Preload Hint 场景下是个问题——因为资源确实”暂时不存在”但很快就会生成。解决方案是 CDN 需要配置为不缓存 blocking 请求的失败响应,或者使用特殊的 HTTP 状态码(如 425 Too Early)来区分。
  • 连接管理策略:播放器可能同时有多个 blocking 请求在等待(比如同时等待下一个 partial segment 和下一个 playlist 更新)。如何高效管理这些长连接,避免连接池耗尽,是客户端实现的关键挑战。

代码片段

# Preload Hint 在 playlist 中的表现形式
# #EXTM3U
# #EXT-X-TARGETDURATION:6
# #EXT-X-PART-INF:PART-TARGET=1.0
# #EXT-X-SERVER-CONTROL:CAN-BLOCK-RELOAD=YES
#
# #EXT-X-PART:DURATION=1.0,URI="part0.mp4"
# #EXT-X-PART:DURATION=1.0,URI="part1.mp4"
# #EXT-X-PRELOAD-HINT:TYPE=PART,URI="part2.mp4"
#
# 播放器看到 PRELOAD-HINT 后立即请求 part2.mp4
# 服务端保持连接打开,数据就绪后返回
# 服务端实现 blocking 请求的伪代码
# 当收到对 partial segment 的请求时:
if segment_ready(requested_uri):
    return segment_data
else:
    # 阻塞等待,直到 segment 生成完成
    wait_for_segment(requested_uri, timeout=3.0)
    if segment_ready(requested_uri):
        return segment_data
    else:
        return HTTP_425_TOO_EARLY  # 数据还没准备好
// AVPlayer 自动处理 Preload Hints
// 只需确保 playlist 包含正确的标签即可
// 无需额外配置,AVPlayer 会自动:
// 1. 解析 #EXT-X-PRELOAD-HINT 标签
// 2. 发起 blocking 请求
// 3. 数据就绪后立即开始解码

let url = URL(string: "https://example.com/live/master.m3u8")!
let asset = AVURLAsset(url: url)
let playerItem = AVPlayerItem(asset: asset)
let player = AVPlayer(playerItem: playerItem)
player.play()

最佳实践

  • 服务端 Preload Hint 的 URI 必须与实际生成的 partial segment URI 完全匹配,任何不一致都会导致播放器请求失败
  • Blocking 请求的超时时间建议设为 partial segment duration 的 2-3 倍
  • CDN 配置时,blocking 请求不应当被缓存,或者设置极短的 TTL
  • 监控服务端的 blocking 请求并发量,做好容量规划——每个活跃播放器至少占用一个长连接
  • 优雅降级:如果客户端不支持 Blocking Preload Hints,应回退到普通轮询模式

还有什么值得关注

  • 这场 Session 是 Low-Latency HLS 系列的深度技术讲解之一,建议搭配 “What’s new in Low-Latency HLS” 总览篇一起看
  • Preload Hints 的规范细节在 Apple 的 HLS Authoring Specification 中有完整定义
  • 如果你在做多码率(ABR)场景,Preload Hints 对码率切换的响应速度也有直接影响
WWDC 2020