系统设计:视频流媒体平台

从零设计一个视频流媒体平台,覆盖上传与转码流水线、切片与 HLS/DASH 协议、CDN 分发与回源、播放器自适应码率、弹幕互动、存储与带宽成本,包含容量估算、架构图、数据模型、选型对比与面试追问。

系统设计:视频流媒体平台

视频平台的复杂度远超「上传一个文件、播放一个文件」:一次上传要经过转码、切片、分发,一次播放要在弱网与高清之间动态权衡,而成本的大头是带宽而非存储。本文按面试节奏逐步拆解。

1. 需求分析

功能性需求

  • 上传:分片上传、断点续传、秒传(内容去重)
  • 转码:多分辨率多码率、水印、封面抽取
  • 播放:多清晰度切换、拖动进度、断线续播
  • 互动:弹幕、评论、点赞、投币
  • 管理:审核、下架、统计观看时长

非功能性需求

  • 起播延迟:低于 1 秒(点播)
  • 卡顿率:低于 1%
  • 可用性:99.99%,播放链路无单点
  • 规模:日活 1 亿,日播放 10 亿次
  • 成本:带宽成本可预测、可优化

核心难点

  1. 转码算力:一源多档,算力需求是上传量的数十倍
  2. 分发成本:CDN 带宽是最大开销,必须提高命中率
  3. 弱网体验:用户网络差异巨大,必须自适应码率

2. 容量估算

  • 日上传视频:500 万个,平均原始大小 100 MB
  • 日新增原始数据:500 万 × 100 MB = 500 TB/天
  • 转码后多档合计:约 1.5 倍原始大小 → 750 TB/天
  • 日播放 10 亿次,平均单次观看 50 MB → 50 PB/天出口流量
  • 若 CDN 命中率 95%,回源流量仅 2.5 PB/天

关键结论:出口带宽按 PB/天计,因此「提高 CDN 缓存命中率」与「降低平均码率」是成本优化的两大杠杆,远比省存储重要。

3. 整体架构

上传端 ──► API 网关 ──► 上传服务 ──► 对象存储(原始文件)
                              │
                              ▼
                     转码任务队列(Kafka)
                              │
                              ▼
                   转码集群(分片并行 + GPU)
                              │
                     ┌────────┴────────┐
                     ▼                 ▼
              切片产物(HLS/DASH)   封面/元数据
                     │                 │
                     ▼                 ▼
              对象存储(源站) ◄── 元数据服务(MySQL/Redis)
                     │
                     ▼
                  CDN 边缘节点
                     │
                     ▼
                  播放器(App/Web)

上传路径

客户端分片上传到上传服务,上传服务做内容哈希实现秒传,原始文件落对象存储,随后投递转码任务。

播放路径

播放器请求播放清单(Manifest),CDN 返回切片列表与地址,播放器按当前带宽选择码率拉取切片;CDN 未命中则回源站。

4. 数据模型

视频主表

videos (
    video_id     BIGINT PRIMARY KEY,
    user_id      BIGINT,
    title        VARCHAR(256),
    duration_ms  INT,
    cover_url    VARCHAR(512),
    source_hash  CHAR(64),        -- 秒传去重
    status       TINYINT,         -- 上传/转码中/可播/下架
    created_at   TIMESTAMP
)

转码产物表

video_variants (
    variant_id   BIGINT PRIMARY KEY,
    video_id     BIGINT,
    resolution   VARCHAR(16),     -- 360p/720p/1080p
    bitrate_kbps INT,
    codec        VARCHAR(16),     -- H.264/H.265/AV1
    manifest_url VARCHAR(512),    -- m3u8/mpd 地址
    segment_cnt  INT
)

弹幕表

danmaku (
    danmaku_id   BIGINT PRIMARY KEY,
    video_id     BIGINT,
    user_id      BIGINT,
    offset_ms    INT,             -- 相对视频时间轴
    content      VARCHAR(128),
    mode         TINYINT,         -- 滚动/顶部/底部
    created_at   TIMESTAMP
)

5. 转码流水线

为什么必须转码

  • 原始文件码率与编码格式五花八门,设备无法直接播放
  • 需要在画质与带宽之间提供多档选择
  • 需要统一封装为流式协议便于切片与自适应

转码任务拆解

  1. Demux:解封装,分离音视频轨道
  2. Decode:解码为原始帧
  3. Filter:缩放、去噪、加水印
  4. Encode:按目标码率重新编码(H.264/H.265/AV1)
  5. Package:切片并生成清单文件

并行加速

  • 时间分片并行:把视频按 GOP 切成多段,多台机器并行转码后拼接,几乎线性加速
  • 硬件加速:GPU/专用编码卡(NVENC)吞吐是 CPU 的数倍
  • 优先级队列:大 UP 主与热门内容优先,长尾内容排队

转码档位设计

档位分辨率码率适用网络
240p426×240300 kbps弱网/2G
480p854×4801 Mbps3G
720p1280×7202.5 Mbps4G/WiFi
1080p1920×10805 Mbps宽带
4K3840×216015 Mbps高速宽带

6. 切片与流式协议

HLS 与 DASH 对比

维度HLSDASH
开发者Apple标准化组织
清单格式m3u8(文本)MPD(XML)
兼容性iOS 原生支持需 MSE
延迟传统 6-30 秒,低延迟可到 2 秒可更低
编码多支持 H.264/H.265支持 AV1 等新编码

