WWDC Quick Look 💓 By SwiftGGTeam
Reduce latency with HLS Blocking Playlist Reload

Reduce latency with HLS Blocking Playlist Reload

观看原视频

Highlight

Apple 为 HLS playlist reload 增加 _HLS_msn_HLS_part delivery directive,让服务器等到目标 segment 或 partial segment 出现后再返回 playlist,从而减少直播播放器发现新内容的等待时间。


核心内容

直播播放器最怕错过一次 playlist 更新。传统 HLS 的做法很简单:客户端定期重新请求同一个 playlist URL。如果它刚好在更新前请求,拿到的还是旧 playlist,只能等下一个 target duration 再试一次。对普通直播,这只是多等几秒;对 Low-Latency HLS(低延迟 HLS),这几秒会直接吞掉低延迟的收益。

Blocking Playlist Reload 把轮询改成了带条件的等待。客户端不再问“现在有什么”,而是告诉服务器“等 playlist 包含我还没见过的下一个内容再回复”。服务器如果还没有目标内容,就保持请求打开;一旦新的 segment 或 partial segment 写进 playlist,就立刻返回新 playlist。

这个改变也解决了 HTTP cache 的老问题。传统 live playlist 总是同一个 URL,缓存要频繁过期,播放器还可能拿到旧响应。Blocking Playlist Reload 使用带查询参数的唯一 URL,例如 _HLS_msn=24,每一次 playlist 更新都能被缓存成独立对象。新的更新请求会穿透缓存到 origin,已经生成的响应又能在 CDN 边缘保留更久。


详细内容

声明服务器支持 blocking reload

01:27)Blocking Playlist Reload 是可选能力。服务器必须在 playlist 的 #EXT-X-SERVER-CONTROL 标签里声明 CAN-BLOCK-RELOAD=YES,客户端才会使用这种请求方式。

#EXTM3U
#EXT-X-TARGETDURATION:6
#EXT-X-SERVER-CONTROL:CAN-BLOCK-RELOAD=YES
#EXT-X-MEDIA-SEQUENCE:19
#EXTINF:6.0,
segmentA.ts
#EXTINF:6.0,
segmentB.ts
#EXTINF:6.0,
segmentC.ts
#EXTINF:6.0,
segmentD.ts
#EXTINF:6.0,
segmentE.ts

关键点:

  • #EXT-X-SERVER-CONTROL 放在 playlist 中,告诉客户端服务器支持额外的播放控制能力。
  • CAN-BLOCK-RELOAD=YES 是 blocking reload 的开关;没有它,客户端应该继续使用普通 reload。
  • #EXT-X-MEDIA-SEQUENCE:19 表示第一个 segment 的 Media Sequence Number 是 19。
  • playlist 中最后一个 segmentE.ts 对应 Media Sequence Number 23,所以下一次新 segment 应该是 24。

_HLS_msn 请求下一个完整 segment

02:44)普通 live playlist 没有 partial segment。客户端只需要用 _HLS_msn 指定自己想看到的下一个 Media Sequence Number。服务器收到请求后,如果 MSN 24 还没写入 playlist,就阻塞这个 HTTP 请求;更新完成后返回新版 playlist。

_HLS_msn=24
#EXTM3U
#EXT-X-TARGETDURATION:6
#EXT-X-SERVER-CONTROL:CAN-BLOCK-RELOAD=YES
#EXT-X-MEDIA-SEQUENCE:20
#EXTINF:6.0,
segmentB.ts
#EXTINF:6.0,
segmentC.ts
#EXTINF:6.0,
segmentD.ts
#EXTINF:6.0,
segmentE.ts
#EXTINF:6.0,
segmentF.ts

关键点:

  • _HLS_msn=24 表示客户端要等待包含 Media Sequence Number 24 的 playlist。
  • 请求 URL 与普通 playlist URL 不同,CDN 可以把这一版 playlist 当成独立缓存对象。
  • 返回结果中 #EXT-X-MEDIA-SEQUENCE 前进到 20,窗口移除了 segmentA.ts
  • 新增的 segmentF 对应 MSN 24,正是客户端等待的下一段内容。

_HLS_part 请求下一个 partial segment

03:57)Low-Latency HLS 会把一个 segment 拆成多个 partial segment。客户端除了 _HLS_msn,还要用 _HLS_part 指明目标 partial segment 的编号。演讲里的例子是 segment 7 已经有 part 0 和 part 1,所以下一次请求目标是 segment 7 part 2。

