设计一个短视频系统

本文系统设计一个短视频平台:需求澄清与量级估算、上传管道与转码流水线、CDN 分发与多码率、推荐信息流(召回/排序)、互动与播放链路、成本与扩展性治理,并给出架构图、数据表、转码与推荐伪代码与量级估算。

短视频是今天流量密度最高的内容形态:一段 30 秒的视频在高峰期可能被上亿人刷到,背后的链路横跨上传、转码、存储、分发、推荐五个环节。本文按照系统设计面试的标准答题结构,设计一个短视频平台,覆盖创作者上传到用户观看的完整链路,以及海量内容下 CDN 成本与推荐质量的权衡。

一句话:短视频系统的核心是「把视频字节高效地送到每个人面前」——上传要快、转码要稳、分发要近、推荐要准,四者缺一不可,成本大头在带宽与转码。

一、需求澄清与量级估算

1.1 需求澄清

面试官给出题目「设计一个短视频系统」后,先通过提问明确边界:

  • 内容形态:UGC 短视频为主,还是含长视频/直播?是否多端(App/H5/小程序)?
  • 核心功能:上传、转码、播放、推荐信息流、点赞/评论/分享、关注,覆盖哪些?
  • 视频规格:时长限制(15 秒~10 分钟)?分辨率/码率档位(标清/高清)?
  • 推荐需求:是否需要个性化推荐?基于什么信号(观看历史/互动/关注)?
  • 成本约束:带宽与转码成本是否可以弹性(码率自适应、冷内容降级)?
  • 规模:多少 DAU、日均上传多少条、单条热门视频多少播放?

明确假设(面向面试的合理假设):

需求项假设
内容形态UGC 短视频,App + H5
视频时长15 秒 ~ 10 分钟
码率档位标清/高清/超清三档
推荐个性化信息流(召回 + 排序)
互动点赞/评论/分享/关注
规模3 亿 DAU、日上传 1000 万条、日播放 300 亿次

1.2 量级估算

指标估算值推导
DAU3 亿头部短视频平台
日均上传1000 万条创作者生态
日均播放300 亿次人均日刷 100 条
播放峰值5000 万/秒晚高峰
单视频大小5~50 MB三档码率 × 时长
峰值带宽数百 TB/s主流码率 × 并发播放
转码任务日千万级每上传一条多档转码
推荐时延P99 < 100ms信息流首屏体验

一句话:短视频是「带宽与算力的游戏」——300 亿次播放对应数百 TB/s 带宽、千万级转码对应巨大算力,架构的每一环都在「体验」与「成本」之间做文章。

二、高层架构设计

   ┌──────────────────────────┐    ┌──────────────────────────┐
   │ 创作者 (App 上传/编辑)    │    │ 用户 (App/H5 播放/互动)    │
   └────────────┬─────────────┘    └────────────┬─────────────┘
                │ 分片上传                       │ 播放请求(经 CDN)
                ▼                               ▼
   ┌─────────────────────────────────────────────────────────┐
   │ 上传网关 → 对象存储(原始视频) → 转码流水线(任务队列)       │
   │  ① 转码: 多码率/多分辨率 ② 切片: HLS/DASH 分片            │
   │  ③ 封面抽帧 ④ 审核(机审+人审)                           │
   └────────────────────┬────────────────────────────────────┘
                │ 转码产物写入 CDN 源站 / 对象存储
                ▼
   ┌─────────────────────────────────────────────────────────┐
   │                    CDN 分发层                             │
   │  边缘节点缓存视频分片 → 就近分发 → 降低源站带宽压力        │
   └────────────────────┬────────────────────────────────────┘
                │ 内容元数据(标题/封面/作者)
                ▼
   ┌─────────────────────────────────────────────────────────┐
   │      内容服务 (元数据)    +   推荐服务 (信息流)             │
   │  视频信息/作者/互动计数   召回(候选池)→粗排→精排→重排      │
   └────────────────────┬────────────────────────────────────┘
                │ 用户行为(播放/点赞/关注/时长)
                ▼
   ┌─────────────────────────────────────────────────────────┐
   │  行为数据链路:埋点 → Kafka → 实时特征 → 推荐/热门榜单     │
   └─────────────────────────────────────────────────────────┘

整体拆为六层:

  1. 上传层:分片上传、断点续传,原始视频进对象存储。
  2. 转码层:任务队列驱动的多码率转码 + HLS 切片 + 审核。
  3. 存储层:对象存储管视频字节,MySQL 管元数据。
  4. 分发层:CDN 就近分发,承载绝大部分播放带宽。
  5. 内容与推荐层:元数据服务 + 信息流推荐。
  6. 行为数据层:埋点流式处理,反馈给推荐与运营。

