DEPLOYMENT.md 12 KB

部署文档

文本转视频生成流水线的部署与运行说明。项目以容器化、服务化为重心:Docker Compose 一键起服务,CLI / HTTP / WebUI 共享同一套配置与统一输出目录。


1. 架构概览

                         ┌──────────────────────────────┐
   浏览器 (WebUI) ──────► │  Next.js Web 服务 (端口 3000)  │
   HTTP /api/render ────► │  apps/web                     │
                         └───────────────┬──────────────┘
                                         │ spawn 子进程
                                         ▼
                         ┌──────────────────────────────┐
                         │  CLI  apps/cli/dist/index.js   │
                         │  runPipeline (7 阶段)          │
                         │   parse → tts → assets →       │
                         │   compose → render → export    │
                         │   → publish(可选)              │
                         └───────────────┬──────────────┘
                                         │
                ┌────────────────────────┼────────────────────────┐
                ▼                        ▼                        ▼
        统一输出目录                 阿里云 OSS              飞书 Webhook
  {output}/{模板}/{日期}/{文件}      (上传视频)            (推送结果/失败)
  • Web 服务(Next.js 15)提供 UI 与 HTTP API;渲染时 spawn 调用 CLI 子进程执行 runPipeline
  • CLIapps/cli)是流水线唯一入口;WebUI 与 HTTP 都复用它,因此 OSS 上传 / 飞书推送只在 CLI 进程内发生一次。
  • 统一输出目录:CLI / HTTP / WebUI 写入同一目录,按 {模板}/{ISO日期}/{文件名}.mp4 自动建子目录。
  • monorepo:pnpm workspaces + Turborepo(packages/shared|core|tts|templates|collectapps/cli|web)。

2. 前置要求

Docker 方式(推荐)

  • Docker 20+ 与 Docker Compose v2。

本地开发方式

  • Node.js 22、pnpm 10、ffmpeg。
  • 渲染依赖 headless Chrome:首次运行 Remotion 会自动下载(@remotion/renderer),或设置 PUPPETEER_EXECUTABLE_PATH 指向系统 Chrome。

3. 快速开始:Docker Compose(推荐)

# 1. 准备配置(密钥 / 端点)
cp .env.example .env
#   编辑 .env,至少填入 LLM、TTS 的 key;按需开启 OSS / 飞书

# 2. 构建并启动
docker compose up --build -d

# 3. 访问
#    WebUI:   http://localhost:13000
#    (PORT 可在 .env 中覆盖,默认 13000 → 容器 3000)

docker compose up 会自动读取仓库根目录的 .env,把其中的变量替换进容器的 environment:(见 docker-compose.yml)。因此密钥放在宿主机 .env,不需要把 .env 打进镜像

停止 / 查看日志 / 重建:

docker compose logs -f pipeline     # 跟随日志
docker compose down                 # 停止
docker compose up --build -d        # 改完代码后重新构建

容器内:

  • Web 服务运行于 /app/apps/web,监听 3000
  • 输出目录 /app/output 挂载到宿主机 ./output(视频落盘可见、可清理)。
  • 任务元数据(jobs.json)保存在 docker volume pipeline-jobs/tmp/pipeline-jobs)。

4. 配置说明

配置分两层:.env(密钥 / 端点) + config/default.yaml(业务参数)。CLI 读取顺序:--config 参数 → pipeline.config.yamlconfig/default.yaml;密钥统一走环境变量。

