# CLAUDE.md 本文件为 Claude Code (claude.ai/code) 在本仓库中工作时提供指引。 ## 项目概述 文本转视频生成流水线。接收描述视频结构(封面、场景、结束语)的 JSON 输入,输出带 TTS 旁白、字幕和模板视觉样式的 MP4 视频。 ## 常用命令 ```bash pnpm build # 构建所有包 (turbo) pnpm typecheck # 类型检查所有包 pnpm lint # Lint 所有包 # 运行视频渲染 node apps/cli/dist/index.js render test/fixtures/sample-knowledge.json -t knowledge -p bilibili # Web UI 开发服务器 cd apps/web && pnpm dev ``` > 部署(Docker Compose / HTTP API / 配置 / OSS·飞书发布)详见 [`docs/DEPLOYMENT.md`](docs/DEPLOYMENT.md),环境变量模板见 [`.env.example`](.env.example)。 ## 架构 pnpm workspaces + Turborepo 的 monorepo 结构。 ``` apps/cli/ CLI 入口 (Commander) apps/web/ Next.js 15 WebUI + API 路由 packages/shared/ Zod schema、类型定义、常量、LLM 客户端 packages/core/ 流水线编排与 6 个阶段 packages/tts/ TTS provider 注册表 + 4 个 provider packages/templates/ 5 个模板的 Remotion React 组件 ``` ### 流水线数据流 输入始终是**结构化 JSON** (`VideoInputSchema`)。流水线在 `packages/core/src/stages/` 中依次执行 6 个阶段: 1. **parse** — 通过 `VideoInputSchema` 验证 JSON,转换为内部 `ParsedContent`(cover → scene-0,outro → 最后一个 scene)。`github-trending` 在这里:①内容场景按 `github.repo.todayStars` 降序取 **top 6**(视频只介绍今日涨星最多的 6 个,顺序与首屏一致);②确定性写入 cover 开场口播(结构:问候 → 今日趋势 → 进入项目详解,即 `大家好,今天{trendSummary}。下面进入项目详解。`,**不含日期/数量**——日期与卡片由首屏视觉呈现;`trendSummary` 缺失时退化为 `大家好,下面进入项目详解。`);③承载 LLM 产出的 `trendSummary`(一句话趋势)透传到首屏渲染。不再注入 summary 场景,也已停用 `coverTags`。parse 末尾还会对所有场景 narration 跑 `normalizeCountsForTTS`,把 `Nk` 星数(如 `11.3k`)展开成中文口语(一万一千三百),避免 TTS 把 k 读成字母 2. **tts** — 按场景调用 TTS provider,生成逐场景音频文件 + word timestamps 3. **assets** — 解析图片资源(本地 `path` > 远程 `url` > 关键词 `query`),复制背景图/字体 4. **compose** — 转换为带帧时间轴的 `ComposedProject`,word timestamps 转为场景内相对时间。逐字段拷贝场景数据——新增场景字段时**必须在此阶段显式透传**(`buildInputProps` 用 `...scene` 自动透传,但 compose 是手写字段映射) 5. **render** — 打包 Remotion bundle,将资源复制到 publicDir,通过 `renderMedia` 渲染 6. **export** — 输出最终 MP4 到**统一输出目录**,按 `{模板名称}/{ISO日期(YYYY-MM-DD)}/{原文件名}.mp4` 自动建子目录;同时写一份同名 `.yaml` **发布清单**到 MP4 旁边(标题/描述/标签来自 LLM 产出的 `publish` 块;分区 tid/category 等平台特定字段来自 `config.publishMeta[平台][模板]`)。写清单是 best-effort,失败只告警不中断渲染 7. **publish**(可选,按需开启)— 渲染成功后上传到阿里云 OSS 并推送飞书 webhook:上传成功推送 OSS 资源链接,生成/上传失败推送失败信息。生成失败(未产出文件)也会推送失败信息。未配置 OSS/飞书时跳过 核心类型链:`VideoInput` → `ParsedContent` → `ComposedProject` → Remotion props。 ### Remotion 约束 Remotion 通过其 webpack dev server 提供所有静态资源。**组件中绝不能使用文件系统绝对路径** — 必须使用 `staticFile(filename)`。render 阶段会将所有资源(音频、图片、背景图)复制到统一的 `publicDir`,通过 props 传递文件名。 音频按场景独立播放:每个 `` 包含自己的 `