7.4.4 自适应码率:客户端的切换艺术(Adaptive Bitrate Switching)
前两节把 HLS 的骨架与分片讲透了,但主索引里那行 #EXT-X-STREAM-INF 的属性只认了脸,没算账。BANDWIDTH、CODECS、RESOLUTION——这些字段是客户端选档的全部依据。本节逐个拆开,最后回答那个规范故意不答的问题:客户端到底怎么决定切哪一档。
BANDWIDTH:峰值口径的精打细算
BANDWIDTH 是 EXT-X-STREAM-INF 上唯一的 必填 属性,语义为变体流的 峰值分片码率 [8]。这个 "峰值" 二字背后有一套精确口径:
- 分片码率 = 分片字节数 ÷ EXTINF 时长——含容器开销,不含 HTTP/TCP/IP 等传输开销 [8]
- 峰值分片码率 = 在总时长介于 0.5~1.5 倍 TARGETDURATION 的任意连续分片组里,(总字节 ÷ 总时长)的最大值 [8]
- 多 Rendition 组合时(视频流加独立音轨),取所有可播放组合的峰值之和的最大者
- 内容尚未编码完就要发布主索引(直播常态),则 应当 填同设置、相似内容的代表值 [8]
为什么非峰值不可?VBR 编码的码流天然有波峰——场景切换、剧烈运动,瞬时码率数倍于均值。客户端若按平均码率选档,一到波峰段下载就会跟不上消耗,缓冲被抽干。规范把话说得很重:不准确的 BANDWIDTH 会导致卡顿甚至无法播放 [8]。附带的 AVERAGE-BANDWIDTH 则是可选的平均口径,供需要精细预估的客户端参考。以 7.6 实战那条流为例:BANDWIDTH=56675,即峰值约 56.7 kbps——CIF 分辨率低码率演示流的真实体量。
CODECS 与其余属性:先问能不能播
选档之前还有一道更靠前的闸门:这台设备到底能不能解码?CODECS 属性按 RFC 6381 定义的 ISO BMFF 命名空间书写,引号内逗号分隔——规范的示例 "mp4a.40.2,avc1.4d401e" 读作 AAC-LC 音频加 H.264 Main Profile Level 3.0 视频 [8]。avc1 后缀的三段十六进制依次是 profile、compatibility、level,客户端据此比对自身解码能力,不支持就直接跳过这档。规范说 SHOULD 携带,工程上几乎是事实必填。
其余属性各司其职:RESOLUTION 声明最佳显示分辨率(含视频时建议携带);FRAME-RATE 取流中最大帧率、保留三位小数,超过 30 fps 时 SHOULD 明示 [8]——高帧率档位对解码性能的要求陡增,提前声明免得客户端误入。
切换决策:规范留白处的战场
属性给齐了,怎么决策?翻遍 RFC 8216 找不到答案——规范定义数据,不定义算法,这是刻意的留白。工业界的通行打法可以归纳为两条信号的合谋:
- 带宽估计:用最近几个分片的实际下载速率估算可用带宽,选一个峰值不超过估值(再留安全余量)的最高档
- 缓冲水位:缓冲区持续缩水说明估计过于乐观,降档避险;水位充裕且带宽上行,升档尝鲜
切换的动作只能发生在 分片边界 上,切换粒度就是一个分片时长——分片越短,跟随网络波动的灵敏度越高,这又是 7.4.5 缩短分片的另一条动机。而切换能否无缝,取决于新档的分片能否独立解码起播:主索引里的 EXT-X-INDEPENDENT-SEGMENTS 标签(上一节实测列表中就有)宣告 每个分片都能独立解码 [8],换档时直接接续,无需等待关键帧——第六章 GOP 的概念,在这里变成了可声明、可消费的清单属性。
小结
ABR 的账算清了:BANDWIDTH 用峰值口径兜住 VBR 的波峰,CODECS 把 "能不能播" 前置到选档之前,切换算法则在规范的留白里各显神通。至此,HLS 的 "看得流畅" 已经闭环;悬而未决的只剩那个与生俱来的账单——延迟。分片粒度、列表周期、播放缓冲三座大山压在那里,业界用了十年时间与它们缠斗。下一节,延迟之战与 LL-HLS。