# 部署文档 文本转视频生成流水线的部署与运行说明。项目以**容器化、服务化**为重心: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`。 - **CLI**(`apps/cli`)是流水线唯一入口;WebUI 与 HTTP 都复用它,因此 OSS 上传 / 飞书推送只在 CLI 进程内发生一次。 - **统一输出目录**:CLI / HTTP / WebUI 写入同一目录,按 `{模板}/{ISO日期}/{文件名}.mp4` 自动建子目录。 - **monorepo**:pnpm workspaces + Turborepo(`packages/shared|core|tts|templates|collect`,`apps/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(推荐) ```bash # 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` 打进镜像**。 停止 / 查看日志 / 重建: ```bash 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.yaml` → `config/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 及签名密钥 | | `LOG_LEVEL` | 否 | 日志级别 `debug\|info\|warn\|error`,默认 `info` | | `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: `;WebUI 任务详情页展示「OSS Links」)。 --- ## 7. 日志与可观测性 排查问题看三处: 1. **容器日志(实时)**:`docker compose logs -f pipeline`。CLI 子进程的每阶段进度、TTS 重试、publish(OSS 上传 / 飞书发送)日志都会**镜像**到这里,每行带 `[job ]` 前缀与时间戳,便于区分并发任务。 2. **WebUI 任务详情页「日志」面板**:任务结束后展示完整捕获的 CLI 输出(上限 ~200KB,超出截断头部)。失败任务同样可看。 3. **失败任务的 `error` / `publishError`**:任务卡片与详情页直接显示。 日志格式:` [LEVEL] [scope] message`,scope 含 `pipeline` / `tts` / `publish`。用 `LOG_LEVEL`(`debug|info|warn|error`,默认 `info`)调节详细程度。 > 说明:渲染由 Web 服务 spawn CLI 子进程执行;CLI 的 stdout/stderr 默认被管道捕获。现在这些输出既会镜像到容器 stdout/stderr(供 `docker compose logs`),也会存入任务(供 UI)。TTS 的瞬时 502/网络重试会以 `[WARN] [tts] HTTP 502, retrying …` 形式出现;OSS/飞书失败会以 `[ERROR] [publish] …` 出现,不再被静默吞掉。 ## 8. 本地开发(非 Docker) ```bash 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 ``` 常用命令: ```bash pnpm typecheck # 全包类型检查 pnpm lint # 全包 lint pnpm build # 全量构建 ``` --- ## 9. CLI 用法 ```bash node apps/cli/dist/index.js render -t