2.1 播放与上传分离

上传是「写路径」(低频大字节),播放是「读路径」(高频大字节),两条链路物理分离:

上传链路:客户端 → 上传网关 → 对象存储 → 转码队列 → CDN 源站
播放链路:客户端 → CDN 边缘节点(命中最优)→ 源站兜底

设计原则:
  - 播放绝不回源对象存储(太慢),由 CDN 缓存分发
  - 上传与播放走不同域名/网络路径,互不干扰
  - 转码是异步的:上传完成后立即可见「审核中」,转码完再可播

一句话:上传和播放的流量特性完全不同(上传少而大、播放多而热),必须用不同管道承载——上传走「对象存储 + 异步转码」,播放走「CDN 边缘缓存」,才不会互相挤占。

三、核心组件设计

3.1 上传管道

短视频上传动辄几十 MB,弱网下必须分片 + 断点续传:

分片上传:
  客户端把视频切成 1~2 MB 分片,逐片上送
  服务端记录已收分片(Redis 位图),返回进度
  断线 → 只续传缺失分片,不重传整个文件

流程:
  ① 申请上传凭证(鉴权 + 限流 + 分配 upload_id)
  ② 分片并发上送 → 校验 MD5
  ③ 全部收齐 → 合并 → 写入对象存储 → 触发转码
;; 伪代码:分片接收与合并状态
(defn receive-chunk [upload-id index data]
  (store-chunk! upload-id index data)          ; 临时分片存储
  (mark-received! upload-id index))            ; 记录已收

(defn complete-upload [upload-id]
  (when (all-received? upload-id)
    (merge-chunks! upload-id)                  ; 合并
    (move-to-object-store! upload-id)          ; 入对象存储
    (enqueue-transcode! upload-id)))           ; 触发转码

要点:分片大小与并发数是关键——12 MB 分片、48 路并发在弱网下体验最优;用位图记录已收分片,让断点续传从「重传整个文件」变成「只传缺失几片」。

3.2 转码流水线

原始视频要转成「多码率 + 分片」才能高效分发:

转码任务(异步队列驱动):
  ① 解析容器(MP4/MOV)→ 探测参数
  ② 转码成多档:标清(480p/800kbps) 高清(720p/2Mbps) 超清(1080p/4Mbps)
  ③ HLS 切片:按 4~6 秒切成 .ts 分片 + 生成 .m3u8 播放列表
  ④ 抽封面帧 + 生成缩略图
  ⑤ 写入对象存储(作为 CDN 源站)

并行与资源:
  转码是 CPU/GPU 密集,任务队列按视频时长加权分配
  热门内容优先转码(先出低清档可播),长尾内容排队
CREATE TABLE video (
  video_id     BIGINT PRIMARY KEY,
  author_id    BIGINT,
  title        VARCHAR(256),
  duration_sec INT,
  cover_url    VARCHAR(512),
  status       TINYINT,       -- 0转码中 1可播放 2审核拒绝 3已删除
  create_time  DATETIME
);

CREATE TABLE video_transcode (
  video_id   BIGINT,
  profile    TINYINT,         -- 1标清 2高清 3超清
  codec      VARCHAR(16),     -- H264 / H265
  url        VARCHAR(512),    -- 播放列表地址
  status     TINYINT,
  PRIMARY KEY (video_id, profile)
);

一句话:转码的产物不是「一个文件」而是「一组可选的档位 + 分片清单」——客户端按网络自适应选档、按分片渐进加载,这是视频「秒开 + 不卡顿」的基础。

3.3 CDN 分发与多码率

播放体验的核心是「让字节尽量近、尽量小」:

CDN 分级:
  边缘节点(用户所在城市)→ 区域节点 → 源站
  命中边缘缓存则本地发片,未命中向上回源并缓存
  HLS 分片天然适合 CDN:按 .ts 分片粒度缓存与失效

多码率自适应(ABR):
  播放列表包含多档码率 → 客户端按实时网速切换档位
  弱网切低清(不卡),强网切超清(清晰)
  首屏优化:先拉低清首分片 → 秒开 → 再升级

命中率优化:
  热门内容预热到边缘节点(开播前排片)
  分片 TTL 与内容热度联动:热内容长缓存,冷内容短缓存
;; 伪代码:播放地址选择(按档位 + 就近节点)
(defn play-url [video-id user]
  (let [profile (select-profile (network-status user))   ; 按网速选档
        nearest (cdn-locate (geo user))                  ; 就近边缘节点
        plist   (get-playlist video-id profile)]
    (redirect (str nearest plist))))