切片策略

  • 每片时长 2 到 6 秒,过长导致切换码率迟钝,过短导致请求数暴增
  • 关键帧必须对齐切片边界,否则切换码率时会花屏
  • 每档码率生成独立切片序列,清单中列出所有档位的地址

清单文件示例

#EXTM3U
#EXT-X-STREAM-INF:BANDWIDTH=800000,RESOLUTION=640x360
360p/index.m3u8
#EXT-X-STREAM-INF:BANDWIDTH=2500000,RESOLUTION=1280x720
720p/index.m3u8

7. CDN 分发与回源

分层缓存

  • 边缘节点:离用户最近,命中率最高,容量最小
  • 中间层:区域汇聚,回源前的一级缓冲
  • 源站:对象存储,仅在全部未命中时访问

提高命中率的手段

  1. 热点预热:新发布视频主动推送到边缘
  2. 长尾合并:冷门视频用更大缓存粒度,减少回源次数
  3. 一致性哈希:同一视频固定路由到同一节点,避免缓存碎片
  4. 智能回源:合并回源请求(回源聚合),降低源站压力

CDN 边缘缓存的失效与回源策略,与 分布式缓存设计 的缓存穿透、击穿问题本质相同;首页推荐流的分发则可参考 信息流系统设计。

成本优化

手段效果代价
提高 CDN 命中率直接降低回源带宽需要更大边缘容量
使用 H.265/AV1同画质码率降 30% 到 50%编码与解码算力上升
多档码率覆盖弱网用户自动降档转码存储增加
P2P 辅助分发热门内容省带宽实现复杂、依赖客户端

8. 播放器与自适应码率

ABR 自适应码率

播放器持续测量下载速度与缓冲区水位,动态选择下一片码率:

def select_bitrate(throughput_kbps, buffer_sec, variants):
    # 缓冲区充足时更激进,紧张时保守
    margin = 1.5 if buffer_sec > 10 else 0.8
    target = throughput_kbps * margin
    candidates = [v for v in variants if v.bitrate_kbps <= target]
    return max(candidates, key=lambda v: v.bitrate_kbps) if candidates else variants[0]

常见算法:基于吞吐量(Throughput)、基于缓冲区(Buffer-based,如 BOLA)、以及两者混合。核心目标是既不卡顿、又不浪费码率。

起播优化

  • 预加载首片、预连接 CDN 域名(DNS/TCP/TLS 预热)
  • 首片用低码率,缓冲稳定后再升档
  • 播放器缓存清单,减少首帧前的往返

断线续播与拖动

  • 播放进度上报服务端,换设备可续播
  • 拖动到未缓冲区间时优先拉取目标位置的关键帧切片

9. 弹幕与互动

弹幕的写入与读取

  • 写:弹幕按视频时间轴写入,量级大但单条小,用分片表 + 时间索引
  • 读:播放器按当前时间窗口拉取(如当前秒前后 5 秒),做本地渲染
  • 热点保护:超热门视频的弹幕做采样与去重,避免刷屏

弹幕一致性

弹幕容忍最终一致,可用消息队列异步落库 + 内存缓存加速读取。与 IM 的实时性要求不同,弹幕延迟一两秒用户无感。

互动数据

点赞、投币、收藏走独立的计数服务,用 Redis 计数 + 异步落库,防止高频写打爆数据库。

10. 面试常见问题

Q: 转码为什么这么贵,怎么优化?
贵在解码与编码的算力。优化路径:时间分片并行缩短墙钟时间、GPU 硬件编码提升吞吐、按热度分级只转必要档位、用更高效的编码标准降低后续带宽。

Q: 为什么用 HLS 而不是直接传 MP4?
MP4 是整文件下载播放,无法中途切换码率、无法快速起播。HLS/DASH 切片后可按需拉取、动态切档,且天然适配 CDN 缓存。

Q: CDN 回源流量怎么降下来?
提高边缘命中率(预热、一致性哈希、合并回源)、降低码率(新编码)、把冷门内容缓存粒度调大,最后才是加缓存节点。

Q: 弱网下如何保证不卡顿?
ABR 快速降档到低码率保连续播放,宁可清晰度低也不卡顿;同时扩大缓冲水位、预取后续切片。

Q: 弹幕量极大时怎么扛?
写入侧限流 + 采样,读取侧按时间窗口拉取并本地渲染;热门视频可对弹幕做聚合展示。

Q: 存储成本怎么估?
原始 + 多档转码约 2.5 倍原始大小,冷门视频可降档或转冷存储;但真正的大头是带宽,估成本时要先算出口流量再算存储。

Q: 秒传怎么实现?
客户端计算文件内容哈希,服务端若已存在相同哈希则直接建立引用,不重复上传与转码。

总结

视频流媒体平台的答题主线是上传—转码—分发—播放四段流水线:上传侧做分片与秒传,转码侧做并行与多档,分发侧靠 CDN 命中率与缓存分层,播放侧靠 ABR 自适应。所有设计最终都要落到两个数字上——带宽成本与卡顿率,能把这两者的 trade-off 讲清楚,再补上弹幕与审核的边界处理,这道题就稳了。

继续阅读

探索更多技术文章

浏览归档,发现更多关于系统设计、工具链和工程实践的内容。

全部文章 返回首页