视频分片技术全解:从上传到播放的全链路架构

为什么视频处理的每一步都在「分片」

一个 4K 60fps 的 10 分钟视频,原始文件可以轻松超过 20GB。把这样的文件当作一个整体来传输、处理、分发,几乎在每个环节都会遇到硬性瓶颈:

  • 上传:单个 HTTP 连接传 20GB,任何一次网络抖动都意味着从头再来
  • 转码:单机串行处理一个 20GB 文件,可能要跑几个小时
  • 分发:CDN 缓存一个 20GB 的完整文件,缓存命中率极低,回源成本爆炸
  • 播放:用户必须等待整个文件下载完才能开始观看,首帧时间以分钟计

分片的本质就是 把一个不可控的大问题拆成若干个可控的小问题。这个思路贯穿了视频处理的全链路:

环节 分片对象 典型分片大小 核心收益
上传 原始文件 2MB - 10MB 断点续传、并发加速
转码 GOP 组 2s - 10s 片段 分布式并行、弹性扩缩
封装 媒体流 2s - 10s segment 流式传输、即时播放
CDN HLS/DASH segment 2s - 6s 边缘缓存、按需回源
播放 码率变体 逐片请求 自适应码率、Seek 定位

下面我们沿着视频数据流的方向,从上传到播放,逐环节拆解每种分片的策略和工程实现。

视频分片全链路 Pipeline

上传分片:断点续传与秒传

为什么不能直接上传

用户在抖音发一个 3 分钟的 1080p 视频,大约 500MB。在 4G 网络下,上行带宽通常只有 5-10Mbps,完成上传需要 7-14 分钟。这期间用户可能切换 WiFi、进电梯、接电话——任何中断都会导致上传失败。

分片上传解决的核心问题:把一次不可靠的长连接,变成多次可重试的短连接

分片上传的基本流程

上传分片流程

整个流程拆解如下:

  1. 客户端切片:将文件按固定大小(通常 2-5MB)切割为多个 chunk
  2. 计算指纹:对每个 chunk 计算 MD5,对整个文件计算 SHA-256
  3. 并发上传:同时开 3-6 个连接并行上传不同的 chunk
  4. 服务端校验:每个 chunk 到达后立即校验 MD5,不匹配则要求重传
  5. 合并写入:所有 chunk 到齐后按序合并,校验整体 SHA-256
  6. 写入对象存储:合并后的完整文件写入 S3/OSS/COS

TUS 协议:断点续传的标准方案

TUS(可恢复上传协议)是目前最被广泛采用的断点续传开放标准,Vimeo 是其主要推动者。核心思路非常简洁:

# 1. 创建上传资源
POST /files HTTP/1.1
Upload-Length: 524288000
Tus-Resumable: 1.0.0

# 响应返回资源地址
HTTP/1.1 201 Created
Location: /files/abc123

# 2. 上传分片(带 offset)
PATCH /files/abc123 HTTP/1.1
Upload-Offset: 0
Content-Type: application/offset+octet-stream
Content-Length: 5242880

[chunk data...]

# 3. 查询上传进度(断点续传的关键)
HEAD /files/abc123 HTTP/1.1

HTTP/1.1 200 OK
Upload-Offset: 15728640   # 已上传的字节数
Upload-Length: 524288000

TUS 相比自研协议的优势在于:客户端 SDK 覆盖全平台(iOS / Android / Web / Flutter),服务端有 tusd 开源参考实现,协议本身通过扩展机制支持并发上传、校验和、过期清理等功能。

秒传:文件级去重

秒传的本质是 内容寻址——上传前先算文件整体的 SHA-256 hash,发给服务端查询。如果存储中已有相同 hash 的文件,直接建立引用关系,跳过实际数据传输。

// 客户端伪代码
async function uploadWithDedup(file) {
  const hash = await computeSHA256(file);

  // 1. 先查是否已存在
  const { exists, fileId } = await api.checkHash(hash);
  if (exists) {
    // 秒传:直接关联,0 字节传输
    return api.linkFile(fileId, file.name);
  }

  // 2. 不存在,走正常分片上传
  return chunkedUpload(file, hash);
}

抖音和 Bilibili 的视频秒传命中率实际并不高(用户上传的视频重复率远低于文件分享场景),但在企业内部视频平台、教育平台等场景下,秒传可以节省 30%-50% 的上传流量。

分片大小的选择

分片大小不是拍脑袋定的,需要平衡多个因素:

