Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 56 additions & 0 deletions .claude/skills/new-scene/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
---
name: new-scene
description: 在 explainer-kit 里新写一场讲解(旁白 + 画面)。用户给一个主题、一段文稿或一个要讲的概念,想做成视频里的一场时使用;也用于把已有的一场改写成另一种风格。
---

# 写一场

## 1. 先写旁白,再想画面

旁白就是时间轴。在纸面上把文稿切成「一句话一个画面」,每个画面变化前放一个 `[[cue]]`:

- 第一个 cue 放在文稿最前面,否则章节卡淡出后会空几秒。
- 一个 cue 对应一个画面变化(新元素进场、转场、镜头推近)。一场 4–7 个 cue 比较合适,太密画面会乱。
- 戏剧停顿用 `||`;引语换声音用 `<<q|……>>`。cue 名只能用字母、数字、下划线,`end` 是保留名。
- 开头那半句(比如「再换一套:」)也要配字或画面,标题要等念到才出的话前面会空。

## 2. 选风格

| 内容 | 风格包 |
|---|---|
| 叙事、人物 | `film` |
| 概念、API | `slides` |
| 流程、因果、拆步骤 | `paper` |
| 系统、架构、数据流 | `neon` |
| 观点、金句、关键数字 | `editorial` |
| 公式推导、函数图像 | `math` |
| 产品介绍、操作演示 | `keynote` |
| 轻松科普、儿童向 | `pixel` |
| 历史、诗词、传统文化 | `ink` |

## 3. 一条命令搭好骨架

```bash
node tools/new-scene.mjs s10 --look paper --chapter "第十场 · 标题" --text "[[start]]……[[next]]……"
```

它会追加 `tts/script.json`、生成能直接跑的 `src/scenes/s10.tsx`(每个 cue 一段跟着旁白出现的字)、登记到 `src/scenes/index.ts`、跑 `--mock` 时间轴。之后改旁白只需 `python tts/gen.py --mock s10`。

## 4. 把占位画面换成真正的画面

只用帧号说话,永远不写死秒数:

- `c('cue')`、`w('词')`、`rel('词', 'cue')` 取帧;`useSpoken().chars/span` 取逐字帧。
- 进场和退场成对:`const {p, q} = life(f, at, out)`,样式用 `move('rise', p, q)`。会被新内容替换的元素一定要有 `out`。
- 屏幕上的字用 `<Spoken text="……旁白原文……" />`,按配音逐字出现;`text` 必须和旁白一字不差(可以加 `\n` 换行)。
- 分镜用 `<Shots>`,转场选 `push` `up` `zoom` `wipe` `whip` `iris` `black`;相似画面不要用 `fade`(会重影)。
- 落定的元素加一点 `drift(f, seed)`,背景要有不停的小动作,不要冻住。
- 音效 `<Sfx at={帧} name="pop" />` 放在场景最外层(不要放进 Shots 的镜头里,镜头切走会把声音截断)。可用的声音见 `src/core/Sfx.tsx` 的 `SFX`。点击配 `click`,落地配 `thud`,大字配 `slam`,画线配 `draw`,推拉配 `whoosh`。
- 想踩在配乐节拍上:`const beat = useBeat()`,`beat.next(帧)` 吸附到下一拍,`beat.pulse()` 每拍一次的 0..1。
- 不要用 `Math.random()`,用 `rng(seed)` / `noise(seed, x)`。

各风格包的组件看 README「风格包」一节和对应的 `src/<pack>/index.tsx`;演示场 `src/scenes/s01–s09.tsx` 是每个包的完整用法示例。

## 5. 交付前

`npx tsc --noEmit` 通过,然后按 `review` skill 审一遍动态、声音和竖屏。
35 changes: 35 additions & 0 deletions .claude/skills/new-style-pack/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
---
name: new-style-pack
description: 给 explainer-kit 新增一套视觉风格包(配色、背景、章节卡、组件、Look)。用户想要「再来一种风格」「做成 XX 风」或提供参考视频/参考风格时使用。
---

# 新风格包

## 1. 先定方向

一句话说清:底色(深/浅)、一个主色、它的「标志性动作」是什么(例:paper 是线条一笔笔画出来并持续轻抖,neon 是网格地面一直往前滚,keynote 是一个形状不断变形)。和现有 9 套比,要有明显不同的东西,而不只是换颜色。

