第 6 章 · 自适应码率 ABR
为什么能自动换清晰度

播放器如何在 4G/5G/WiFi 之间无缝切换画质?五种经典 ABR 算法详解。

本章你会理解:ABR 是什么、播放器用哪些策略切换清晰度、BOLA/MPC/Pensieve 算法的核心思想、工程上该怎么选。

预计阅读时间:20 分钟
• • •

1 6.1 生活场景:为什么它很重要

假设你在地铁上看剧,网络在 4G / 弱 4G / 5G 之间频繁切换。

- 如果 APP 锁定 1080p 不变 → 网差时会卡到转圈圈
- 如果 APP 锁定 360p 不变 → 网好时画面糊得心疼

理想状态:APP 能自己根据网速和缓冲情况切换清晰度,让你不间断看完。

这就是 ABR(Adaptive Bitrate)自适应码率 要做的事。

• • •

2 6.2 ABR 的工作循环

每下载一个切片后,播放器都会问自己:

┌──────────────────────────┐
│  上一个切片下得怎么样?    │
│  现在缓冲区还剩多少秒?    │
│  网速估得怎么样?          │
│  设备还扛得住当前档吗?    │
└──────────────────────────┘
             │
             ▼
       ┌──────────┐
       │ 算出下一档│
       └──────────┘
             │
             ▼
     下载下一个切片

这个循环每 1-4 秒跑一次(每下完一片触发)。

关键信号

- 最近吞吐量(Throughput):最近几片的实际下载速度
- 缓冲占用(Buffer Level):播放器已缓存但还没播的秒数
- 当前码率(Current Bitrate)
- 可选码率集合(Manifest 列出的 bitrate ladder)

• • •

3 6.3 策略一:基于吞吐(Throughput-Based)

最直觉的做法

估计网速 = 最近 N 个切片的平均下载速度
下一档码率 ≈ 估计网速 × 0.8   (留 20% 余量)

示例

- 最近下载速度 5 Mbps
- × 0.8 = 4 Mbps
- 在 360p(0.5) / 720p(2.5) / 1080p(5) / 4K(15) 中选 ≤ 4 Mbps 的最高档 → 720p

维度 分析
优点 简单直观,实现成本低
缺点 HTTP/TCP 层测速噪声大(慢启动、队头阻塞、TLS 握手…);频繁切换,画面一会儿清一会儿糊
代表实现 早期 hls.js 的 bandwidthFraction 策略
• • •

4 6.4 策略二:基于缓冲(Buffer-Based,BBA)

另一种思路:不管网速,只看缓冲区还有多少秒

核心规则

缓冲 < 10s  → 下最低档(稳住不卡)
缓冲 10-30s → 下中档
缓冲 > 30s  → 下最高档(反正你够看,多享受)

画成曲线

码率档位
  ▲
最高│                    ┌────────
    │                   ╱
中档│              ┌───╱
    │             ╱
最低│────────────┘
    └─────────────────────────► 缓冲秒数
    0   10s      30s      60s

代表方案:BBA(Buffer-Based Adaptation),Huang 等人在 Stanford / Netflix 2014 年 SIGCOMM 论文 A Buffer-Based Approach to Rate Adaptation 提出。

维度 分析
优点 对网速噪声免疫(不看网速);稳定,不频繁切换
缺点 启动阶段缓冲不足时很激进地降档;没充分利用带宽(网好时可能选档偏低)
• • •

5 6.5 策略三:BOLA(基于 Lyapunov 优化)

BOLA = Buffer Occupancy based Lyapunov Algorithm

- 作者:Spiteri、Urgaonkar、Sitaraman
- 2016 年 INFOCOM 论文 BOLA: Near-Optimal Bitrate Adaptation for Online Videos
- dash.js 默认算法之一

核心思想

BOLA 把 ABR 建模为多目标优化问题

最大化:平均画质 - V × (卡顿惩罚 + 切换惩罚)
V 是权衡系数:
- V 大 → 偏保守,优先防卡
- V 小 → 偏激进,优先画质