分片大小 优势 劣势 适用场景
1MB 重传代价小,弱网友好 HTTP 请求数多,overhead 大 移动端弱网
2-5MB 平衡点 - 通用场景
10MB 吞吐效率高,请求数少 重传代价大 局域网/高速网络
动态分片 自适应网络状况 实现复杂 高级客户端

实际工程中比较推荐的做法是 动态分片:初始 chunk 设为 2MB,根据前几个 chunk 的上传速度动态调整——上传快就增大到 5-8MB 减少请求数,上传慢就缩小到 1MB 降低重传成本。七牛云和阿里云 OSS 的 SDK 都实现了类似策略。

一句话总结:上传分片把一次赌博式的长传输变成了多次确定性的短传输,配合 TUS 协议和秒传机制,在弱网和大文件场景下提供了可靠的用户体验。

视频编码基础:理解 GOP 是理解后续一切的前提

要理解转码分片和流媒体分片,必须先搞清楚视频编码的基本结构。这里只讲和分片直接相关的部分。

I 帧、P 帧、B 帧

视频编码的核心思想是 去除时间冗余——相邻帧之间大部分内容是相同的,只需要编码差异部分:

  • I 帧 (Intra-coded):关键帧,包含完整画面信息,可以独立解码。相当于一张完整的 JPEG
  • P 帧 (Predicted):只存储与前一个参考帧的差异,需要依赖前面的 I 帧或 P 帧才能解码
  • B 帧 (Bi-directional):双向预测帧,同时参考前后两个帧的差异,压缩率最高但解码复杂度也最高

典型的帧大小比例:I 帧约 100KB,P 帧约 30KB,B 帧约 15KB(以 1080p H.264 为例)。

GOP:分片的天然边界

GOP(Group of Pictures)就是从一个 I 帧开始到下一个 I 帧之前的所有帧组成的序列。一个典型的 GOP 结构:

I B B P B B P B B P B B P B B I B B P ...
|<------------ GOP (通常 2-10s) ---------->|

GOP 是视频分片的 天然切割点,原因很简单:

  1. 每个 GOP 以 I 帧开头,可以独立解码,不依赖前面的 GOP
  2. 在 GOP 边界切割不会破坏帧间依赖关系
  3. 如果在 GOP 中间切割,切割点后的 P/B 帧会因为丢失参考帧而无法解码

这就是为什么 HLS/DASH 的 segment 长度通常是 GOP 长度的整数倍——不是巧合,而是编码结构的硬性约束。

编码器选型

编码器 标准 压缩效率 编码速度 硬件加速 适用场景
x264 H.264/AVC 基准线 NVENC/QSV/AMF 兼容性优先,移动端
x265 H.265/HEVC +30-40% 慢 3-5x NVENC/QSV 4K 内容,带宽敏感
libsvtav1 AV1 +40-50% 慢 5-10x 有限 长尾内容,无版权费
libvpx-vp9 VP9 +30% 慢 3x 有限 YouTube 生态

目前的行业现状:YouTube 已经全面拥抱 AV1(2024 年起新上传视频默认 AV1 编码),Netflix 在中低码率场景大量使用 AV1,Bilibili 主力仍是 H.264 + H.265 组合。编码器选型的核心权衡是 压缩效率 vs 编码成本 vs 终端兼容性

一句话总结:GOP 是视频编码中帧间依赖的基本单元,所有后续的分片操作——转码切割、HLS segment、播放器 Seek——都必须对齐到 GOP 边界。

转码分片:用并行把小时级任务压到分钟级

为什么转码是最耗资源的环节

一个 10 分钟的 4K H.264 视频,用 x264 以 medium preset 转码为 1080p,单核 CPU 大约需要 30-40 分钟。如果要输出 4 个码率档位(1080p/720p/480p/360p),串行处理就是 2 小时起步。

用户上传视频后等 2 小时才能发布?这在任何内容平台都是不可接受的。

分片并行转码流程

转码分片 Pipeline

核心步骤:

  1. GOP 边界分析:用 ffprobe 扫描源文件,找到所有 IDR(Instantaneous Decoder Refresh)帧的位置
  2. 分片切割:在 IDR 帧位置切割源文件,每个分片包含完整的若干个 GOP
  3. 分布式转码:每个分片独立发到转码集群的不同节点并行处理
  4. 多码率输出:每个节点同时输出多个码率档位
  5. 合并:转码完成后按顺序合并各分片的输出
