7.9 KiB
7.9 KiB
VPlatform
一个面向“通信服务后端 / 音视频处理 / 视频编辑服务 / AIGC 流程”求职方向设计的最小可用项目。它实现了一个完整的音视频处理服务闭环:上传视频、创建异步处理任务、由内存队列中的 worker 调用 FFmpeg 执行处理、返回任务状态与结果,并在前端页面中展示处理产物。
Step 1 - 功能解读
这个项目解决什么问题
很多视频处理场景都不是同步接口能优雅承载的:上传文件后,转码、裁剪、封面抽帧、HLS 切片通常都要几秒到几十秒。如果全部放在请求线程内,会导致接口超时、资源竞争和糟糕的用户体验。
这个项目把问题缩成一个 1 天内能交付的最小闭环:
- 用户上传视频
- 用户提交处理任务
- 后端把任务放入内存队列
- worker 异步执行 FFmpeg 任务
- 前端轮询查看状态和结果
为什么贴合 JD
- 体现了通信服务后端常见的“任务异步化”和“状态可观测”
- 体现了音视频工程能力,真实调用 FFmpeg 而不是伪代码
- 体现了视频编辑服务常见能力:裁剪、转码、封面、HLS
- 体现了 AIGC/媒体流水线常见的 pipeline 思维
- 体现了调度系统最小形态:队列、worker、状态、日志
为什么一天内能完成
- 不引入 Redis、MySQL、对象存储等重基础设施
- 任务队列使用内存
Queue - 文件存储使用本地文件系统
- 后端选 FastAPI,前端选 React + Vite,开发速度快
- 核心亮点集中在“处理链路真实可跑通”
Step 2 - 技术选型
Frontend
React + Vite- 原因:启动快、代码量小、适合快速搭建可展示页面
Backend
Python FastAPI- 原因:接口编写快,文件上传和 JSON API 处理顺手,和 FFmpeg 命令行集成成本低
Task Model
内存队列 + 后台 worker 线程- 原因:足够展示异步处理模型,不需要为了 demo 引入 Redis / Celery
Media Processing
FFmpeg- 原因:真实工业标准工具,能直接体现音视频处理能力
Storage
本地文件系统- 原因:最容易跑通,便于 GitHub demo 和本地展示
Step 3 - 架构设计
模块划分
- 前端页面:上传文件、创建任务、轮询状态、展示结果
- FastAPI 接口层:上传接口、创建任务接口、任务查询接口
- TaskManager:任务元数据管理、状态维护、队列分发
- Worker:从队列消费任务,调用 FFmpeg 执行媒体处理
- 本地存储:保存原始文件、转码结果、封面图、HLS 切片
请求流转
- 前端上传视频到
/api/upload - 后端保存文件并返回
file_id - 前端使用
file_id调用/api/tasks - 后端将任务入队并返回
task_id - 前端轮询
/api/tasks或/api/tasks/{task_id}
异步任务流转
- API 创建
queued状态任务 - worker 从队列取出任务,更新为
processing - FFmpeg 依次执行转码、封面、HLS
- 成功则更新为
completed - 失败则更新为
failed并记录错误
存储结构
storage/uploads/原始上传文件storage/processed/处理后的 MP4storage/covers/封面图storage/hls/<task_id>/HLS m3u8 与 ts 分片
Mermaid 架构图
flowchart LR
A[React Frontend] -->|上传视频| B[FastAPI Upload API]
A -->|创建任务| C[FastAPI Task API]
C --> D[In-Memory Queue]
D --> E[Worker Thread]
E --> F[FFmpeg Pipeline]
F --> G[Local Storage]
A -->|轮询状态| C
C -->|返回状态/结果| A
G -->|静态文件访问| A
Step 4 - 分阶段计划
- 第 1 小时:设计接口、目录结构、任务模型
- 第 2 小时:完成 FastAPI 文件上传和任务查询接口
- 第 3 小时:实现内存队列和 worker
- 第 4 小时:接入 FFmpeg 转码、封面、HLS
- 第 5 小时:搭 React 页面,打通上传和轮询
- 第 6 小时:联调、异常处理、README 收尾
Step 5 - 项目目录结构
vplatform/
├── backend/
│ ├── app/
│ │ ├── services/
│ │ │ ├── media.py
│ │ │ ├── storage.py
│ │ │ └── tasks.py
│ │ ├── __init__.py
│ │ ├── config.py
│ │ ├── main.py
│ │ └── schemas.py
│ ├── Dockerfile
│ └── requirements.txt
├── frontend/
│ ├── src/
│ │ ├── App.jsx
│ │ ├── main.jsx
│ │ └── styles.css
│ ├── Dockerfile
│ ├── index.html
│ ├── nginx.conf
│ ├── package.json
│ └── vite.config.js
├── storage/
│ ├── covers/
│ ├── hls/
│ ├── processed/
│ └── uploads/
├── .dockerignore
├── .gitignore
├── README.md
├── docker-compose.yml
└── prompt.md
功能列表
- 上传视频文件
- 创建异步音视频处理任务
- 任务状态查询:
queued / processing / completed / failed - 视频裁剪前 N 秒
- MP4 转码并叠加简单文字水印
- 封面图抽帧
- HLS 切片输出
- 前端任务看板和结果展示
快速启动
1. 启动后端
cd backend
python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
uvicorn app.main:app --reload --port 8000
如果本机没有 python3-venv,也可以直接:
cd backend
python3 -m pip install --user -r requirements.txt
python3 -m uvicorn app.main:app --reload --port 8000
2. 启动前端
cd frontend
npm install
npm run dev
3. 打开页面
Docker 启动
如果你希望在 Ubuntu 24.04 或其他装有 Docker 的环境中快速运行,直接使用:
docker compose up --build
启动后访问:
容器方案说明:
- 后端镜像基于
python:3.12-slim,容器内安装ffmpeg - 前端镜像采用 Node 构建 + Nginx 静态托管
- Nginx 会把
/api和/media反向代理到后端容器 docker-compose.yml把宿主机./storage挂载到容器/app/storage,所以上传文件和处理结果会保留
API 说明
POST /api/upload
上传视频文件,返回上传后的 file_id。
响应示例:
{
"file_id": "f8d25e4c0e8b4b2b9b60f1a4d0e6a1df.mp4",
"original_name": "demo.mp4",
"file_url": "/media/uploads/f8d25e4c0e8b4b2b9b60f1a4d0e6a1df.mp4"
}
POST /api/tasks
创建异步处理任务。
请求示例:
{
"file_id": "f8d25e4c0e8b4b2b9b60f1a4d0e6a1df.mp4",
"clip_seconds": 8,
"transcode_mp4": true,
"generate_cover": true,
"generate_hls": true,
"watermark_text": "VPlatform Demo"
}
GET /api/tasks
获取全部任务列表,用于前端轮询。
GET /api/tasks/{task_id}
获取单个任务详情。
页面预览说明
- 顶部 Hero 区展示项目定位和技术栈
- 左侧面板上传视频
- 右侧面板配置处理参数并提交异步任务
- 底部任务看板实时展示状态、日志、转码视频、封面图和 HLS 链接
项目亮点
- 用最小成本演示了“上传 -> 入队 -> worker -> FFmpeg -> 结果回查”的完整链路
- 没有停留在概念层,能真实跑出 MP4、封面图和 HLS 文件
- 结构足够清晰,后续可自然扩展到 Redis、Celery、对象存储和告警系统
- 非常适合写进简历,能覆盖后端、音视频、异步任务和前后端联调能力
后续优化方向
- 使用 Redis + Celery / RQ 替换内存队列
- 接入 MySQL / PostgreSQL 持久化任务状态
- 上传到对象存储而不是本地磁盘
- 增加任务超时、重试和告警
- 接入 WebSocket 推送任务状态,替代前端轮询
- 支持更多处理能力,例如字幕叠加、GIF 生成、拼接和音轨替换