feat: beat-level local image/movie references (Phase 2)
## Overview
`imageParams.images`(グローバル)に加え、**beat 内にローカルな `images` を定義**して同じ beat の html_tailwind 等で使えるようにする。Issue #1292 の Phase 2。
## Agent 入力仕様
### reference として渡せるもの
| 生成対象 | reference に渡せるもの | 渡せないもの |
|---------|----------------------|-------------|
| 画像生成 (`imageGenerator`) | `imageRefs` の画像(複数可, `referenceImages: string[]`) | `movieRefs` の動画 |
| 動画生成 (`movieGenerator`) | `imageRefs` の画像(1枚, `imagePath: string`) | `movieRefs` の動画 |
| html_tailwind / markdown | `imageRefs` (`image:name`) + `movieRefs` (`movie:name`) | — |
**`imageRefs`(画像パス)は全場面で使える万能 ref。`movieRefs`(動画パス)は html/markdown 内の `movie:name` でのみ使用可能。**
## Design
### Schema
\`beat.images\` フィールドを追加。\`imageParams.images\` と同じスキーマ(\`image\`/\`imagePrompt\`/\`movie\`/\`moviePrompt\`)。
```json
{
"beats": [{
"images": {
"bg": { "type": "imagePrompt", "prompt": "cherry blossom garden" },
"pan": { "type": "moviePrompt", "prompt": "slow dolly forward", "imageName": "bg" }
},
"image": {
"type": "html_tailwind",
"html": ["<video src='movie:pan' autoplay muted style='width:100%;height:100%;object-fit:cover' />"]
}
}]
}
```
### 解決タイミング
`beat_graph_data` に `localRefs` ノードを新設。preprocessor/imagePlugin の **前** に beat.images を解決し、グローバル refs とマージ。
```
localRefs (new) ← beat.images を解決 → mergedImageRefs, mergedMovieRefs
↓
preprocessor ← mergedImageRefs から referenceImages を取得(画像のみ)
imagePlugin ← mergedImageRefs, mergedMovieRefs を html_tailwind/markdown に渡す
imageGenerator ← referenceImages(画像パスのみ)を AI に渡す
movieGenerator ← referenceImageForMovie(画像パス1枚)を AI に渡す
```
### マージルール
- `mergedImageRefs = { ...globalImageRefs, ...localImageRefs }` — ローカル優先
- `mergedMovieRefs = { ...globalMovieRefs, ...localMovieRefs }` — ローカル優先
### 依存順序(2段階解決)
1. **Stage 1**: `image`, `imagePrompt`, `movie` を並列解決
2. **Stage 2**: `moviePrompt` を解決(`imageName` で Stage 1 の imageRefs を参照可能)
## Implementation Steps
### Step 1: Schema 変更
- `src/types/schema.ts`: `mulmoBeatSchema` に `images: mulmoImageParamsImagesSchema.optional()` 追加
### Step 2: Beat-local refs 解決ロジック
- `src/actions/image_references.ts`: `resolveBeatLocalRefs()` 関数追加
- `beat.images` なし → グローバル refs をそのまま返す(既存動作に影響なし)
- `beat.images` あり → 2段階解決 → グローバルとマージして返す
### Step 3: beat_graph_data に localRefs ノード追加
- `src/actions/images.ts`: `localRefs` ノード追加、preprocessor/imagePlugin の入力を `:localRefs.imageRefs` / `:localRefs.movieRefs` に変更
### Step 4: moviePrompt 解決(generateReferenceMovie)
- `src/actions/image_references.ts`: `generateReferenceMovie()` 関数追加(PR #1294 と同じロジック)
### Step 5: ドキュメント更新
- `docs/image.md`: `beat.images` セクション追加
### Step 6: テストスクリプト
- `scripts/test/test_beat_local_refs.json`:
- Beat 1: beat.images に imagePrompt → html_tailwind で `image:name` 参照
- Beat 2: beat.images に imagePrompt + moviePrompt → html_tailwind で `movie:name` 参照
- Beat 3: グローバル + ローカル混在(同名キーでローカル優先の確認)
- Beat 4: beat.images の imagePrompt を `beat.imageNames` で reference image として imageGenerator に渡す
## Plan file
`plans/feat-beat-local-refs.md`
关闭于 2026-03-16 0 条评论