# Step 1: 获取所有关键帧位置
ffprobe -select_streams v -show_entries frame=pkt_pts_time,key_frame \
  -of csv=p=0 input.mp4 | grep ",1$" | cut -d',' -f1

# Step 2: 在关键帧位置切割(假设每 30s 一个分片)
ffmpeg -i input.mp4 -c copy -f segment \
  -segment_times 30,60,90,120 \
  -reset_timestamps 1 \
  segment_%03d.mp4

# Step 3: 并行转码每个分片(实际中用任务队列调度)
ffmpeg -i segment_001.mp4 \
  -map 0:v -map 0:a \
  -c:v libx264 -preset medium -crf 23 \
  -s 1920x1080 -b:v 8M \
  output_001_1080p.mp4

转码调度:从 FFmpeg 到分布式集群

小规模场景下,一台多核服务器跑多个 FFmpeg 进程就够了。但平台级别的转码(日均百万级视频上传)需要完整的分布式调度系统:

任务编排层:接收上传完成事件,根据源文件信息生成转码 DAG(有向无环图)。DAG 里包含分析、切割、多码率转码、合并、切片、索引生成等节点。

调度层:把 DAG 中的转码任务分发到集群节点。关键的调度策略包括:

  • 数据本地性:优先把任务分配到源文件所在节点,减少数据搬运
  • GPU 亲和性:H.264 用 NVENC 硬件编码的任务分配到有 GPU 的节点
  • 负载均衡:根据各节点的 CPU/GPU 使用率和队列长度做均衡

执行层:每个节点运行 FFmpeg worker,通过容器化实现资源隔离。Kubernetes + 自定义 operator 是目前比较主流的方案,字节跳动和快手都有类似架构的内部系统。

多码率 ABR Ladder

ABR Ladder(自适应码率阶梯)定义了一组码率/分辨率组合,让播放器根据网络状况选择最优档位。

传统的固定 ABR Ladder:

档位 分辨率 视频码率 音频码率 目标带宽
1 1920x1080 8 Mbps 192 kbps 10+ Mbps
2 1280x720 5 Mbps 128 kbps 6 Mbps
3 854x480 2.5 Mbps 128 kbps 3 Mbps
4 640x360 1 Mbps 96 kbps 1.5 Mbps
5 426x240 400 kbps 64 kbps 600 kbps

Netflix Per-Title Encoding

Netflix 在 2015 年提出了一个影响深远的观点:不同内容的编码复杂度差异巨大,用固定码率编码是一种浪费

一个静态演讲视频,720p 下 1.5Mbps 就能达到很好的画质;而一个动作片的爆炸场景,720p 下 5Mbps 可能还不够。Netflix 的解法是 per-title encoding

  1. 对每个视频独立做编码分析,生成 Rate-Quality 曲线
  2. 在曲线上找到每个分辨率的最优码率点(质量边际收益开始递减的拐点)
  3. 生成该视频专属的 ABR Ladder

后来这个思路进一步演进为 per-shot encoding(按镜头级别优化)和 per-frame encoding——Netflix 公开数据显示,per-title encoding 相比固定 ladder 平均节省 20% 的带宽,画质不变甚至更好。

YouTube 也有类似的 VP9/AV1 编码优化策略。Bilibili 则在 2023 年推出了基于机器学习的智能编码系统,根据视频内容自动调整编码参数。

一句话总结:转码分片通过 GOP 对齐切割实现分布式并行,多码率 ABR Ladder 提供了适配不同网络的能力,而 per-title encoding 则在此基础上进一步压缩了编码冗余。

流媒体封装协议:HLS vs DASH vs CMAF

转码完成后,视频需要被封装成流媒体协议格式,才能被播放器以分片方式请求和播放。

HLS(HTTP Live Streaming)

Apple 在 2009 年推出的 HLS 是目前最广泛部署的流媒体协议。其核心思路:

  1. 把视频切成固定时长(通常 6s)的小文件(.ts 或 .fmp4)
  2. 生成一个播放列表文件(.m3u8)索引这些分片
  3. 播放器通过 HTTP 逐个下载分片播放
#EXTM3U
#EXT-X-VERSION:7
#EXT-X-TARGETDURATION:6