## 2. 搭骨架

```bash
node tools/new-pack.mjs chalk --base "#1F2B26" --accent "#F2C14E"
node tools/new-scene.mjs s10 --look chalk --chapter "第十场 · 黑板风" --text "[[start]]……"
```

`new-pack` 生成 `src/chalk/index.tsx`:经过 `themed()` 的调色板、带缓慢光斑的背景、章节卡、`Title`/`Card` 组件、`Look`。

## 3. 每个包都要满足

- 调色板必须经过 `themed('<pack>', {...}, {accent: [...], accent2: [...]})`,把主色挂到 accent 槽位,品牌色才能一键替换;颜色写 `#rrggbb`。
- 背景永远有一点动作(漂移光斑、滚动纹理、闪烁),不能整屏静止。
- 章节卡和场景开头的版式尽量一致(editorial 的章节卡和正文同一套刊头),切进正文时不跳。
- `look.subtitles`:浅底配深色字幕条(`boxColor`),深底反之;`quoteColor` 用主色。
- 组件只用 `useCurrentFrame()` 和传进来的帧号;进场退场用 `life` + `move`;随机用 `rng`/`noise`。
- 标志性动作做成组件,并配好音效建议(例:画线配 `draw`,落地配 `thud`)。
- 包内不 import 其他风格包;core 不 import 任何包。

## 4. 演示和文档

- 写一场演示(`src/scenes/sNN.tsx`),把这个包最有代表性的动作都用上,按 `review` skill 审一遍,包括 `FORMAT=9x16`。
- README「风格包」加一条介绍、「选哪套」加一句用途、目录表加一行;英文段落的包列表同步。
- `node tools/overview.mjs` 看新包和其他包放在一起是否协调;再设一个 `brand.accent` 看换色效果。
32 changes: 32 additions & 0 deletions .claude/skills/publish/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
---
name: publish
description: 出片:从真配音到最终带配乐、响度标准化的 mp4,包括横屏、竖屏 9:16、方屏 1:1 和品牌色设置。用户说「出片」「渲染成片」「导出竖屏」「发布」时使用。真配音和正式渲染在 Windows 本机做。
---

# 出片

## 一条命令

```bash
node tools/publish.mjs # 真 edge-tts → 渲染 → 配乐 → 混音,主画幅
node tools/publish.mjs --formats 9x16,1x1 # 同时出竖屏和方屏(或 --formats all)
node tools/publish.mjs --skip-tts # 只改了画面,沿用现有配音和时间轴
node tools/publish.mjs --mock # 离线跑通整条流水线(静音旁白)
```

成品:`out/<id>-mixed.mp4`、`out/<id>-9x16-mixed.mp4`……

## 出片前确认

