Composing Images
Character design pre-flight (ALWAYS run first when a character is mentioned):
Will this character appear in downstream video work? (video, clip, promo, 宣传片, 短片, 连续剧, film, scene, shot, short film)
-
Yes → 4-panel reference sheet, regardless of ref count:
Bashnode "$PAI_REPO_ROOT/server/cli/generate_image_pro.js" \ --prompt "4-panel character reference sheet: Front-full, Profile-full, Back-full, Closeup-bust. @Image1 @Image2 @Image3 show the actor..." \ --size 2560x1440 --subtype character --name "Detective Morris" --role "lead detective" \ --ref-source-id <ref1> --ref-source-id <ref2> --ref-source-id <ref3>Announce: "Starting with a 4-panel reference sheet for [character] — locks identity across video shots. Say the word for simple portraits instead."
-
No (poster, print art, standalone illustration) → single portrait:
Bashnode "$PAI_REPO_ROOT/server/cli/generate_image.js" \ --prompt "Realistic character portrait of Detective Morris... Front-facing medium close-up..." \ --aspect-ratio 9:16 --image-size 2K --subtype character --name "Detective Morris" --role "..."
Skipping this check and defaulting to a single portrait for video-bound characters is the most common mistake — identity drifts shot-to-shot without multi-angle anchor data.
Progress:
- [ ] Run character pre-flight if a character is named (video-bound? refs available?)
- [ ] Identify canvas sources (characters, locations, prior results) per project context rules
- [ ] Pick the matching pattern (1–7)
- [ ] Mirror any external URLs via mirror_url.js before use as refs
- [ ] Build the CLI command with correct tool (standard vs pro), subtype, name/role, refs, source-node-id
- [ ] Announce the action in one short line before firing (no pasted prompts)
- [ ] Fire the CLI call via --stage per draft-gate rules
- [ ] Report price/status after draft; recommend next step after terminal result
Tool selection: generate_image.js (standard, accepts --aspect-ratio/--image-size) is default. generate_image_pro.js (accepts --size only, exact pixel dims) is required for storyboard mosaics and character reference sheets — panel layout, text suppression, and identity consistency are load-bearing there.
Reference wiring: every --ref-source-id becomes @Image1, @Image2, … in prompt order, and emits one derived provenance edge. External URLs must be mirrored onto the canvas first (mirror_url.js --url <URL>) — no direct URL flag exists. If a canvas note (script/shot note) authored the image, pass --source-node-id <note_id>.
| Trigger | Pattern | Tool |
|---|---|---|
| One-off portrait, poster, print art (NOT video-bound) | 1. Character portrait | standard |
| "Establish/design/picture [LOCATION]" | 2. Location still | standard |
| "Change/edit/swap/tweak" existing image | 3. Edit/variation | standard |
| "[Character] in [setting]", scene with existing characters | 4. Scene w/ characters | standard |
| Fresh unrelated image | 5. Standalone still | standard |
| Storyboard, mosaic, NxM grid, shot list, previs | 6. Storyboard mosaic | pro |
| Video-bound character, with or without actor refs | 7. Character reference sheet | pro |
Example 1 — video-bound character, 0 refs (Mode B)
Input: "We're making a short film — introduce the villain, a burned-out cult leader."
Output: Pre-flight fires (short film = video-bound). No refs exist. Fire generate_image_pro.js with a text-only 4-panel prompt (Front-full/Profile-full/Back-full/Closeup-bust) describing age, build, wardrobe explicitly per panel, --subtype character --name "Cult Leader", no --ref-source-id. Announce: "Starting with a 4-panel reference sheet for the cult leader so identity locks across video shots."
Example 2 — edit of existing image
Input: "Make it snow instead of rain in that alley shot."
Output: Locate source node, reuse its aspect ratio/size. generate_image.js --prompt "Change the rain to falling snow. Preserve everything else." --subtype edit --source-node-id <id> --ref-source-id <id>.
Example 3 — storyboard mosaic
Input: "Storyboard shot 3, a 2x2 grid."
Output: One generate_image_pro.js call, --size 2560x1440 --subtype storyboard --label "Storyboard — Shot 3" --source-node-id <shot3_note_id>, single composite prompt describing 4 cinematic 16:9 panels. Announce "Generating a 2×2 mosaic for Shot 3." — not one call per panel.
Example 4 — location
Input: "Establish the causeway location from the script."
Output: generate_image.js --prompt "Realistic establishing still of Causeway..." --aspect-ratio 16:9 --image-size 2K --subtype location --name "Causeway" --source-node-id <script_note_id>. No characters in frame.
- Default storyboard grid: 2×2 at 2560x1440 (16:9 cinematic), unless user specifies portrait/square/vertical or another ratio.
- Warn before firing 3×3+ mosaics; recommend splitting into multiple sheets instead.
- Never fire Mode A (photo-based) character sheets with fewer than 3 actor refs — the model overfits to a single angle.
- Edit prompts describe only the delta ("Preserve everything else"), never re-describe the whole scene.
- Multi-step edit chains use one CLI call per step, each sourcing the prior result — never flatten A→C into one call.
- Announce actions in one short line before firing; never paste the full prompt into chat.
- One mosaic per clip/shot note — never one CLI call per panel.
- One character sheet per base character or material variant; variants reference the base sheet's node and describe only the persistent change.
- Defaulting to Pattern 1 (single portrait) for any character that will appear in video — this is the single most common and costly mistake; use Pattern 7 instead.
- Passing
--aspect-ratioor--image-sizetogenerate_image_pro.js— it only accepts--sizewith exact pixel dimensions. - Treating a storyboard request as N separate single-image CLI calls instead of one composite mosaic call.
- Forgetting to mirror external URLs before using them as
--ref-source-id. - Over-specifying edit prompts with a full scene re-description instead of a targeted delta, causing identity drift.
- Omitting
--source-node-idwhen a script or shot note authored the design, breaking provenance.