Skip to content

About

个人自托管的 AI 短视频生产工作站:LLM 写稿 → MoneyPrinterTurbo 出片 → ffprobe 质检 → 人工审核。FastAPI + Vue 3 + SQLite,Docker Compose 部署。

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Repository files navigation

热点工厂 HotFactory

个人自托管的 AI 短视频生产工作站。架构依据见 docs/design/hot-factory-overview-design.md v1.0(现行架构单一真源);运行与出片见 docs/runbook/weekend-slice.md;进度与验证见 docs/progress/PROCESS.md。

当前状态:第一阶段工程骨架已可运行,真实 MoneyPrinterTurbo 出片已验证。 已实现「创建任务 → Worker 原子认领 → 脚本生成 → 视频引擎合成 → ffprobe 基础质检 → 待人工审核 → 前端轮询进度与预览」的完整垂直链路。发布、多平台、热点官方 API 均未实现(按三阶段路线)。

不要重复造轮子(硬约束):配音、字幕、素材、异步任务与进度、视频合成全部由 MoneyPrinterTurbo 提供,本项目只透传配置、翻译状态、做质检。没有 providers/tts/、没有自研字幕、没有第二套进度体系。新增模块前先查上游是否已提供,详见架构文档第 3 章。

能力 由谁提供
结构化脚本(落盘、可手改、可复用) 本项目 providers/llm(DeepSeek / fake)
配音 voice_name、字幕 subtitle_enabled、素材 video_source MoneyPrinterTurbo,本项目只透传配置项
异步任务 task_id 与 0~100 进度 MoneyPrinterTurbo,本项目只做 engine_job_id 映射与状态翻译
视频合成 / 转码 MoneyPrinterTurbo + FFmpeg
任务持久化、ffprobe 质检、预览、审核 本项目(引擎不产出质检报告)

目录

frontend/          Vue 3 + TS + Vite + Element Plus
backend/app/
  api/             FastAPI 路由
  core/            配置
  models/          SQLAlchemy 模型与 SQLite 连接(WAL + busy_timeout)
  schemas/         接口契约
  services/        任务生命周期
  providers/       llm / video / qc —— 外部能力适配(不设 tts)
  workers/         Worker 入口、流水线、批量出片 CLI
backend/tests/     pytest
config/            配置样例、topics 清单样例、本机 .env
data/              数据库、脚本、素材、成片(不进 Git)
docs/
  design/          架构单一真源(现行 v1.0)
  runbook/         运行与出片手册(命令、配置、降级矩阵)
  progress/        进度台账与废弃决策留痕
scripts/           Windows 一键启动脚本
docker-compose.yml 目标部署形态

根目录只放门面、协作规范与部署入口三类文件,文档一律进 docs/ 子目录分类存放:

分类 位置
门面 / 法律 README.md、LICENSE、THIRD-PARTY-NOTICES.md
AI 协作规范 AGENTS.md、CLAUDE.md(规范本体在全局,不随仓库分发)
部署与启动 docker-compose.yml、.gitignore、config/、start.bat
文档 docs/design/、docs/runbook/、docs/progress/

快速开始 · Windows 一键启动

双击根目录的 start.bat(或在终端执行),从零到能点出片:

start.bat