然后用 Lyapunov 优化理论 证明:只看当前缓冲就能做出近最优决策

简化伪代码

def bola_select_bitrate(buffer_level, bitrates, V):
    best_bitrate = None
    best_score = -inf

    for r in bitrates:
        # 效用函数 = log(码率)(边际递减)
        utility = log(r)
        # 奖励 = 当前缓冲 × 效用
        score = buffer_level * utility - V * r
        if score > best_score:
            best_score = score
            best_bitrate = r

    return best_bitrate

好处

- 理论可证接近最优
- 仅看缓冲,无需精确测网速
- 已在 dash.js 生产环境跑了 10+ 年

实际细节

dash.js 把 BOLA 和 ThroughputRule 动态组合

- 缓冲很低(启动时):用 ThroughputRule
- 缓冲充足:用 BOLA

• • •

6 6.6 策略四:MPC(模型预测控制)

MPC(Model Predictive Control)

- 作者:Yin, Jindal, Sekar, Sinopoli
- 2015 年 SIGCOMM 论文 A Control-Theoretic Approach for Dynamic Adaptive Video Streaming over HTTP

思想

与其"只看当下决定",不如预测未来几秒的网速联合优化未来 K 个切片的选择:

现在在第 n 个切片。
假设未来 5 个切片(到第 n+5)网速会是 T1, T2, T3, T4, T5。
试所有码率组合,选一个让:
  (总画质 - 卡顿惩罚 - 切换惩罚) 最大

预测网速

常用做法:

- Harmonic Mean(调和平均):1 / mean(1/throughput_i) —— 比算术平均对慢样本更敏感
- EWMA(指数加权移动平均)

优缺点

- 比 BOLA 更智能(看未来)
- 计算量稍大
- 网速预测不准时容易翻车

• • •

7 6.7 策略五:Pensieve(AI 学习型 ABR)

Pensieve

- 作者:Mao, Netravali, Alizadeh (MIT)
- 2017 年 SIGCOMM Neural Adaptive Video Streaming with Pensieve

思想

用强化学习(A3C 算法)训练神经网络做 ABR 决策

维度 内容
输入特征 过去 K 秒吞吐量、当前缓冲、上一个码率、剩余切片数量、Manifest 里各档码率
输出 下一个切片的码率选择
训练 在海量真实/模拟网络轨迹上跑仿真,神经网络自己学出最优策略

效果

在特定测试集上超越 BOLA 和 MPC。但——

局限性

- 泛化性:训练时没见过的网络模式下表现不一定好
- 可解释性差:出问题不好调
- 需要持续 online fine-tune

工业界在用 Pensieve 吗?

- 头部公司(Netflix、YouTube)自研了类似的学习型 ABR
- 中小平台用 BOLA 或 MPC 已经足够

• • •

8 6.8 实际工业界是怎么做的?

Netflix

- 客户端侧用类似 BBA 的策略
- 服务端给 hint(例如"当前 CDN 负载高,建议你降档")
- 结合 VMAF 决定 bitrate ladder

YouTube

- 自研,结合"用户观看时长预测"做联合优化
- 复杂的 A/B 测试体系

普通平台

- 直接用开源播放器(hls.js、Shaka Player、ExoPlayer)自带的 ABR
- 参数调优:maxBufferLength、bandwidthFraction、码率档位设置

实际建议:Netflix/YouTube 有自研 AI ABR。其他平台用开源播放器自带的 BOLA/MPC + 参数调优就够了
• • •

9 6.9 短视频/短剧场景的特殊考虑

和长视频不同,短剧/短视频场景 ABR 需求变了:

特殊点

- 首帧时间(TTFF)最重要 ——用户滑动 300ms 没画面就走了
- 单集短:完播 90 秒,ABR 可能还没来得及向上切就结束了
- 预载多集:可能同时下载 N+1、N+2 的切片

常见调整