4.1 环境变量(.env

变量 必填 说明
OPENAI_API_KEY / OPENAI_BASE_URL 是* LLM(OpenAI 兼容端点:DeepSeek / Qwen / GLM 等)。*用结构化 JSON + --skip-llm 时可省
OPENAI_TTS_API_KEY / OPENAI_TTS_BASE_URL 是* 默认 TTS provider。*--no-tts 时可省
OPENAI_TTS_MODEL TTS 模型,默认 seed-tts-1.1
TTS_MAX_RETRIES TTS 请求失败重试次数(网络错误 / 429 / 5xx,指数退避),默认 3;0 关闭
FISH_AUDIO_API_KEY Fish Audio provider
MINIMAX_API_KEY / MINIMAX_GROUP_ID MiniMax provider
ELEVENLABS_API_KEY ElevenLabs provider
OUTPUT_DIR 统一输出目录;空则用 config.output.dir(默认 ./output)。Docker 内固定 /app/output
OUTPUT_RETENTION_DAYS 缓存保留天数,默认 30;0 关闭自动清理
OSS_REGION OSS_BUCKET OSS_ACCESS_KEY_ID OSS_ACCESS_KEY_SECRET 阿里云 OSS;四项齐全才启用上传
OSS_ENDPOINT OSS_PATH OSS_PUBLIC_DOMAIN OSS_SECURE OSS 自定义端点 / key 前缀 / 资源链接域名(如 CDN) / 是否 HTTPS
FEISHU_WEBHOOK_URL FEISHU_WEBHOOK_SECRET 飞书自定义机器人 webhook 及签名密钥
PORT 宿主机映射端口,默认 13000

也可在 WebUI Settings 页面填写并保存到 .env(敏感值自动脱敏显示)。

4.2 config/default.yaml

TTS provider 选择、模型、对齐(whisper)、模板配色、采集源(collect)、OSS/飞书的非敏感默认值(region/bucket/path 等)在此配置。详见文件内注释。


5. 输出目录与缓存清理

  • 布局{OUTPUT_DIR}/{模板名}/{YYYY-MM-DD(UTC)}/{模板}-{平台}-{jobId前8位}.mp4
    • 例:output/github-trending/2026-07-16/github-trending-bilibili-701832d4.mp4
  • 统一性:相对路径相对 monorepo 根解析,CLI 与 apps/web 落到同一物理目录;容器内为 /app/output
  • 自动清理:每次渲染启动时按 OUTPUT_RETENTION_DAYS(默认 30)扫描,删除 mtime 超过阈值的文件及随之变空的日期目录(best-effort,不影响渲染)。设 0 关闭。

6. 发布:OSS 与飞书

渲染完成后自动执行(可被 --no-publish / config.skipPublish 跳过):

场景 行为
上传 OSS 成功 推送飞书:✅ 视频生成成功 + OSS 资源链接
渲染成功但上传失败 推送飞书:⚠️ 已生成但上传失败 + 本地路径 + 错误(本地视频仍保留)
渲染本身失败 推送飞书:❌ 生成失败 + 错误信息
  • OSS 用 ali-oss 分片上传;资源链接优先用 OSS_PUBLIC_DOMAIN(CDN),否则用 bucket 默认域名。假定对象为公开读;若为私读需另行接签名 URL。
  • 飞书支持自定义机器人的签名校验FEISHU_WEBHOOK_SECRET),算法为 base64(HMAC-SHA256(key=timestamp+"\n"+secret, message=""))
  • 上传后的 OSS URL 会回填到导出文件(CLI 打印 oss: <url>;WebUI 任务详情页展示「OSS Links」)。

7. 本地开发(非 Docker)

pnpm install
pnpm build            # 构建所有包(含 apps/cli/dist、apps/web/.next)

# CLI 直接渲染
node apps/cli/dist/index.js render test/fixtures/sample-knowledge.json \
  -t knowledge -p bilibili --skip-llm --no-tts --no-publish

# WebUI 开发服务器(热更新)
cd apps/web && pnpm dev    # http://localhost:3000

常用命令:

pnpm typecheck       # 全包类型检查
pnpm lint            # 全包 lint
pnpm build           # 全量构建

8. CLI 用法

node apps/cli/dist/index.js render <input> -t <template> [options]
  • <input>:JSON / Markdown / 纯文本文件路径;或用 --source <name> 从采集源取数(如 github-trendinggithub-daily)。
  • -t/--templatenews|knowledge|opinion|marketing|github-trending(必填)。
  • -p/--platformbilibili|douyin-long|douyin-short|universal-16x9|universal-9x16,逗号分隔多平台。
  • -o/--output:输出目录(默认走 config.output.dir / ./output)。
  • --no-tts:跳过 TTS,生成静音视频(调试布局)。
  • --skip-llm:跳过 LLM,要求输入是合法 VideoInputSchema JSON。
  • --no-publish:跳过 OSS 上传与飞书推送。
  • --config:指定配置文件路径。

