288 lines
8.0 KiB
Markdown
288 lines
8.0 KiB
Markdown
# 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 切片
|
||
|
||
### 请求流转
|
||
|
||
1. 前端上传视频到 `/api/upload`
|
||
2. 后端保存文件并返回 `file_id`
|
||
3. 前端使用 `file_id` 调用 `/api/tasks`
|
||
4. 后端将任务入队并返回 `task_id`
|
||
5. 前端轮询 `/api/tasks` 或 `/api/tasks/{task_id}`
|
||
|
||
### 异步任务流转
|
||
|
||
1. API 创建 `queued` 状态任务
|
||
2. worker 从队列取出任务,更新为 `processing`
|
||
3. FFmpeg 依次执行转码、封面、HLS
|
||
4. 成功则更新为 `completed`
|
||
5. 失败则更新为 `failed` 并记录错误
|
||
|
||
### 存储结构
|
||
|
||
- `storage/uploads/` 原始上传文件
|
||
- `storage/processed/` 处理后的 MP4
|
||
- `storage/covers/` 封面图
|
||
- `storage/hls/<task_id>/` HLS m3u8 与 ts 分片
|
||
|
||
### Mermaid 架构图
|
||
|
||
```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 - 项目目录结构
|
||
|
||
```text
|
||
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. 启动后端
|
||
|
||
```bash
|
||
cd backend
|
||
python3 -m venv .venv
|
||
source .venv/bin/activate
|
||
pip install -r requirements.txt
|
||
uvicorn app.main:app --reload --port 8000
|
||
```
|
||
|
||
如果本机没有 `python3-venv`,也可以直接:
|
||
|
||
```bash
|
||
cd backend
|
||
python3 -m pip install --user -r requirements.txt
|
||
python3 -m uvicorn app.main:app --reload --port 8000
|
||
```
|
||
|
||
### 2. 启动前端
|
||
|
||
```bash
|
||
cd frontend
|
||
npm install
|
||
npm run dev
|
||
```
|
||
|
||
默认会监听 `8451` 端口,并自动把 `/api`、`/media` 代理到 `http://localhost:8000`。
|
||
|
||
### 3. 打开页面
|
||
|
||
- 前端:http://localhost:8451
|
||
- 后端:http://localhost:8000
|
||
- 健康检查:http://localhost:8000/api/health
|
||
|
||
## Docker 启动
|
||
|
||
如果你希望在 Ubuntu 24.04 或其他装有 Docker 的环境中快速运行,直接使用:
|
||
|
||
```bash
|
||
docker compose up --build
|
||
```
|
||
|
||
启动后访问:
|
||
|
||
- 前端:http://localhost:8451
|
||
- 后端 API:http://localhost:8000
|
||
- 健康检查:http://localhost:8000/api/health
|
||
|
||
容器方案说明:
|
||
|
||
- 后端镜像基于 `python:3.12-slim`,容器内安装 `ffmpeg`
|
||
- 前端镜像采用 Node 构建 + Nginx 静态托管
|
||
- Nginx 会把 `/api` 和 `/media` 反向代理到后端容器
|
||
- `docker-compose.yml` 把宿主机 `./storage` 挂载到容器 `/app/storage`,所以上传文件和处理结果会保留
|
||
|
||
## API 说明
|
||
|
||
### `POST /api/upload`
|
||
|
||
上传视频文件,返回上传后的 `file_id`。
|
||
|
||
响应示例:
|
||
|
||
```json
|
||
{
|
||
"file_id": "f8d25e4c0e8b4b2b9b60f1a4d0e6a1df.mp4",
|
||
"original_name": "demo.mp4",
|
||
"file_url": "/media/uploads/f8d25e4c0e8b4b2b9b60f1a4d0e6a1df.mp4"
|
||
}
|
||
```
|
||
|
||
### `POST /api/tasks`
|
||
|
||
创建异步处理任务。
|
||
|
||
请求示例:
|
||
|
||
```json
|
||
{
|
||
"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 生成、拼接和音轨替换
|