#EXT-X-STREAM-INF:BANDWIDTH=8000000,RESOLUTION=1920x1080
1080p/playlist.m3u8
#EXT-X-STREAM-INF:BANDWIDTH=5000000,RESOLUTION=1280x720
720p/playlist.m3u8
#EXT-X-STREAM-INF:BANDWIDTH=2500000,RESOLUTION=854x480
480p/playlist.m3u8
#EXT-X-STREAM-INF:BANDWIDTH=1000000,RESOLUTION=640x360
360p/playlist.m3u8

子播放列表的内容:

#EXTM3U
#EXT-X-VERSION:7
#EXT-X-TARGETDURATION:6
#EXT-X-MEDIA-SEQUENCE:0

#EXTINF:6.006,
segment_000.ts
#EXTINF:6.006,
segment_001.ts
#EXTINF:6.006,
segment_002.ts
#EXTINF:5.338,
segment_003.ts
#EXT-X-ENDLIST

DASH(Dynamic Adaptive Streaming over HTTP)

MPEG-DASH 是国际标准(ISO/IEC 23009),与 HLS 的核心思路相同,但在协议设计上更灵活:

  • 使用 XML 格式的 MPD(Media Presentation Description)替代 m3u8
  • 原生支持 fMP4 容器(而非 HLS 早期的 MPEG-TS)
  • 支持更丰富的时间模型和内容保护方案

CMAF:统一的容器格式

HLS 最初用 .ts(MPEG-2 Transport Stream)作为分片容器,DASH 用 .m4s(fragmented MP4)。两套格式意味着同一个视频要存两份分片,存储成本翻倍。

CMAF(Common Media Application Format)的目标就是统一容器格式——使用 fMP4 作为通用容器,HLS 和 DASH 共享同一套分片文件,只需要各自的 manifest(m3u8 / MPD)。

Apple 从 HLS 第 7 版开始支持 fMP4 容器,这使得 CMAF 在实践中成为可能。

协议对比

特性 HLS DASH CMAF
提出方 Apple (2009) MPEG (2012) MPEG + Apple (2018)
Manifest 格式 m3u8 (文本) MPD (XML) 复用 HLS/DASH
分片容器 .ts 或 .fmp4 .m4s (fmp4) .fmp4
iOS 支持 原生 需 JS Player 通过 fMP4
Android 支持 ExoPlayer 原生 ExoPlayer
DRM 集成 FairPlay Widevine/PlayReady 两者皆可
低延迟版本 LL-HLS LL-DASH 支持
生态成熟度 最广泛 开放标准 逐步推广
典型用户 Apple/抖音/Bilibili YouTube/Netflix 新建系统推荐

分片时长的取舍

segment 时长是一个关键参数,直接影响用户体验和系统效率:

分片时长 延迟 编码效率 CDN 缓存效率 Seek 精度 适用场景
2s 低 (~4-6s) 较差 分片数多 准直播、低延迟
4s 中 (~8-12s) 中等 平衡 通用点播
6s 高 (~12-18s) 高效 较低 Apple 推荐默认
10s 很高 最好 最高效 长内容、带宽节省

Apple 推荐 HLS 使用 6s 的分片时长,但在实际工程中,4s 是目前更主流的选择——在延迟和效率之间取得了较好的平衡。

LL-HLS 与 LL-DASH:低延迟方案

传统 HLS 的延迟通常在 15-30s(3 个 segment 的缓冲),这对直播场景来说太高了。

LL-HLS(Low-Latency HLS,Apple 2019 年提出)的核心改进:

  • 部分分片(Partial Segments):把一个 6s 的 segment 进一步拆成多个 200ms-500ms 的 partial segment
  • 阻塞式播放列表加载:播放器请求 playlist 时可以阻塞等待新的 partial segment 出现,避免轮询
  • 预加载提示:服务端可以告诉播放器下一个 partial segment 的 URL,实现提前请求

LL-HLS 可以把延迟从 15-30s 降到 2-5s。

LL-DASH 使用 Chunked Transfer Encoding 实现类似效果,播放器在 segment 还没完全生成时就可以开始下载已经产出的部分。

一句话总结:HLS 是兼容性之王,DASH 是开放标准的选择,CMAF 是统一格式的未来方向。分片时长在延迟和效率之间取舍,低延迟场景用 LL-HLS/LL-DASH 把延迟压到秒级。

CDN 分发:让分片离用户更近

视频内容天然适合 CDN 加速——单个 segment 文件小(几百 KB 到几 MB),访问模式有明显的时间局部性(热门视频的前几个 segment 被大量请求),而且 segment 一旦生成就不会修改(天然的不可变对象)。

