# 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//` 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,可以直接用项目根目录下的脚本把前后端挂到后台: ```bash chmod +x start.sh stop.sh status.sh ./start.sh ``` 脚本会做这些事: - 后台启动 FastAPI,默认端口 `8000` - 后台启动 Vite,默认端口 `8451` - 把 PID 写到 `.run/` - 把日志写到 `logs/` 常用命令: ```bash ./status.sh ./stop.sh tail -f logs/backend.log tail -f logs/frontend.log ``` 如果你要改端口,可以在启动前传环境变量,前端代理也会自动跟着后端端口变化: ```bash BACKEND_PORT=9000 FRONTEND_PORT=8451 ./start.sh ``` ## 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 生成、拼接和音轨替换