tutorial-auto-pagebreaklisted
Install: claude install-skill elrufaiforexfx22-creator/claudecode-video-maker
# Tutorial Auto PageBreak
## Overview
在這個 Remotion tutorial 管線中,每個 step 會被切成多「頁」,每頁對應一段 voiceover。**`pages.length` 必須等於 `voiceovers.length`**,否則 `pageAudioDurationsFor()` 取不到對應音訊,頁會提早切掉或音訊被截斷。
本 skill 把「依 `voiceovers.length` 自動插 `pageBreak`」寫成確定性算法,讓人類只寫腳本,分鏡自動生成。
## Core Rule
- **頁數 = `voiceovers.length`**。永遠。
- `voiceovers.length <= 1` → skip,不做事。
- 跑完後,`blocks[]` 裡非-`pageBreak` 元素的**順序與內容完全不變**。
- **冪等**:對同一 step 跑兩次結果相同。
**違反鐵律就是違反精神**:不要為了「看起來比較自然」私自塞/刪 block,skill 只動 pageBreak。
## When to Use
- 正在編輯 `public/screenshots/tutorial-ch1/steps.json`(或同結構的 tutorial data)
- 使用者改了 `voiceovers[]` 腳本,要同步重建分鏡
- 頁數跟配音數對不起來 → 音訊被切、動畫提早結束
- 在跑 `voiceover:tutorial` 或 render 前的最後一步
## When NOT to Use
- 單段 voiceover 的 step(`voiceovers.length <= 1`)
- 非 tutorial 的 composition(如 `src/content.ts`, scenes 不走 blocks/pageBreak 模型)
- 資料結構沒有 `voiceovers[]` + `blocks[]` + `type: "pageBreak"`
## Algorithm — 自然斷點 + 均勻目標
**價值序**:單頁資訊完整 → 不太擠 → 留白。**不追求塊數平均**。
### 步驟
1. **Strip** 既有 `pageBreak`(先乾淨化 → 保證冪等)
2. 若 `blocks.length < N`(`N = voiceovers.length`)→ `console.warn` + skip(不硬切)
3. 計算 **N-1 個均勻目標斷點**:`targets[i] = floor(len * (i+1) / N) - 1`,i ∈ [0, N-2]
4. 對每個 target,從 `[t-MAX_DRIFT, t+MAX_DRIFT]` 範圍內(`MAX_DRIFT = 2`)**挑「最佳斷點」**:
1. **優先**:`image` / `code` / `callout` 之後(這三個是「資訊單位收尾」)
2. 同級下:**離 target 最近**
3. 平手:**偏右邊**(index 較大)
4. 已被用過的 index 不可再選(每個 target 各自的斷點必須不同)
5. **排除尾端 block**(`idx === len - 1`)當斷點
6. 範圍內都沒自然斷點 → 就切在 target(可能切在 paragraph 之間,接受)
5. **