一句话:CDN 解决「远」、ABR 解决「快」——CDN 把内容搬到离用户一个城市的地方,ABR 让客户端按网速自动降档/升档,两者叠加才是「在任何网络下都刷得动」。

3.4 推荐与信息流

信息流是「下一屏刷什么」的决策,采用经典「召回 → 排序」两段式:

召回(从海量内容取几百条候选):
  - 基于用户兴趣标签:看过/点过的内容类目
  - 协同过滤:相似用户爱看的内容
  - 关注与热点:关注作者的新作品 + 全网热门
  - 多样性与探索:新内容池随机召回(防信息茧房)

排序(对候选打分):
  精排模型预估 pCTR / 播放时长 / 互动率
  特征:用户特征 × 内容特征 × 上下文(时间/地点/网络)
  重排:去重、打散(同作者/同类目不连续)、广告穿插
线上链路:
  用户打开 App → 请求 feed
  → 召回引擎取候选(几百条) → 特征查询 → 排序模型打分
  → 重排 → 返回 10~20 条 → 客户端预加载下一条
  目标:P99 < 100ms,预加载保证滑动零等待

一句话:推荐是「召回宽、排序准、重排稳」——召回保证候选多样不缺好内容,排序保证把最可能喜欢的内容放前面,重排保证用户不会看到千篇一律。

3.5 成本与扩展性治理

短视频最大的成本是带宽与转码算力,治理是关键:

带宽治理:
  - H265/AV1 编码:同清晰度码率降 30%~50%
  - 弱网/小屏自动降档:少传高码率字节
  - 热点内容边缘长缓存,减少回源

转码治理:
  - 长尾内容只转低清档(高清档按需转码)
  - 低质内容(低分辨率/过短)跳过超清档

存储治理:
  - 冷门内容下沉冷存储(对象存储低频档)
  - 删除/违规内容及时回收

算力扩展:
  转码集群按队列积压自动扩缩容
  高峰期削峰:优先保证热门内容转码完成
成本项主要手段降幅
分发带宽高压缩编码 + ABR 降档30%~50%
转码算力按热度分级转码 + 扩缩容显著
存储冷热分层 + 回收40%+

结论:短视频的盈利在「每千次播放的成本」,而成本的大头是带宽与转码——用更好的编码、更聪明的分档、更合理的缓存,把「让用户看好」的成本压到最低,是平台规模化后的核心竞争力。

四、深入权衡

4.1 转码档位数量

档位策略体验成本
三档(标/高/超清)覆盖大部分网络转码 + 存储适中
单档(统一高清)弱网体验差最低
七档 ABR全网络最优转码/存储最贵

结论:档位越多体验越好但成本越高——生产上「三档 + 客户端 ABR 切换」是主流平衡点;档位数量要跟着「网络分布」走,而非盲目加档。

4.2 热门内容分发 vs 长尾内容分发

热门内容:全量预热边缘节点 → 成本高但必须(承担大部分播放)
长尾内容:只存源站 + 按需回源 → 单次播放成本高但总量小
动态决策:按内容热度动态调整预热与缓存策略

一句话:内容分发也要「二八分层」——把缓存和预热的资源倾向头部内容,长尾内容按需分发,用动态热度策略让每一分带宽花在刀刃上。

4.3 个性化 vs 探索性

推荐全个性化会形成信息茧房,全探索又浪费流量:

个性化(主):基于历史行为的精排 → 满足「想看」
探索(辅):固定比例的随机召回 → 满足「惊喜」
权衡:约 80% 个性化 + 20% 探索是常见配比
冷启动:新用户无历史 → 以热门 + 类目引导为主

结论:推荐的体验不是「越准越好」而是「准中有新」——用探索配比兼顾时长与留存,是推荐系统在商业目标(时长/广告)与用户价值之间的长期博弈。

五、总结

短视频系统的骨架是「上传、转码、分发、推荐」四段式:上传用分片续传承载大字节写路径,转码流水线产出多码率 + HLS 分片,CDN 边缘分发加 ABR 自适应承载 300 亿次的播放读路径,推荐用「召回 + 排序 + 重排」决定每一屏内容。三个核心工程决策是:一是上传与播放链路分离,写读互不干扰;二是多码率 + 分片 + CDN,让视频在任何网络下秒开不卡;三是成本治理,用高压缩编码、分级转码、冷热分层把每千次播放的成本压到最低。最终,短视频系统以「创作者一条条传进来、用户亿万人刷出去」的高效循环,撑起一个平台的内容生态与商业价值。

继续阅读

探索更多技术文章

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

全部文章 返回首页

「design」更多文章

  1. 设计一个 API 网关系统
  2. 设计一个分布式缓存系统
  3. 设计一个日志检索系统