其它子命令:collectpreviewtemplatesvoicesinit--help 查看)。


9. HTTP API(服务化调用)

发起渲染

POST /api/render
Content-Type: application/json

{
  "input": {
    "template": "knowledge",
    "platforms": ["bilibili"],
    "ttsProvider": "openai-tts",
    "text": "<VideoInput JSON / Markdown / 纯文本>"
  },
  "options": { "noTts": false }
}
  • input.template(必填)、input.ttsProvider(必填)。
  • input.textinput.source 二选一;platforms 缺省为 ["bilibili"]
  • 采集源:input.source + input.sourceArgs(如 { "owner": "x", "repo": "y" })。

响应:{ "jobId": "<uuid>", "status": "started" }

轮询任务 / 下载

GET /api/jobs/<jobId>            # 返回任务状态、outputFiles、ossUrls、publishError
GET /api/jobs                    # 任务列表
GET /api/download?file=<绝对路径>&download=1   # 下载视频(仅允许统一输出目录或任务目录内文件)

任务状态:pending | running | completed | failedcompletedoutputFiles 给出本地路径,ossUrls 给出 OSS 链接(若已上传)。

cURL 示例

curl -X POST http://localhost:13000/api/render \
  -H 'Content-Type: application/json' \
  -d '{"input":{"template":"knowledge","platforms":["bilibili"],"ttsProvider":"openai-tts","text":"<JSON 字符串>"}}'

# 轮询
curl http://localhost:13000/api/jobs/<jobId>

10. 数据持久化(卷)

挂载 容器路径 用途
./output /app/output 视频产物 + 渲染临时目录(按模板/日期归档,自动清理)
docker volume pipeline-jobs /tmp/pipeline-jobs 任务元数据 jobs.json(重启保留)

注意:任务元数据存在内存卷中,删除 volume 会丢失任务历史(但不影响已生成的视频文件)。


11. 排错

现象 排查
渲染卡在 [5/7] Rendering headless Chrome 未就绪。本地确认 Chrome / Chromium 可用,或设 PUPPETEER_EXECUTABLE_PATH;Docker 镜像已内置所需系统库
TTS 报 API_KEY 错误 检查 .env 的 TTS key;或临时用 --no-tts 调布局
TTS 报 502 / 503 / 网络错误 TTS 网关上游瞬时故障(如 DNS、滚动重启);已内置重试(TTS_MAX_RETRIES 默认 3)。若持续失败,检查 OPENAI_TTS_BASE_URL 网关健康度或临时换 provider
日志里出现 Note: … @remotion/media-parser … license 这是 Remotion 的许可证提醒parseMedia() 探测音频时长时打印),不是错误、不影响渲染。若要消除,需在 packages/tts/src/duration.tsparseMedia() 传入 acknowledgeRemotionLicense: true——注意这是对许可证的法律确认,公司用途请先确认是否需要 Remotion 许可
OSS 上传失败 检查 OSS_REGION/BUCKET/ACCESS_KEY_*;任务详情会展示 Publish warning,本地视频仍生成
飞书收不到消息 确认 FEISHU_WEBHOOK_URL;若启用了签名校验需同时填 FEISHU_WEBHOOK_SECRET
容器内找不到输出 确认挂载到 /app/outputOUTPUT_DIR),docker compose 已默认如此
改了 .env 不生效 重启服务:docker compose up -d(环境变量在容器启动时注入)

12. 目录速查

apps/cli/            CLI 入口(Commander)
apps/web/            Next.js WebUI + API 路由
packages/shared/     Zod schema、类型、常量、LLM 客户端、路径/发布配置解析
packages/core/       流水线编排、7 阶段、cleanup、publish(OSS+飞书)
packages/tts/        TTS provider 注册表
packages/templates/  Remotion 场景组件
packages/collect/    数据采集器(github-trending 等)
config/default.yaml  业务配置(provider / 模板配色 / 采集源 / OSS·飞书默认值)
.env(.example)       密钥与端点
docker-compose.yml   容器编排
Dockerfile           多阶段构建