CDN 分发与自适应码率播放

CDN 缓存策略

视频分片的缓存策略和普通网页资源有很大区别:

分层缓存架构

层级 角色 缓存内容 TTL
L1 边缘节点 靠近用户,毫秒级响应 热门视频的前 N 个 segment 24-48h
L2 中间层 区域汇聚,减少回源 全量 segment 7-30d
源站 存储全量数据 所有文件 永久

缓存预热策略

  • 头部分片优先:视频的前 3-5 个 segment 缓存优先级最高(大部分用户的首次播放集中在开头)
  • 热度驱动:根据视频的实时播放热度动态调整缓存策略
  • 码率分层:720p 的缓存优先级高于 1080p 和 480p(覆盖最广的中间码率)

Netflix 公开数据显示,其 CDN(Open Connect)的缓存命中率超过 95%,回源流量不到总流量的 5%。这得益于他们的 预填充策略:新内容上线前,主动把热门内容推送到边缘节点。

多 CDN 调度

大型视频平台不会只用一家 CDN。Bilibili 同时使用了自建 CDN、阿里云 CDN、腾讯云 CDN 等多家供应商。多 CDN 的调度逻辑:

  1. DNS 层调度:根据用户 IP 的地理位置,解析到最近的 CDN 节点
  2. HTTP 302 调度:请求到达调度服务后,根据实时状态 302 重定向到最优节点
  3. 客户端调度:播放器 SDK 内置调度逻辑,根据历史测速数据选择 CDN

核心调度因子包括:

  • 各 CDN 节点的实时可用带宽和延迟
  • 当前 CDN 供应商的成本(不同供应商的流量单价不同)
  • 节点健康状态(故障自动摘除)
  • 区域覆盖能力(有些 CDN 在某些省份覆盖更好)

回源优化

CDN 回源是成本的大头(源站出口带宽很贵),优化回源有几个关键策略:

合并回源:当多个边缘节点同时回源请求同一个 segment 时,中间层做请求合并,只向源站发一次请求。这在新视频刚上线时特别有用——瞬间涌入的大量请求如果每个都回源,源站扛不住。

Range 回源:用户 Seek 跳转时,播放器可能只需要 segment 的一部分。支持 Range 请求可以减少无效数据传输。

源站多地部署:源站本身做多区域部署(比如华北、华东、华南各一套),CDN 回源时就近选择源站,减少跨地域回源的延迟和带宽成本。

一句话总结:CDN 分发的核心是把视频分片缓存到离用户最近的地方,通过分层缓存、多 CDN 调度和回源优化,把缓存命中率做到 90% 以上,源站压力控制在极低水平。

播放器 ABR:每一个分片请求都是一次决策

ABR(Adaptive Bitrate)是流媒体播放的灵魂。播放器在请求每一个 segment 之前,都要根据当前的网络状况和缓冲区状态,决定请求哪个码率的版本。

ABR 算法的两个流派

Throughput-based(基于吞吐量)

核心思路:用最近几个 segment 的下载速度来估算当前带宽,选择不超过估算带宽的最高码率。

estimated_bandwidth = EWMA(recent_download_speeds)
selected_bitrate = max(bitrate for bitrate in ladder
                       if bitrate < estimated_bandwidth * safety_factor)

优点是实现简单,反应灵敏。缺点是对带宽波动敏感,可能频繁切换码率(用户感知为画面质量忽高忽低)。

Buffer-based(基于缓冲区)

核心思路:根据当前缓冲区的水位决定码率——缓冲区水位高说明网络充裕可以升码率,水位低说明网络不足需要降码率。

if buffer_level > high_threshold:
    # 缓冲充足,尝试升码率
    selected_bitrate = next_higher_bitrate
elif buffer_level < low_threshold:
    # 缓冲紧张,紧急降码率
    selected_bitrate = lowest_bitrate
else:
    # 缓冲区适中,线性映射码率
    selected_bitrate = linear_map(buffer_level, lowest, highest)

优点是码率切换更平滑,不会因为短暂的带宽波动而频繁跳档。缺点是反应较慢,在带宽突变时可能来不及调整导致卡顿。

实际应用中的混合策略

YouTube 的 ABR(基于 MPC——Model Predictive Control)综合考虑吞吐量估计、缓冲区水位、未来几个 segment 的码率切换成本,在一个优化模型中求解最优决策。Netflix 的 ABR 也是混合方案,并且加入了 QoE(Quality of Experience)评分模型。