_HLS_msn=7
_HLS_part=2
当前 playlist 末尾:segment 7 part 0、segment 7 part 1
下一次 blocking reload 目标:segment 7 part 2

关键点:

  • partial segment 的目标时长是 2 秒,这是演讲示例中的 part target duration。
  • _HLS_msn=7 锁定父 segment 的 Media Sequence Number。
  • _HLS_part=2 请求该 segment 的第三个 partial segment。
  • 服务器等到 segment 7 part 2 出现在 playlist 后再返回,播放器不需要用固定间隔反复探测。

请求越过 segment 末尾时的处理

04:47)客户端可能请求一个超出当前 segment 末尾的 part,例如 segment 7 part 3。服务器会把这种请求转换成下一个 segment 的 part 0。这样客户端只要按顺序递增 part 编号,不必提前知道每个 segment 最终会包含多少个 part。

客户端请求:segment 7 part 3
服务器解释:segment 8 part 0
如果请求的 part 越过 parent segment 末尾,
服务器会把它转换为下一个 segment 的 part 0。

关键点:

  • _HLS_part=3 超出了 6 秒 segment 与 2 秒 part 的组合范围。
  • 服务器把它解释为下一个 segment 的 part 0。
  • 下一个 segment 的 part 0 出现在 playlist 后,请求就可以返回。
  • 客户端逻辑保持线性:看到哪个 MSN 和 part,就请求下一个 MSN 和 part。

缓存与超时规则

05:22)delivery directive 只适用于 live playlist。带 #EXT-X-ENDLIST 的 playlist 会忽略这些参数。服务器已经拥有客户端请求的版本时,必须立即返回当前 playlist;如果请求的 segment 已经滚出窗口,也立即返回当前 playlist。只有等待超过三个 target duration 时,服务器才返回错误。

_HLS_msn=23  -> playlist update 23 的独立缓存对象
_HLS_msn=24  -> playlist update 24 的独立缓存对象
_HLS_msn=7 + _HLS_part=2 -> segment 7 part 2 的独立缓存对象

关键点:

  • 每组 delivery directive 对应不同 playlist update,缓存不需要用同一个 live playlist 对象互相覆盖。
  • 新请求带着 CDN 没见过的参数组合,会继续发送到 origin。
  • 成功的 playlist 响应可以按演讲建议缓存六个 target duration
  • CDN 应配置 duplicate edge request coalescing,把相同边缘请求合并成一次 origin 请求,降低源站压力。

核心启发

  • 直播播放器的 reload 诊断面板

    • 做什么:在内部播放器里显示当前 MSN、part、下一次 _HLS_msn / _HLS_part 请求和等待耗时。
    • 为什么值得做:这个 session 的核心问题是播放器发现新内容的时间;把等待时间可视化,才能判断延迟来自编码、origin、CDN 还是客户端请求策略。
    • 怎么开始:记录每次 playlist 请求 URL、响应时间、返回 playlist 的最后一个 MSN 和 part,按播放会话绘制时间线。
  • Low-Latency HLS origin 的 blocking 请求监控

    • 做什么:为 origin 增加 blocking reload 并发数、平均阻塞时长、三倍 target duration 超时数等指标。
    • 为什么值得做:服务器会保持 HTTP 请求直到 playlist 更新,容量瓶颈从短请求吞吐变成并发等待连接。
    • 怎么开始:在处理 _HLS_msn_HLS_part 的入口打点,按 playlist path 和 CDN POP 聚合延迟与错误率。
  • CDN 缓存命中实验

    • 做什么:比较普通 live playlist URL 与带 delivery directive URL 的缓存命中、回源和响应复用情况。
    • 为什么值得做:演讲强调每个 playlist update 有唯一 URL 后,成功响应能在缓存中保留更久。
    • 怎么开始:为 _HLS_msn_HLS_part 组合输出缓存标识,开启 duplicate edge request coalescing,再观察 origin 请求数是否下降。
  • 直播窗口异常恢复测试器

    • 做什么:模拟客户端请求过旧 MSN、请求超前 part、请求已结束 playlist 等边界条件。
    • 为什么值得做:session 给出了这些例外规则;提前测试可以避免播放器卡在等待状态。
    • 怎么开始:用脚本生成不同 query parameter,请求 staging playlist,验证服务器是否按规则立即返回当前 playlist,或在超时后返回错误。

关联 Session

评论

GitHub Issues · utterances