脚本按顺序做五件事:检查 Python / Node / FFmpeg 与端口 → 缺 config/.env 就由 env.example 生成(默认 fake + mock,不需要任何 Key)→ 前端产物过期就重新构建 → 起后台 Worker → 起 FastAPI 并自动开浏览器。

  • 访问地址 http://127.0.0.1:8000:前端由 FastAPI 托管,单端口,不用另开终端;接口文档在 /docs。
  • 停止:在启动窗口按 Ctrl+C,Worker 会被一起收掉,不留孤儿进程。
  • 参数:start.bat -WithEngine(video=mpt 时顺带把 MoneyPrinterTurbo 起在 8080)、-Dev(前端 vite 热更新,访问 5173)、-Rebuild(强制重建前端)、-Port 8010(换端口)、-SkipWorker(只起 Web)、-NoBrowser、-Help。
  • 日志:data/logs/worker.log;-WithEngine 时另有 data/logs/mpt.log;-Dev 时另有 data/logs/vite.log。
  • 首次运行会自动装 backend/.venv 与 frontend/node_modules(需要几分钟,之后秒起)。
  • 改了 config/.env 或后端代码之后:直接重跑 start.bat。Worker 的配置与代码都是启动那一刻读进内存的,所以脚本默认接管:没有任务在跑时,杀掉遗留 Worker 重启一个;有任务正在跑时保留它并提示你等跑完再重跑。不存在「复用一个别人起的旧 Worker」这种情况。
  • 要出真片:把 config/.env 的 HF_VIDEO_PROVIDER 改成 mpt,再 start.bat -WithEngine——脚本会先等引擎在 8080 就绪再起 Web,退出时把引擎一起收掉;引擎侧配置(本地素材、Edge 字幕)见 docs/runbook/weekend-slice.md 第 2 章。
  • 不配 LLM 也能出片:HF_LLM_PROVIDER=fake 会把主题套进 6 段通用口播稿;想文案对题,就在页面「可选:粘贴自己的口播稿」里填稿,填了就完全跳过 LLM。
  • 素材在页面直接传:点「上传图片 / 视频」选文件即可(jpg/png/bmp/mp4/mov/avi/mkv/webm,图片 ≤20MB、视频 ≤200MB)。传上去的会作为本条任务的素材,只使用你选中的这些,引擎素材库里别的文件(比如测试彩条)不会混进成片;一个都不传才会用引擎库全集。
  • 成片按主题命名:落到 data/videos/{任务ID}/{主题}.mp4,页面任务列表也有「主题」和「成片」两列,不用再靠 task_id 猜哪条是自己的。
  • 成片时长与配音语速:主题框下面两个下拉框,每条任务单独设。时长 15 / 30 / 45 / 60 秒或「不限(按稿件)」,语速 0.8x ~ 2.0x。引擎没有总时长参数——成片多长完全由配音多长决定,所以选 30 秒 = 把稿件裁到约「30 × 4.5 × 语速」字(中文口播实测 4.5 字/秒),裁在完整句子上,不会半句话断掉。稿子框下面会实时显示「当前多少字 ≈ 多少秒」,超了会提示将被截断。

已实测(2026-11-13,Windows 11 + PowerShell 7):零凭据模式下点一次生成 → Worker 原子认领 → mock 引擎出片 5s / 1080×1920 / H.264 + AAC → ffprobe 质检 6 项全过 → 状态 WAITING_REVIEW,全程约 2 秒;-Dev 模式下 vite 页面与 /api 代理均验证可用。

快速开始 · 一条命令批量出片(周末主用)

不另写第二套流水线:批量 CLI 只是「批量入队 + 汇总报告」的薄封装,复用同一张 task 表、同一条 workers/pipeline.py、同一套 providers 和 ffprobe 质检,避免两套流水线各自漂移。

cd backend

# 单主题
.venv/Scripts/python.exe -m app.workers.cli --subject "一杯手冲咖啡的冲泡过程"

# 批量:先改 config/topics.example.json
.venv/Scripts/python.exe -m app.workers.cli --topics ../config/topics.example.json \
  --report ../data/videos/batch-report.json

# 改词不重新调 LLM:复用已落盘脚本,或直接用手写口播稿
.venv/Scripts/python.exe -m app.workers.cli --topics ../config/topics.example.json \
  --from-script ../data/scripts/<task_id>/script.json
  • 主题清单支持 ["主题A", "主题B"] 或 {"topics": [{"topic": "...", "script": "...", "voice_name": "..."}]};条目里填 script 即跳过 DeepSeek。
  • 每条任务一个 data/videos/{task_id}/ 目录,不覆盖历史成片。
  • 报告含 status / file_path / qc_passed / 错误信息;--limit N 只跑前 N 条;有任务失败时退出码为 1。
  • 该命令会把队列中所有 PENDING 任务跑完。若 Worker 正在运行,先停 Worker,避免进度归属分散(认领是原子的,不会重复执行)。
  • 引擎侧分段排错用 MoneyPrinterTurbo 自带的 CLI --stop-at script|audio|video,本项目不重复实现。

已实测(2026-11-13,真实 ffmpeg / ffprobe,无 API Key):3 条主题一次跑完,3/3 WAITING_REVIEW,产出 3 条 1080×1920 / H.264 + AAC MP4,质检全项通过,报告见 data/cli-smoke/batch-report.json。注意这是 mock 引擎的测试图,只证明一键链路可复现;真成片要切到 MoneyPrinterTurbo。

快速开始 · 零凭据验证

