视频上传、转码、切片、封面生成系统应该怎么设计?

视频上传转码系统应采用异步处理:上传完成后先校验文件,再由任务队列执行转码、HLS 切片和封面生成,产物检查通过才允许发布。设计重点是状态可追踪、失败可重试、任务不重复生效以及文件与数据库一致。原片和输出应按版本隔离,不能让一次失败的重转码覆盖正在正常播放的内容。

上传完成、转码完成、发布完成是三个状态

把上传、转码和发布塞进一个网页请求,会受到请求超时、客户端断线和工作进程重启影响。更稳妥的边界是:Web 接口负责鉴权和创建任务,处理节点负责媒体计算,发布步骤负责确认可用版本。本文适用于自有或已授权内容的点播处理。

待上传 → 上传中 → 校验中 → 排队中
                           ↓
                        转码中
                           ↓
                  产物校验 → 待发布 → 已发布
                           ↓
                     失败 / 等待重试

每个状态都应带更新时间与原因,页面进度不能只依赖浏览器内存。任务失败后显示可操作的信息,例如“输入文件损坏”“存储上传失败”或“超出处理资源限制”,而不是统一显示“系统繁忙”。

上传:先确认文件完整,再交给处理节点

大文件可采用分片上传或由服务端授权客户端直传对象存储。后台只为当前用户分配允许的对象键、权限和有效期;上传完成通知还要由服务端核对实际对象、大小和校验信息,不能直接相信浏览器传来的成功标记。预签名地址具有访问能力,应避免进入公开页面、完整日志或分析事件。S3 预签名 URL 说明

以 S3 为例,分片上传包含创建、上传分片和完成合并的步骤,并可使用校验和检测完整性。不要把分片上传对象的 ETag 一概当作整个文件的 MD5。中断后未完成的分片也需要生命周期清理。S3 分片上传说明未完成分片清理

文件扩展名和客户端 MIME 类型只能作线索。处理前还要检查真实媒体流、时长、分辨率、轨道数量与文件大小,并设置合理限制,防止一个异常输入占满处理资源。

数据库和队列如何避免重复执行?

记录建议保存作用
视频记录业务标识、所有者、当前发布版本、状态控制用户实际看到的内容
输入记录对象键、校验信息、大小、探测结果确定转码输入是哪一个版本
任务记录任务 ID、模板版本、尝试次数、锁定时间、错误码追踪处理和恢复过程
产物记录清晰度、清单地址、封面、校验状态通过验证后再发布

队列消息可能被重复投递,因此不能仅依赖“发送过一次”。可以用“输入版本 + 编码模板版本”形成任务唯一约束,处理节点领取任务时原子更新状态或取得租约,发布时确认任务版本仍然有效。数据库状态提交与队列发送之间也要有可恢复机制,例如可重发的任务记录与定期扫描,而不是发送失败就永远丢失任务。

工作进程重启后,超过租约时间的任务可重新领取;旧进程迟到提交时必须验证任务归属与版本。已发布的结果被重复回调时,应返回已有结果,不能再次创建重复业务记录。

FFmpeg 示例:先让一个受控样本跑通

下面是 Linux/macOS 终端的演示命令,输入为本地 input.mp4,输出到新建测试目录。使用前确认 FFmpeg 包含 libx264 与 AAC 编码能力。示例保留第一路视频和可选的第一路音频,不包含字幕、多清晰度或生产环境的资源限制。

mkdir -p output/job-demo

ffprobe -v error -show_format -show_streams \
  -of json input.mp4

ffmpeg -nostdin -i input.mp4 \
  -map 0:v:0 -map '0:a:0?' \
  -c:v libx264 -pix_fmt yuv420p -crf 23 -preset medium \
  -force_key_frames 'expr:gte(t,n_forced*6)' \
  -c:a aac -b:a 128k \
  -f hls -hls_time 6 -hls_playlist_type vod \
  -hls_segment_filename 'output/job-demo/segment_%05d.ts' \
  output/job-demo/index.m3u8