hls.js(最流行的开源 HLS 播放器库)默认使用 throughput-based + buffer-based 的混合策略,开发者可以通过配置调整两者的权重。

首帧优化

首帧时间(Time to First Frame)是视频体验的关键指标。YouTube 的数据显示,首帧时间每增加 1 秒,用户放弃率增加约 6%。

优化手段包括:

  1. 低码率起播:首个 segment 用最低码率(360p),后续快速升档。用户宁可先看到模糊画面,也不愿意盯着加载圈
  2. 预加载 manifest:在用户点击播放前就提前请求 m3u8/MPD
  3. Preload Hints:LL-HLS 支持在 playlist 中声明下一个 segment 的 URL,播放器提前建连
  4. CDN 预热:热门视频的前几个 segment 提前推送到边缘节点
  5. 连接复用:使用 HTTP/2 或 HTTP/3 复用 TCP/QUIC 连接,避免每个 segment 都重新握手

抖音的首帧优化做得非常激进——通过预下载策略(在 feed 流中预加载即将可能被点击的视频的首个 segment),把首帧时间压到了 200ms 以内。

Seek 优化

用户拖动进度条时,播放器需要快速定位到目标时间点并开始播放。Seek 性能取决于几个因素:

  1. segment 边界对齐:目标时间点通常不在 segment 边界上,播放器需要请求包含目标时间点的 segment,然后在本地丢弃目标点之前的帧
  2. 关键帧距离:解码必须从 I 帧开始,如果 GOP 很长(比如 10s),Seek 到 GOP 中间位置时需要从 GOP 头部的 I 帧开始解码,丢弃中间的帧
  3. Range 请求:如果知道目标时间点在 segment 文件中的字节偏移,可以用 HTTP Range 只请求需要的部分

Netflix 使用了 trick play 技术:预先生成低分辨率的 I-frame-only 流,用户拖动进度条时显示这个流的预览图,松手后再切回正常播放流。

一句话总结:ABR 的核心在于用合理的模型估算网络状态,在画质和流畅性之间找到最优平衡。首帧和 Seek 优化则通过预加载、低码率起播等工程手段提升交互体验。

DRM 与安全:分片级别的内容保护

付费内容、版权内容需要 DRM(Digital Rights Management)保护。在分片架构下,DRM 加密是以 segment 为单位进行的。

三大 DRM 系统

特性 Widevine FairPlay PlayReady
所有方 Google Apple Microsoft
覆盖平台 Android/Chrome/Smart TV iOS/macOS/Safari Windows/Xbox/Edge
安全级别 L1(硬件)/L2/L3(软件) 仅硬件 SL150(软件)/SL2000/SL3000(硬件)
支持的封装 DASH/HLS(CMAF) HLS DASH/HLS(CMAF)
许可证费用 免费 需 Apple 开发者账号 按量付费
离线播放 支持 支持 支持

覆盖全平台至少需要 Widevine + FairPlay 两套方案。大多数商业视频平台(爱奇艺、腾讯视频、Netflix)都三套全部部署。

分片级加密

以 AES-128-CBC(HLS 标准加密)和 SAMPLE-AES(样本级加密)为例:

AES-128-CBC:对整个 .ts segment 文件做 AES-128 加密。密钥通过 Key Server 获取,m3u8 中声明密钥 URI:

#EXT-X-KEY:METHOD=AES-128,URI="https://key.example.com/key/abc123",IV=0x00000000000000000000000000000001
#EXTINF:6.006,
encrypted_segment_000.ts

SAMPLE-AES / CENC:只加密媒体样本(视频的 NAL 单元和音频帧),不加密容器头部。这意味着播放器可以先解析容器结构(知道分辨率、时长等信息),再解密实际的媒体数据。CENC(Common Encryption)是 MPEG 标准,允许同一份加密内容被 Widevine、FairPlay、PlayReady 解密——实现了 加密一次,多 DRM 解密 的目标。

密钥轮换

为了增强安全性,高安全要求的场景(如院线窗口期的电影)会做密钥轮换——每隔 N 个 segment 更换一次加密密钥。这样即使某一段时间的密钥被破解,也只能解密对应的几个 segment,无法解密整个视频。

Netflix 的策略是对不同安全级别的内容采用不同的密钥轮换频率:普通内容不轮换,高价值内容(如独占首映)每 5 分钟轮换一次。