不需要 Docker、不需要任何 API Key、不需要 MoneyPrinterTurbo,就能验证整条链路。

# 1. 后端依赖(Python 3.12+,本机已验证 3.13)
cd backend
uv venv .venv --python 3.13
uv pip install -r requirements.txt

# 2. 配置(复制样例,默认就是 fake + mock)
cp ../config/env.example ../config/.env

# 3. 跑测试
.venv/Scripts/python.exe -m pytest

# 4. 启动 Web 与 Worker(两个终端,或用 run-dev.sh 一次起)
.venv/Scripts/python.exe -m uvicorn app.main:app --port 8000
.venv/Scripts/python.exe -m app.workers          # 另一个终端

# 5. 创建任务并轮询
curl -X POST http://127.0.0.1:8000/api/tasks -H "Content-Type: application/json" \
  -d '{"topic":"一杯手冲咖啡的冲泡过程"}'
curl http://127.0.0.1:8000/api/tasks/<上一步返回的 id>

前端:

cd frontend
npm install
npm run dev          # http://127.0.0.1:5173,/api 代理到 8000
# 或者:npm run build 后直接访问 http://127.0.0.1:8000(由 FastAPI 托管 dist)

快速开始 · 接真实 MoneyPrinterTurbo

  1. 安装并启动 8080 API(已在本机实测):
python -m pip install mpt                      # 官方包 mpt 1.3.10,harry0703 维护,Python ≥ 3.11

# 注意:mpt CLI 只有 cli / webui 两个子命令,不会启动 API。
# 8080 是包内的 FastAPI 应用 app.asgi:app:
python -m uvicorn app.asgi:app --host 127.0.0.1 --port 8080
# API 文档: http://127.0.0.1:8080/docs     OpenAPI: /openapi.json

mpt webui                                      # 可选,WebUI 8501 人工试片

PyPI 上另有旧名称发行包 MoneyPrinterTurbo,不作为安装依据。api_key 默认空(免认证),8080 只监听本机、不得暴露公网;CORS 默认同源,服务端调用不带 Origin 不受限。

  1. 准备素材与引擎配置(没有 Pexels Key 时必做):
  • 把 3~10 张图片或视频片段放到 MPT 自己的 storage/local_videos/ 目录,Windows 下通常是 %LOCALAPPDATA%\MoneyPrinterTurbo\storage\local_videos\;或调引擎 POST /api/v1/video_materials 上传。
  • 适配器会自动调 GET /api/v1/video_materials 取文件名并填进 video_materials,HotFactory 不扫描也不配置这个目录。
  • MPT 的 config.toml 里按需设 subtitle_provider = "edge"(别开 whisper,首跑要下 1.6~3 GB)、LLM Key(填了 video_script 就不需要)、ffmpeg_path。包内自带中文字体 STHeitiMedium.ttc,字幕字体不是阻塞。
  • 配音与字幕是引擎能力,本项目的 HF_MPT_* 只透传参数,不生成音频或字幕文件。
  1. 实测契约要点(完整表见架构文档第 4 章):统一响应信封 {"status","data","message"};任务 state 是 FAILED=-1 / COMPLETE=1 / PROCESSING=4(不是网上流传的 0/1/2/3);videos 返回 /tasks/<id>/final-1.mp4 相对 URI,由适配器从引擎 HTTP 下载;video_source=local 时必须带 video_materials。这三处已用契约测试锁定。

  2. 改 config/.env:

HF_LLM_PROVIDER=deepseek
HF_DEEPSEEK_API_KEY=你的Key
HF_DEEPSEEK_MODEL=官方当前可用的模型标识
HF_VIDEO_PROVIDER=mpt
HF_MPT_API_BASE=http://127.0.0.1:8080
HF_MPT_VIDEO_SOURCE=local
HF_MPT_STORAGE_DIR=            # 引擎返回相对路径时填其 storage/tasks 根目录
  1. 重启 Web 与 Worker。Worker 会把 MPT 的 task_id 存进 video_task.engine_job_id,把 state / progress 翻译成本系统任务状态,不重复实现一套进度体系。

端到端实测(2026-11-13,本机,已通过)

用同一条批量命令接真实 MPT,没有 DeepSeek Key、没有 Pexels Key(fake 脚本 + 3 张本地图):

