系统设计:Design a Video Streaming Platform
把一个 MP4 放进 object storage,再返回下载链接,可以完成最早的 demo。它无法解决真实播放环境:用户网络会不断变化,手机不需要下载 4K,拖动到第 30 分钟不应先下载前 29 分钟,一个热门直播也不能让几百万观众同时打到源站。
视频平台的核心不是“存大文件”,而是:把原始媒体异步处理成多种码率的小分片,由 manifest 描述播放顺序,再通过 CDN 和自适应码率让客户端根据网络持续选择。
配套实验:打开 Video Streaming Lab。先增加上传量和 rendition 数,观察转码;再增加并发观众,观察瓶颈如何转到 CDN egress。
为什么一个视频要保存很多份
上传一个 4K 视频,平台可能生成:
2160p 12 Mbps
1080p 5 Mbps
720p 2.5 Mbps
480p 1 Mbps
360p 0.5 Mbps
audio 128 Kbps
每个 rendition 又切成例如 2–6 秒的 segments。播放器先下载 manifest,然后根据当前带宽和 buffer 选择下一段的码率。
如果网络从 20Mbps 突然掉到 2Mbps,播放器无需重开整个文件,只在下一个 segment 切到 720p/480p。这个机制叫 adaptive bitrate streaming(ABR)。
它增加转码和存储,却显著降低卡顿,并适配不同屏幕和网络。后面所有架构都围绕这条内容准备与分发链路展开。
先讲清 Source、Rendition、Segment 和 Manifest
Source asset
用户上传的原始媒体。它是最高质量事实来源,通常长期保留或按策略归档。
Rendition
某种分辨率、码率、codec 和音频组合的转码结果。
Segment
几秒钟的媒体块。播放器可以独立请求、缓存和切换码率。
Manifest / playlist
描述有哪些 rendition、每个 segment 的 URL、时长、codec 和加密信息。HLS 常见 .m3u8,DASH 常见 MPD。
Origin 与 CDN
Origin 保存媒体对象;CDN 在全球 edge 缓存 segment。绝大多数播放流量应停在 edge,而不是回源。
题目边界
核心功能:
- 断点上传视频;
- 校验、转码、切片、生成缩略图和 manifest;
- 发布/下架视频;
- 点播播放、seek 和 ABR;
- CDN 分发和访问授权;
- 记录 playback/QoE 事件;
- 支持直播作为后续演化。
第一版不设计推荐、评论、完整 DRM license server 和内容审核模型。审核作为发布 gate。
非功能目标:
- 上传可续传,完成后原始文件不损坏;
- 处理 pipeline 可重试、可观察;
- 播放首帧快、rebuffer 少;
- 热门内容不冲垮 origin;
- 已下架内容快速停止新播放;
- 多租户/地域版权与访问控制正确;
- 媒体和 metadata 有明确 retention、复制与删除。
第一版:一个 MP4 的 Multipart Upload
客户端先创建 asset:
POST /v1/videos
{
"title":"System Design Lesson",
"contentType":"video/mp4",
"size":10737418240
}
返回 video_id 和 multipart upload session。客户端把 10GB 文件分块直传 object storage,失败只重传某些 parts。
完成:
POST /v1/videos/v-9/uploads/up-81:complete
{
"parts":[
{"partNumber":1,"etag":"..."},
{"partNumber":2,"etag":"..."}
],
"contentHash":"sha256:..."
}
服务端验证 size/hash,原子把 asset 从 UPLOADING 改为 PROCESSING,并写 outbox。半上传 object 位于 staging,不对播放器可见。
第一版转码可以只输出一个 720p MP4,支持 HTTP range。它先验证 upload、状态机、权限和 CDN;ABR 是下一步,而不是一开始搭十种 codec。
数据模型:处理状态与发布状态分开
Video(
video_id,
owner_id,
title,
visibility,
processing_state,
publishing_state,
source_asset_id,
active_package_id,
version,
created_at,
published_at
)
MediaAsset(
asset_id,
video_id,
type,
object_uri,
size,
content_hash,
codec,
width,
height,
duration_ms,
state
)
MediaPackage(
package_id,
video_id,
pipeline_version,
manifest_uri,
renditions,
state,
created_at
)
ProcessingJob(
job_id,
video_id,
stage,
input_artifact_hash,
attempt,
state,
output_ref,
failure_reason
)
一个视频可重新转码生成新 package;active pointer 切换后,新播放使用新 package,已开始的 session 可继续旧 manifest。不要原地覆盖 segments,CDN cache 会混入新旧内容。
处理 Pipeline:每个 Stage 都应幂等
validate / probe
-> malware / policy scan
-> transcode renditions
-> segment + package
-> thumbnails / captions
-> quality validation
-> publish
每个 stage 的 output key 由 source hash、pipeline version、rendition config 决定。Worker 重试相同输入时复用完整产物或写 attempt 临时路径,最后通过 manifest commit 发布。
flowchart LR U[Uploader] --> UP[Upload API] U --> O[(Object storage)] UP --> Q[(Processing queue)] Q --> V[Probe + validation] V --> T[Transcode workers] T --> S[Segment + package] S --> QA[Quality checks] QA --> M[(Metadata store)] S --> O O --> CDN[CDN] P[Players] --> CDN P --> E[QoE events]
Orchestrator 传 URI 和 metadata,不搬运视频 bytes。Transcode worker 尽量读取本地/同 Region source,输出直接写 object storage。
Rendition Ladder:不是分辨率越多越好
每多一个 rendition,都增加转码计算、存储和 packaging。固定 ladder 简单,但动画、体育、访谈对 bitrate 的需求不同。
可以先用固定 ladder,再根据 source resolution、帧率和复杂度做 per-title encoding。质量指标如 VMAF 帮助选择在目标质量下更低的 bitrate。
关键约束:相邻 rendition 的 keyframe/segment 边界对齐。否则播放器切码率时可能无法无缝解码。
Codec 也是取舍:新 codec 带宽更省,但编码更贵、设备支持不完整。Manifest 根据客户端 capability 提供兼容组合,不能只生成最先进 codec。
播放 API 和授权
POST /v1/videos/v-9/playback-sessions
{"device":{"codecs":["h264","hevc"],"maxHeight":1080}}
{
"sessionId":"ps-88",
"manifestUrl":"https://cdn.example.com/.../master.m3u8?token=...",
"expiresAt":"2026-07-13T18:00:00Z",
"heartbeatIntervalSeconds":30
}
Token 绑定 video/package、用户权限、地区、expiry 和可选 device。CDN edge 验证签名,避免每个 segment 都回源鉴权服务。
对公开视频,manifest/segments 可长缓存;私有/付费视频用短期 token、signed cookie/url。下架时停止签发新 session,并通过 CDN purge/短 manifest TTL 缩短残余窗口。
CDN:命中率和回源保护
Segment URL immutable,包含 package/version/hash:
/videos/v-9/packages/pkg-17/1080p/segment-0042.m4s
这样可以设置很长 cache TTL。新转码产生新 URL,不需要覆盖旧对象。
Manifest 更易变化,TTL 较短;VOD 发布后也可 immutable。Live manifest 持续更新,必须短 TTL 或 no-cache/revalidation。
热门新视频发布时,许多 edge 同时 miss 会冲击 origin。使用:
- Origin shield / mid-tier cache;
- Request coalescing,同一 segment 只回源一次;
- 热门内容预热;
- Origin per-key rate limit 和 autoscale;
- Multi-origin/replication。
Cache hit 要按 bytes 而不只 requests 计算。一个 4K segment miss 比一个小 manifest miss 贵得多。
ABR:播放器决定下一段,不是服务器强推
播放器持续估计:
network throughput
buffer seconds
recent download time
device decode capacity
viewport
选择能在 segment 播放前下载完成的最高 rendition。启动时通常保守选择较低码率,积累 buffer 后再升,减少首帧时间。
系统端提供对齐的 segments、准确 bitrate metadata 和多码率;具体 ABR 算法在 client。服务端 QoE 事件用来评估:startup time、rebuffer、bitrate、switch 和 fatal error。
不要只优化平均 bitrate。高码率但频繁卡顿通常比稳定较低画质更差。
容量估算:分发 Egress 远大于上传
假设 10M 并发观众,平均播放 bitrate 3Mbps:
10M × 3Mbps = 30Tbps egress
这不可能由单一 origin 提供,CDN 是架构核心而非优化项。
若 CDN byte hit 98%,origin 仍需:
30Tbps × 2% = 600Gbps
Origin shield 和多 Region 仍然重要。
上传假设每天 1M 小时 source,平均 10Mbps:
1M hours × 10Mbps ≈ 4.5PB source/day
若平均生成 6 个 rendition,总输出可能是 source 的数倍。Transcode 计算以 video minutes × ladder × codec 估算,按 queue age 和 deadline 调度。
Storage 不只 source + renditions,还包括 thumbnails、captions、DRM metadata 和旧 package retention。热门冷门分层到不同 storage class。
转码调度:短视频不能排在电影后面一整天
Job metadata 包含 duration、resolution、codec、priority 和 publish deadline。Scheduler 可把长视频按 time range 切成多个 parallel segments 转码,再做边界一致的 packaging。
优先级:
- Live/near-live 最高,必须跟上输入;
- 用户刚发布短视频,低等待;
- Library backfill/新 codec 转码可低优先级、可抢占。
GPU/ASIC encoder 提升吞吐,但某些 quality preset 仍需 CPU。Resource profile 通过 benchmark,不按“一个视频一个 worker”猜。
Backpressure 时 API 仍可接收上传,但明确预计处理时间;超出存储/队列上限则拒绝新大任务,不能无限积压。
Live Streaming:相同分发,不同时间边界
Live source 持续 ingest:
encoder -> ingest edge -> transcoder -> segmenter -> live manifest -> CDN
VOD 可以等整个文件上传后重试某段;Live 必须在 segment deadline 前完成,错过就无法回到过去。Pipeline latency 大致:
capture + encode + upload + transcode + segment + CDN + player buffer
6 秒 segment、播放器等 3 段就天然增加十几秒。Low-latency HLS/DASH 使用 partial segments、更小 buffer 和持续传输,代价是请求更多、CDN/cache 效率下降、卡顿容忍更低。
Live origin/encoder 故障可切备用 ingest。Manifest 中 discontinuity 明确处理时间线变化。直播结束后将 segments 和 manifest finalize 成 VOD package。
QoE 事件:服务端 200 不代表用户看到了
Player 上报:
playback_start
first_frame
segment_download
rebuffer_start/end
bitrate_switch
decode_error
playback_end
事件带 session ID、package/rendition、CDN POP、网络类型和时间。批量异步上报,不阻塞播放。
关键指标:
- Video start time;
- Rebuffer ratio / count;
- Average bitrate 和 switch;
- Playback failure;
- CDN byte hit、origin egress、segment p95;
- 按 ISP/device/codec/Region 切片。
平均成功率会掩盖某款电视 decoder 或某个 ISP 的严重问题。
故障与正确性
Multipart upload 中断
客户端查询已完成 parts,继续上传。过期 session 的 staging parts 后台清理。
Transcode worker 崩溃
Stage 按 source hash + config 幂等重试。临时 output 不进入 active package。
某个 Rendition 失败
如果最低可用 ladder 已完整,可以降级发布并标记 missing rendition;4K 失败不必阻止 720p。Audio/关键基础 rendition 失败则不发布。
Package 部分上传
Manifest 最后写并原子 publish。播放器不会看到引用缺失 segment 的 package。
CDN 回源风暴
Shield、coalescing、stale-if-error 和 per-object protection。Origin 失败时可短暂服务已缓存 immutable segment。
下架
Metadata 先改不可播放,停止签发 session;purge manifest/segments 按风险执行。已签 token 的残余窗口是明确产品语义。
关键取舍
更多 Rendition 改善 ABR 选择,也增加转码、存储和 manifest 复杂度。
更短 Segment 提高切码率和 seek 粒度、降低直播 latency,却增加请求数、header 开销和 CDN 压力。
新 Codec 降带宽,但编码成本和设备兼容性更差。
更长 CDN TTL 提高命中,适合 immutable segment;权限/manifest 更新需要 versioned URL 或 purge。
更大 Player buffer 减少卡顿,却增加 startup/live latency。
Origin 多 Region 提高可用性和回源容量,也增加复制、成本和一致性管理。
用 Lab 看瓶颈怎样迁移
实验一:增加上传与 Rendition
保持观众不变,观察 transcode queue 和 storage。决定固定 ladder 何时值得做 per-title 优化。
实验二:增加并发观众
观察 CDN egress 和 byte hit,确认增加 transcode worker无助于播放热点。
实验三:打开 Live
比较 VOD 的可重试 batch pipeline 与 live deadline。缩短 segment 后,记录 latency 和 CDN 请求放大。
面试表达:先把媒体准备与分发分开
可以这样开场:
I would separate the asynchronous media-processing path from the playback path. Uploads create immutable source assets; workers generate aligned bitrate renditions and segments; an immutable manifest is published only after validation; CDN edges then serve almost all playback traffic.
演化顺序:
multipart source upload
-> one validated rendition
-> multi-bitrate segments + manifest
-> CDN and origin shield
-> QoE-driven ABR tuning
-> live ingest and low-latency packaging
最后给深入入口:
I can go deeper into transcoding orchestration, CDN cache behavior, adaptive bitrate and QoE, or low-latency live streaming.
这样讲,视频系统不再是一张 S3 -> CDN 图,而是一条有完整 publish 边界的媒体供应链。