一句话总结:DRM 在分片架构下天然地以 segment 为加密单位运作,CENC 标准实现了加密一次多端解密,密钥轮换在安全性和性能之间提供了灵活的选择空间。

直播场景:实时切片与延迟控制

直播和点播的核心区别在于:点播的分片在播放前就全部生成好了,而直播的分片必须实时生成。这带来了完全不同的工程挑战。

实时切片流程

直播的转码-切片-分发链路必须在极短时间内完成:

  1. 推流端:主播通过 RTMP/SRT 把音视频流推到服务端
  2. 转码:实时转码为多个码率档位(延迟要求比点播严格得多,通常用 -preset veryfast 或硬件编码)
  3. 切片:以 GOP 为单位生成 segment,同时更新 m3u8 playlist
  4. 分发:新生成的 segment 立即推送到 CDN 边缘节点

整个链路的延迟预算:

编码延迟 (1 GOP, ~2s)
+ 转码延迟 (~0.5s)
+ 切片上传 (~0.3s)
+ CDN 分发 (~0.5s)
+ 播放器缓冲 (3 segments = ~6s)
= 总延迟约 9-10s (传统 HLS)

延迟控制对比

方案 典型延迟 核心机制 兼容性 适用场景
传统 HLS 15-30s 3-segment 缓冲 最好 非交互直播
LL-HLS 2-5s Partial Segments + 阻塞加载 iOS 14+, 需支持的 CDN 互动直播
传统 DASH 10-20s 类似 HLS 非交互直播
LL-DASH 2-5s Chunked Transfer 需 DASH 播放器 互动直播
WebRTC 0.5-1s P2P + UDP 浏览器原生 连麦、实时互动
RTMP 2-5s 持久 TCP 连接 Flash 退役后受限 推流端(非播放端)
SRT 0.5-2s UDP + ARQ 需专用播放器 专业级远程制作

实际案例

抖音直播:推流用 RTMP/QUIC,播放端用 HTTP-FLV + HLS 双协议。HTTP-FLV 提供 2-3s 的低延迟用于互动场景,HLS 作为回退方案保证兼容性。

Bilibili 直播:推流用 RTMP,播放端主推 HTTP-FLV,辅以 HLS。2023 年开始试点 LL-HLS。

YouTube Live:推流支持 RTMP 和 HLS,播放端用 DASH,超低延迟模式可以达到 2-3s。

Twitch:推流用 RTMP,播放端用 LL-HLS,延迟约 2-3s。Twitch 是 LL-HLS 在大规模直播场景下的标杆案例。

直播分片的特殊挑战

时间窗口管理:直播的 m3u8 playlist 是滑动窗口——只保留最近 N 个 segment 的引用。播放器如果暂停太久,恢复播放时可能发现之前的 segment 已经从 playlist 中移除,需要跳到直播最新位置。

CDN 缓存一致性:直播的 m3u8 每隔几秒就更新一次,CDN 对 playlist 文件不能像点播那样长时间缓存。通常的策略是 playlist 文件的 CDN TTL 设为 0.5-1s,而 segment 文件设为较长的 TTL(segment 一旦生成就不变)。

推流端异常处理:主播断网、推流软件崩溃等情况下,服务端需要在最后一个 segment 的 m3u8 中加入 #EXT-X-ENDLIST 标记,通知播放器直播已结束,而不是让播放器一直轮询等待新 segment。

一句话总结:直播场景下,分片从预生成变成了实时生成,延迟控制的核心在于压缩编码-切片-分发-缓冲这条链路上每个环节的时间开销,LL-HLS 和 WebRTC 分别适用于不同的延迟要求。

架构全景与成本优化

视频平台的成本结构

对于一个日活千万级的视频平台,成本结构大致如下:

成本项 占比 量级参考
CDN 带宽 40-55% 最大头,随播放量线性增长
转码计算 20-30% GPU 实例成本高,但可弹性
存储 10-15% 多码率版本 + 原始文件
源站带宽 5-10% 回源流量,单价高
其他 5-10% DRM License Server、监控等

对于中小平台,CDN 费用是最大的成本项。以国内云厂商的价格为参考:CDN 带宽按峰值计费约 10-30 元/Mbps/月,按流量计费约 0.15-0.25 元/GB。一个日均 1 亿次播放、平均观看 3 分钟的平台,日均 CDN 流量约 150-300TB,月 CDN 成本可达数百万元。

成本优化策略

编码优化(效果最显著)

