Highlight
Apple 为 HLS playlist reload 增加
_HLS_msn和_HLS_partdelivery 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,按播放会话绘制时间线。
- 做什么:在内部播放器里显示当前 MSN、part、下一次
-
Low-Latency HLS origin 的 blocking 请求监控
- 做什么:为 origin 增加 blocking reload 并发数、平均阻塞时长、三倍
target duration超时数等指标。 - 为什么值得做:服务器会保持 HTTP 请求直到 playlist 更新,容量瓶颈从短请求吞吐变成并发等待连接。
- 怎么开始:在处理
_HLS_msn和_HLS_part的入口打点,按 playlist path 和 CDN POP 聚合延迟与错误率。
- 做什么:为 origin 增加 blocking reload 并发数、平均阻塞时长、三倍
-
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
- What’s new in Low-Latency HLS — Low-Latency HLS 的总览,先理解 partial segment 和两秒级直播延迟目标。
- Discover HLS Blocking Preload Hints — 继续看媒体数据本身如何通过 blocking preload hint 提前请求。
- Optimize live streams with HLS Playlist Delta Updates — 了解大型 live playlist 如何只传输变化部分,减少 reload 成本。
- Adapt ad insertion to Low-Latency HLS — 学习低延迟链路中广告插入如何保持切换和播放连续性。
- Improve stream authoring with HLS Tools — 用 HLS 工具检查打包结果,验证 playlist 与媒体切片是否符合预期。
评论
GitHub Issues · utterances