- 启动档位更低(保证快速起播)
- 向上切换更慢(防止刚起播就变清导致下载卡顿)
- 预载时下低档(省流量)
- 正在播放的下高档(画质优先)

• • •

10 6.10 ABR 常见问题与工程建议

为什么会"看着看着突然变糊"?

大概率是:

1. 网速实测下降(4G 转弱信号、家里路由器切换了信道)
2. CDN 边缘节点出问题(换到另一个节点时慢)
3. 设备热控(手机过热,降频导致解码跟不上)

为什么会"一直糊、明明网很好"?

- 启动策略太保守
- 测速累计样本还是慢的
- Manifest 里没有高档位(转码时没生成 1080p)

为什么频繁切换清晰度、看得眼花?

- 码率档位设得太密(每档差距小)
- 算法对吞吐噪声敏感(用 Throughput-based 但没滤波)
- 解决:码率档位间距拉大到 1.5x 左右加切换惩罚(switching penalty)用 BOLA 替代 Throughput-based

工程上 ABR 最重要的配置是什么?

不是算法,是 bitrate ladder(码率阶梯)!

一个不合理的阶梯,再好的算法也救不了。推荐阶梯设计原则:
- 相邻档位码率比 1.5x-2x(差太小切换无意义、差太大切换突兀)
- 最低档足够低(能覆盖 2G/弱 3G 用户)
- 最高档不浪费(1080p 用 8 Mbps 跟 5 Mbps 肉眼差别不大)

Per-title encoding 就是要给每部片子定制最优 ladder。

典型码率阶梯示例

档位 分辨率 H.264 码率 H.265 码率
1 360p 400 kbps 250 kbps
2 480p 800 kbps 500 kbps
3 720p 2.0 Mbps 1.2 Mbps
4 1080p 4.5 Mbps 2.8 Mbps
5 4K 15 Mbps 9 Mbps
• • •

11 6.11 动手:观察一个 ABR 决策过程

动手试一试:在 Chrome 里用 hls.js 播放时观察 ABR。

1. 打开 https://hls-js.netlify.app/demo/
2. 粘贴一个 m3u8 URL(或用默认的 Apple 测试流)
3. 按 F12 打开 DevTools → Network 面板
4. 播放,你能看到每个 .m4s / .ts 切片的下载时间、大小
5. Network 面板打开 Throttling 选成 "Slow 3G",观察 hls.js 自动降档

hls.js Stats 面板会显示:

- bandwidthEstimate:当前带宽估计
- level:当前档位 index
- nextAutoLevel:下一个切片会用哪档

• • •

五种 ABR 算法对比总览

算法 核心依据 优势 劣势 代表
Throughput 网速 简单直观 噪声大、频繁切换 早期 hls.js
BBA 缓冲区 稳定、抗噪声 启动慢、利用率低 Netflix 客户端
BOLA 缓冲+优化 理论最优、生产可用 需与 Throughput 组合 dash.js 默认
MPC 预测未来 前瞻性强 预测不准就翻车 学术论文
Pensieve AI 学习 特定场景超越其他 泛化差、不可解释 Netflix/YouTube 自研
• • •

本章要点回顾

1. ABR = 自适应码率,每下一片后决定下一片下哪档。

2. 五类经典策略:
    - Throughput-based:看网速,简单但噪声敏感
    - Buffer-based (BBA):看缓冲,稳但偏保守
    - BOLA:基于 Lyapunov,理论最优,生产可用
    - MPC:预测未来,更智能
    - Pensieve:强化学习,头部公司自研类似方案

3. 工程上,ABR 算法不是最重要的,bitrate ladder 设置才是。

4. 短剧/短视频场景 ABR 要配合预载和 TTFF 优化。

5. 档位间距 1.5-2x、足够低的最低档、合理的最高档是黄金三条。
• • •
← 上一章:流媒体协议 目录 下一章:CDN 分发 →
© 2026 Zmead · VOD 流媒体技术全解