提升编码效率是最根本的降本手段——同样的画质用更少的码率就意味着更少的 CDN 流量和存储。

  • 从 H.264 迁移到 H.265:相同画质下节省 30-40% 码率
  • 从 H.265 迁移到 AV1:进一步节省 20-30%
  • Per-title encoding:根据内容复杂度自动调整码率,平均再省 20%
  • 两遍编码(Two-pass):第一遍分析内容分配码率预算,第二遍按预算编码,比单遍编码质量更高

YouTube 估算,AV1 编码相比 VP9 每年为其节省数十亿美元的 CDN 成本。

存储优化

  • 冷热分离:最近 7 天的视频存热存储(SSD),7-90 天的存温存储(HDD),90 天以上存冷存储(归档级)
  • 延迟转码:不是所有上传的视频都需要立刻生成全部码率。可以只先生成 720p,当视频播放量达到阈值后再生成 1080p 和 480p
  • 原始文件清理:转码完成并确认质量后,可以删除原始文件只保留转码后的版本(需要权衡是否有重新转码的需求)

CDN 优化

  • 缓存命中率提升:优化缓存 key 设计,避免不必要的缓存穿透(比如 URL 中包含用户 ID 导致同一个 segment 被缓存多份)
  • 多 CDN 成本博弈:同时接入 3-4 家 CDN,根据实时价格和质量动态调度。大客户可以跟 CDN 厂商谈阶梯价格
  • P2P 辅助分发:在客户端之间做 P2P 传输,减少 CDN 回源。Bilibili 的 P2P 方案在高峰期可以分担 30-40% 的 CDN 流量
  • HTTP/3 + QUIC:减少连接建立开销,在弱网环境下提高传输效率,间接减少重传导致的带宽浪费

转码优化

  • 弹性伸缩:使用 Spot Instance / 竞价实例做转码,成本降低 50-70%
  • 硬件编码:GPU 的 NVENC 硬件编码器速度是 CPU 软编码的 5-10 倍,虽然同码率下质量略逊于 x264/x265 的 slow preset,但在时效性要求高的场景下性价比极高
  • 智能转码策略:只转码有人看的码率。统计数据显示,80% 的播放集中在 720p 和 480p,1080p 的播放占比通常不到 15%。可以按需生成冷门码率

监控与质量保障

完善的监控体系是保障视频体验的基础:

播放侧指标

  • 首帧时间(P50 < 1s,P99 < 3s)
  • 卡顿率(rebuffer ratio < 1%)
  • 码率切换频率(每分钟不超过 2 次)
  • 播放失败率(< 0.1%)

服务侧指标

  • CDN 缓存命中率(> 90%)
  • 转码排队时间(P99 < 5min)
  • 源站 5xx 错误率(< 0.01%)

YouTube 有一个叫 Video Quality Report 的内部系统,实时监控全球数亿设备的播放质量。Netflix 的 Telescope 系统则从 ISP 级别的网络质量到播放器帧级别的渲染质量全链路监控。

一句话总结:视频平台的成本大头是 CDN 带宽,最有效的降本路径是提升编码效率;存储分层、按需转码、P2P 辅助分发等策略叠加起来,可以在不影响体验的前提下把成本降低 40-60%。

总结:分片思维是视频工程的第一性原理

回顾全文,视频处理全链路的每个环节都在做同一件事——把大的变成小的,把串行的变成并行的,把集中的变成分散的

环节 分片策略 核心收益
上传 文件切块 + 并发传输 断点续传、秒传
转码 GOP 对齐切割 + 分布式并行 分钟级完成小时级任务
封装 固定时长 segment + manifest 索引 流式传输、即时播放
CDN segment 级缓存 + 多级分发 高命中率、低延迟
播放 逐片请求 + ABR 决策 自适应码率、流畅体验
DRM 分片级加密 + 密钥轮换 安全与性能兼顾
直播 实时切片 + Partial Segment 秒级延迟

这种分片思维不只适用于视频,它是处理大规模数据问题的通用范式——大文件传输要分片(BitTorrent),大数据处理要分片(MapReduce),大模型推理要分片(Tensor Parallelism)。

对于想要深入视频技术的工程师,我的建议是:先用 FFmpeg 手动走一遍完整的切片-转码-封装-播放流程,建立直觉后再去理解上层平台的设计选择。很多看起来复杂的系统,拆开来看都是围绕「分片」这一个核心动作的不同变体。

加载导航中...

评论