1. **字体**:`npm run fonts` 下载 Noto Sans/Serif SC,否则会退回系统字体。
2. **品牌**:`kit.config.json` 的 `brand.name`(片尾、跑马灯里的名字)、`brand.accent` / `brand.accent2`(#rrggbb,替换所有风格包的主色),单个包微调用 `theme.<pack>.<key>`。改完先跑 `node tools/overview.mjs` 看一眼。
3. **画幅**:`formats` 里每个格式都会多一个合成 `<id>-<格式>`。竖屏把 16:9 画面放在中间,上面是章节标题,下面是大字幕;某一场内容集中在中间时,在 `src/scenes/index.ts` 给它 `portrait: {zoom: 1.3}` 放大裁边(`focus` 选保留哪一侧)。
4. **音量**:`sfx.volume` 是音效总音量;`music.bpm` 决定配乐节拍(场景里 `useBeat()` 用同一个网格)。改了音效配方要跑 `python tools/sfx.py`。

## 踩过的坑

- 渲染一定要 `--gl=angle`(`tools/render.mjs` 已带上),纯软件 GL 慢约 5 倍。
- 超过 10 分钟的渲染脱离终端跑并看日志:Git Bash `nohup node tools/publish.mjs --formats all > out/publish.log 2>&1 &`;PowerShell 用 `Start-Process` 并重定向输出。
- edge-tts 原始响度只有约 -24 LUFS,必须经过 `tools/mix.py`(publish 已包含)到 -16 LUFS。
- 只重做某几场的配音:`python tts/gen.py s03 s05`,其他场沿用旧时间轴;然后 `publish --skip-tts`。
- 换了真配音后 cue 位置都会变,交付前按 `review` skill 再审一遍。
50 changes: 50 additions & 0 deletions .claude/skills/review/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
---
name: review
description: 审片:检查 explainer-kit 某一场或整片的动态、声音、竖屏/方屏版式和品牌色。改完场景、换了风格包或品牌色、要交付之前使用;用户说「看看效果」「检查一下」「审一下」时也用。
---

# 审片

渲染工具在没有 Remotion 浏览器的环境(比如云端沙箱)会自动用 `/opt/pw-browsers` 里预装的 headless shell,也可以用 `REMOTION_BROWSER=…` 指定。输出都在 `out/`,不要提交。

## 看动态:拼帧,不要只看静帧

```bash
node tools/strip.mjs s05:block # cue 前 6 帧到后 84 帧,每 6 帧一格
node tools/strip.mjs s05:block:-4:120:8 # 场景:cue:起:止:步长
FORMAT=9x16 node tools/strip.mjs s07:card # 竖屏版式
```

逐格对照这些问题:

1. **死帧**:cue 之后有没有超过 1 秒什么都不动、或者画面是空的(常见于标题等念到才出、开头半句没配画面)。
2. **重影**:两个相似画面叠化时互相透出来。换成 `push`,或让旧元素先 `life(..., out)` 离场。
3. **重叠**:旧内容还没走完新内容就进来了(退场要在下一个 cue 之前结束)。
4. **冻住**:元素落定后就完全不动。加 `drift`,或背景带一点持续动作。
5. **字和声音对不上**:屏幕大字跑在配音前面或落后太多。用 `<Spoken>`,不要按固定速度打字。
6. **出画/遮挡**:元素压到字幕区(画面底部约 120px)或被裁掉。

## 看全片和品牌色

```bash
node tools/overview.mjs # 每场一格的总览图
node tools/overview.mjs --format 9x16 # 竖屏总览
```

改 `kit.config.json` 的 `brand.accent` 后跑一次总览,确认九套风格换色后都还看得清。

## 听声音(没有扬声器也行)

```bash
node tools/listen.mjs s05 # 整场
node tools/listen.mjs s05:block s05:out:30 # 一段
```

输出每个声音离哪个 cue 多少帧(如 `hit+0`)。`--mock` 时旁白是静音的,列出来的全是音效和配乐节拍。核对:每个点击、落地、砸字都有声音,且偏差在 ±3 帧内;没有意外的长时间噪声。

## 交付前的检查清单

- `npx tsc --noEmit`、`pytest` 通过
- 改过的每场都拼帧看过,主画幅和 9x16 各一遍
- 音效位置用 `listen` 核对过
- 真配音(Windows 上 `python tts/gen.py`)后再看一遍:cue 位置会变,写死的帧数会错位
3 changes: 2 additions & 1 deletion CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,6 @@
Remotion 讲解视频模板:旁白里写 `[[cue]]` 标记,edge-tts 的逐词时间戳驱动字幕和动画。用法见 `README.md`。

- 面向用户的文档用简体中文;代码、命令、标识符用英文。
- 本机是 Windows(渲染、真 TTS 验证在那里做);云端沙箱只做重构、类型检查、`--mock` 时间轴和单测。
- 本机是 Windows(渲染、真 TTS 验证在那里做);云端沙箱只做重构、类型检查、`--mock` 时间轴和单测。沙箱里也能看画面和听音效:`tools/` 的渲染脚本会自动用 `/opt/pw-browsers` 预装的 headless shell(`node tools/strip.mjs s01:quote`、`node tools/overview.mjs`、`node tools/listen.mjs s05`),只看,不提交 `out/`。
- 常做的事有项目 skill(`.claude/skills/`):`new-scene` 写一场、`review` 审片、`new-style-pack` 新风格包、`publish` 出片。反复手动做的步骤,优先收成 `tools/` 脚本或补进这些 skill。
- 不在仓库里提交字体文件和渲染产物(`out/`、`public/fonts/`)。
Loading
Loading