ffmpeg -nostdin -i input.mp4 -map 0:v:0 \
  -frames:v 1 -update 1 output/job-demo/poster.jpg

ffprobe 可输出媒体格式与流信息;HLS 输出选项控制清单和切片,强制关键帧用于让分段目标更可控。示例不是任意素材都适用的万能模板:奇数尺寸、HDR、旋转元数据、特殊帧率等输入需要另外的预处理与验证。封面命令取首帧,正式系统应提供候选帧或人工选择,避免片头黑场。ffprobe 文档FFmpeg 参数说明HLS 输出选项

业务程序应以参数数组启动进程,不把用户文件名直接拼接成 shell 命令。输入来源、可访问协议、处理时长、内存、CPU 和临时磁盘都应有明确边界;转码节点无需持有数据库管理权限或整桶删除权限。

产物发布与清理要有先后顺序

  1. 每次任务写入独立的暂存目录或对象前缀,重新处理时不覆盖在线版本。
  2. 检查退出码、输出文件、播放时长、音画同步和清单引用;退出码为零也不代表业务样本完全符合要求。
  3. 先上传媒体切片与封面,再上传引用它们的清单,核对存储中的文件完整性。
  4. 从实际分发地址抽检播放,验证通过后原子切换数据库中的已发布版本。
  5. 保留旧版本至约定观察期结束,之后按数据库引用与生命周期策略清理,避免误删仍被播放的对象。

发布后的列表页只读取已发布版本。处理中可以在后台显示进度,但不要提前把未完成的 m3u8 暴露成可播放内容。取消或下架任务时也要有版本校验,防止后台已取消的任务稍后重新把视频发布出来。

失败恢复:区分能重试与必须修复的错误

错误类型处理方式需要保留的证据
短暂网络或存储失败有限次数退避重试,使用同一任务标识状态码、时间、对象键的安全摘要
媒体损坏或不支持的编码停止自动重试,提示重新上传或调整处理模板探测结果和脱敏错误摘要
磁盘、内存或执行时限不足暂停领取新任务,调整资源后恢复资源峰值与失败阶段
进程消失或节点重启租约到期后重新领取,拒绝旧任务迟到发布任务尝试次数和版本

重试要有上限和可见的终止状态。先监控队列等待时长、处理耗时、失败率、每分钟视频的计算消耗和临时存储占用,再决定扩容;无上限重试会把一个坏文件变成持续占用资源的任务。

何时需要定制开发,以及如何验收?

需要批量上传、多用户隔离、多个编码模板、断点恢复、人工审核或接入现有后台时,通常需要设计业务流程,而不只是调用一条 FFmpeg 命令。视频处理流水线定制可按输入类型、日处理时长、并发要求与存储环境评估开发和运行成本。

  • 相同任务重复回调、重复投递,不产生重复发布和额外业务记录。
  • 上传中断、处理节点重启、存储短暂失败后,都能恢复或明确结束。
  • 无音轨、竖屏、长片、损坏文件和大尺寸输入均有可预期结果。
  • 重新转码失败时旧版本仍可播放;取消任务后不会迟到发布。
  • 后台能定位失败步骤,日志中没有上传凭证、访问 Token 或客户隐私。

视频处理系统常见问题

视频上传成功为什么还不能播放?

上传只说明输入文件已送达,后续还需要校验、转码、切片、上传产物和发布验证。页面应明确显示当前处理状态。

使用 GPU 就一定比 CPU 更合适吗?

不一定。需要比较输入格式、画质目标、吞吐、设备成本和编码支持,用实际样本测试后决定。

转码完成后可以立即删除原片吗?

应按内容授权、业务留存和重处理需求确定。删除原片会减少重新编码和修复能力,不能由单次任务成功自动决定。

参考与核对依据

把下一步说清楚。

带上现状、目标与需要解决的问题,先确认实施范围和验收方式。