cd backend
HF_LLM_PROVIDER=fake HF_VIDEO_PROVIDER=mpt HF_MPT_API_BASE=http://127.0.0.1:8080 \
HF_MPT_VIDEO_SOURCE=local HF_MPT_POLL_INTERVAL=3 \
  .venv/Scripts/python.exe -m app.workers.cli \
  --subject "一杯手冲咖啡的冲泡过程" --report ../data/mpt-smoke/report.json

结果:WAITING_REVIEW / 100 / qc=PASS,耗时 5 分 26 秒,成片 39.6 秒 / 1080×1920 / H.264 + AAC / 30fps / 7.2 MB。引擎侧日志确认 Edge TTS 生成 39 秒中文配音、Edge 时间戳字幕、3 张本地图预处理成 zoom 片段、合并 40 秒、最终烧字幕渲染;抽帧确认中文字幕已烧录且无乱码。

画面用的是 ffmpeg 生成的测试彩条,只证明链路可用。把 MPT 的 storage/local_videos/ 换成自己的图片、在 config/.env 填 DeepSeek Key,即可出真正的内容片。当前长句字幕换行处略挤,可调 font_size / subtitle_position。

降级矩阵

缺什么 怎么办
抖音热点 Scope 一等公民降级:POST /api/tasks {"topic": ...} 或 CLI --topics 主题清单就是手工热点源;不为将来才可能拿到的官方 API 提前写 HotSource 抽象
DeepSeek Key HF_LLM_PROVIDER=fake,或条目里填 script 用手写口播稿,或 --from-script 复用落盘脚本
Pexels / Pixabay Key HF_MPT_VIDEO_SOURCE=local,素材放 MPT 自己的 storage/local_videos/,文件名由引擎 GET /api/v1/video_materials 提供
MPT 未启动 HF_VIDEO_PROVIDER=mock,用测试图 MP4 验证链路与质检
ffmpeg 已装则无需处理;未装则 ffprobe 质检会报明确错误,不会静默通过
中文字幕异常 关闭 subtitle_enabled 保底出片
引擎半途失败 用 MPT 自带 --stop-at 分段跑,复用已生成的脚本和音频

接口一览

Method Path 说明
POST /api/tasks 创建视频任务,立即返回 id
GET /api/tasks/{id} 轮询状态、进度、阶段、错误和结果
GET /api/tasks 最近任务列表
POST /api/tasks/{id}/retry / cancel / approve 重试 / 取消 / 审核通过
GET /api/videos 成片列表(可按 task_id 过滤)
GET /api/videos/{id}/stream 视频预览(限制在 data/videos/ 内)
POST /api/materials 上传图片 / 视频素材(multipart file),转发引擎素材接口
GET /api/materials 当前可用素材清单
GET /api/health 健康检查
GET /docs FastAPI 自动生成的接口文档

任务状态机:PENDING → SCRIPTING → GENERATING → QC → WAITING_REVIEW → APPROVED,异常 FAILED / CANCELLED。

测试

cd backend && .venv/Scripts/python.exe -m pytest     # 50 个用例
cd frontend && npm run typecheck && npm run build

已知限制

  • 基础质检只覆盖元数据(流、时长、分辨率、大小);黑屏 / 静音语义检测未实现。
  • 主题靠手工输入(CLI 主题清单 / API topic 字段),没有官方热点 API,也没有自动选题评分;等抖音 Scope 到位再引入 HotSource 抽象。
  • 没有用户认证,管理接口只应监听本机或受保护网络;MPT 的 8080 不要暴露公网。
  • 前端全量引入 Element Plus,构建产物约 1 MB,后续按需引入或分包。
  • docker-compose.yml 目前只编排 Web + Worker 两个自有服务;本机未安装 Docker,第三个程序 MPT 按上游文档单独启动并通过 HF_MPT_API_BASE 接入。待 Docker 就绪且固定上游镜像 digest 后再编入。
  • 本机已验证环境:Python 3.13.14 / uv 0.12.5 / Node 22.22.2 / FFmpeg 9.0.1 / Windows + Git Bash;Docker 未安装。

许可与依赖

本项目代码以 MIT License 发布。第三方组件版本、许可证与来源记录在 THIRD-PARTY-NOTICES.md;接入前需按架构文档第 11.3 节复核上游 LICENSE 与服务条款。

About

个人自托管的 AI 短视频生产工作站:LLM 写稿 → MoneyPrinterTurbo 出片 → ffprobe 质检 → 人工审核。FastAPI + Vue 3 + SQLite,Docker Compose 部署。

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages