What's new in Low-Latency HLS
Audio & Video 进阶 25m

Low-Latency HLS 新特性

What's new in Low-Latency HLS

2020年6月24日

在 Apple 官方观看视频

一句话判断

如果你在构建直播系统,这场 Session 汇总了 Low-Latency HLS 在 2020 年的全部更新——从 Partial Segments 到 Blocking Playlist Reload,一套组合拳将端到端延迟压到 3 秒以内。

这场 Session 讲了什么

这场 Session 是 WWDC 2020 关于 Low-Latency HLS 的总览性演讲。Apple 在 2019 年提出了 Low-Latency HLS 的概念,2020 年则是将这些规范落地为可用技术的关键一年。演讲者从传统 HLS 的延迟问题讲起——标准 HLS 的端到端延迟通常在 15-30 秒,主要因为播放器需要下载完整的 segment(通常 6 秒)才能开始播放。

Low-Latency HLS 的核心思路是将完整的 segment 进一步拆分为更小的 partial segment(通常 0.5-1 秒),播放器可以在 partial segment 级别就开始解码播放,而不必等待完整 segment。配合 Blocking Playlist Reload 和 Preload Hints 两个机制,播放器可以在服务器有新数据时立即获取,而不是轮询等待。

Session 还介绍了 Low-Latency HLS 对 CDN 的友好设计。通过 Delta Playlist Updates,服务器只需要发送 playlist 的增量变化,而不是完整的 playlist 文件,这大幅减少了 CDN 的带宽消耗。广告插入(Ad Insertion)也有了新的方案,在低延迟场景下实现更无缝的广告切换。

值得深挖的点

  • 端到端延迟的组成部分:延迟不只是播放器的问题——从编码器到 CDN 到客户端,每一环都在加延迟。Apple 给出的目标是 encoder delay + segment duration + CDN propagation + client buffer < 3 秒。这意味着你需要从整个链路角度去优化,不能只盯着播放器端。
  • CDN 兼容性的现实:Low-Latency HLS 的很多新特性(如 Blocking Playlist Reload)依赖 CDN 支持 HTTP/2 的长连接和推送。如果你的 CDN 不支持这些特性,一些优化效果会打折扣。选择 CDN 时需要特别关注其对 Low-Latency HLS 的支持程度。

代码片段

# Low-Latency HLS Playlist 示例
# #EXTM3U
# #EXT-X-TARGETDURATION:6
# #EXT-X-PART-INF:PART-TARGET=1.0
# #EXT-X-SERVER-CONTROL:CAN-BLOCK-RELOAD=YES,PART-HOLD-BACK=3.0
#
# #EXT-X-PART:DURATION=1.0,URI="segment1_part0.mp4"
# #EXT-X-PART:DURATION=1.0,URI="segment1_part1.mp4"
# #EXT-X-PART:DURATION=0.75,URI="segment1_part2.mp4"
# #EXTINF:6.0,
# segment1.mp4
# 使用 mediastreamsegmenter 生成 Low-Latency HLS 流
mediastreamsegmenter \
  --segment-duration 6 \
  --partial-segment-duration 1 \
  --delete-ext-old-clips 30 \
  --output-directory /hls/live/ \
  --master-playlist-name master.m3u8 \
  --file /dev/stdin
// 使用 AVPlayer 播放 Low-Latency HLS 流
import AVFoundation

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

// 配置低延迟播放偏好
playerItem.preferredForwardBufferDuration = 1.0

let player = AVPlayer(playerItem: playerItem)
player.play()

// 监听延迟指标
player.addPeriodicTimeObserver(
    forInterval: CMTime(seconds: 1, preferredTimescale: 1),
    queue: .main
) { time in
    // 计算当前延迟
    if let currentDate = playerItem.currentDate() {
        let latency = Date().timeIntervalSince(currentDate)
        print("当前延迟: \(latency) 秒")
    }
}

最佳实践

  • Partial segment duration 设为 1 秒是延迟和性能的最佳平衡点,不要为了追求更低延迟而设得太小
  • PART-HOLD-BACK 至少设为 partial segment duration 的 3 倍,确保播放器有足够的缓冲
  • 直播场景下优先使用 fMP4 容器而非 MPEG-TS,前者支持更精确的 partial segment 切分
  • 部署前用 mediastreamvalidator 全面验证流的合规性,特别是 Low-Latency 特有的标签
  • CDN 缓存策略需要为 partial segment 设置更短的 TTL,避免播放器拿到过期数据

还有什么值得关注

  • Low-Latency HLS 的规范已经提交为 RFC 草案,正在走向标准化
  • 这一系列还有三场深度 Session:Blocking Preload Hints、Playlist Delta Updates、Blocking Playlist Reload
  • 搭配 “Improve stream authoring with HLS Tools” 一起看,可以掌握完整的 Low-Latency HLS 工具链
WWDC 2020