@milenyumai/film-kit 2.3.4 → 2.3.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +6 -2
- package/build/index.d.ts +1 -1
- package/build/lib/cli.js +1 -1
- package/build/lib/configure.js +14 -9
- package/build/lib/storyboard-reference/adapters/seedance20.d.ts +1 -0
- package/build/lib/storyboard-reference/adapters/seedance20.js +27 -11
- package/build/lib/storyboard-reference/index.d.ts +1 -1
- package/build/lib/storyboard-reference/output-writer.js +6 -0
- package/build/lib/storyboard-reference/prompt-bundle-builder.js +89 -21
- package/build/lib/storyboard-reference/types.d.ts +35 -1
- package/build/lib/storyboard-reference/validators.js +9 -0
- package/build/lib/templates.js +1 -1
- package/content/skills/storyboard-reference/SKILL.md +13 -8
- package/content/workflows/generate-storyboard.md +8 -6
- package/package.json +1 -1
- package/packages/gpt-image-smart/content/skills/storyboard-reference/SKILL.md +13 -8
- package/packages/gpt-image-smart/content/workflows/generate-storyboard.md +24 -6
- package/packages/hybrid/content/skills/storyboard-reference/SKILL.md +13 -8
- package/packages/hybrid/content/workflows/generate-storyboard.md +24 -6
- package/packages/hybrid-smart/content/skills/storyboard-reference/SKILL.md +13 -8
- package/packages/hybrid-smart/content/workflows/generate-storyboard.md +24 -6
- package/packages/multi/build/lib/configure.js +4 -4
- package/packages/multi/build/lib/templates.js +9 -9
- package/packages/multi/content/skills/storyboard-reference/SKILL.md +13 -8
- package/packages/multi/content/workflows/generate-storyboard.md +24 -6
- package/packages/studio/content/skills/storyboard-reference/SKILL.md +13 -8
- package/packages/studio/content/workflows/generate-storyboard.md +24 -6
package/README.md
CHANGED
|
@@ -183,6 +183,7 @@ npx @milenyumai/film-kit generate-storyboard \
|
|
|
183
183
|
Outputs:
|
|
184
184
|
|
|
185
185
|
- `outputs/storyboard-reference-plan.json`
|
|
186
|
+
- `outputs/storyboard-prompt.md`
|
|
186
187
|
- `outputs/reference-prep/CHARACTER-SHEET-*.md`
|
|
187
188
|
- `outputs/storyboard-prompts/SHOTNN-GPT-IMAGE-2-STORYBOARD.md`
|
|
188
189
|
- `outputs/prompt-bundles/SHOTNN.bundle.json`
|
|
@@ -196,8 +197,11 @@ Rules:
|
|
|
196
197
|
- `@character1` is used once to create a 16:9 character sheet prompt with front, back, side, three-quarter, and face close-up views.
|
|
197
198
|
- GPT Image 2 still prompts use `REFERENCE LOCK`, `Keep same`, `Change only`, and `Avoid` sections so character identity, wardrobe, props, and materials stay immutable unless explicitly changed.
|
|
198
199
|
- Each `SHOTNN.md` includes a professional `GPT IMAGE 2 STORYBOARD PROMPT`; the generated shot storyboard controls composition, blocking, camera, timing, and editorial phase order only.
|
|
199
|
-
-
|
|
200
|
+
- If no external storyboard image exists, Film-Kit still generates the GPT Image 2 storyboard bootstrap prompt and writes it to both `outputs/storyboard-prompts/SHOTNN-GPT-IMAGE-2-STORYBOARD.md` and the convenience alias `outputs/storyboard-prompt.md`.
|
|
201
|
+
- Storyboard prompts default to a 12-panel 16:9 production-board sheet: white paper, rough black-and-white pencil drawings, strong silhouettes, visible body/camera momentum, cinematic camera variety, and color-coded planning annotations only. Hard negatives block photorealistic stills, full-color rendered panels, concept-art strips, CGI, anime, and polished illustration.
|
|
202
|
+
- Seedance treats the generated storyboard token as the complete visual/action/camera/choreography source, follows all beats left-to-right/top-to-bottom, and ignores arrows, labels, notes, page headers, timestamps, panel borders, and other annotations in the rendered video.
|
|
200
203
|
- Seedance provider-facing tokens map generated character sheets first (`@Image1`, `@Image2`, ...) and the generated shot storyboard next. Legacy lowercase aliases remain documented in runtime text.
|
|
204
|
+
- `SHOTNN.bundle.json` includes `storyboard_creation` metadata with provider, prompt path, alias path, style contract, default panel count, reading order, panel count, forbidden visual modes, Seedance token, annotation policy, and prompt text.
|
|
201
205
|
- Speaking shots must bind `Audio Plan.activeSpeakerKey` back to project-level `voiceCast`; broken voice bindings fail QA.
|
|
202
206
|
- Public-figure, celebrity, likeness, logo, trademark, or brand references in the brief, dialogue metadata, or reference metadata are blocked unless safely anonymized first.
|
|
203
207
|
- Phase budget: 4-6s uses 1-2 phases, 7-10s uses 2-3 phases, and 11-15s uses 3-4 phases.
|
|
@@ -216,7 +220,7 @@ CLI flags for direct storyboard bundle generation:
|
|
|
216
220
|
| `--models` | Comma-separated target models: `veo31`, `seedance-2.0`, `kling-3.0` |
|
|
217
221
|
| `--duration` | Duration in seconds per generated shot. Seedance provider range is 4-15 seconds |
|
|
218
222
|
| `--aspect` | `16:9`, `9:16`, or `1:1` |
|
|
219
|
-
| `--storyboard-panel-count-hint` | Optional
|
|
223
|
+
| `--storyboard-panel-count-hint` | Optional GPT Image 2 storyboard sheet panel count, `1-12`. Default: `12`. This does not by itself split SHOT files |
|
|
220
224
|
| `--max-storyboard-phases` | Upper bound per shot. Default: `4` |
|
|
221
225
|
|
|
222
226
|
## CLI
|
package/build/index.d.ts
CHANGED
|
@@ -4,4 +4,4 @@ export { buildStoryboardReferencePromptBundles, normalizeVideoPromptRequest, ren
|
|
|
4
4
|
export { assertModelAllowed, getModel, getModelAdapterKey, getModelDisplayName, getReplacementModel, isActiveModelId, isDeprecatedModelId, isImageModelId, isKnownModelId, isModelSupportedByPreset, isRemovedModelId, isVideoModelId, listActiveModels, listActiveVideoModelIds, listImageModels, listModels, listModelsForPreset, listModelsForReferenceMode, listRunnableVideoModelIds, listRunnableVideoModels, listVideoModels, requireModel, validateModelAllowed } from "./lib/model-registry/index.js";
|
|
5
5
|
export type { AgentConfigOptions, ConfigureFilmKitResult, ConfigureResult, FilmKitConfigFile, FilmKitConfigOptions, FilmKitPreset, GptImageFormat, GptImageQuality, GptImageSize, HybridAspectRatio, KlingPreset, NanoBananaImageSize, ReferenceMode, StoryboardReferenceConfig, SupportedModel, SupportedPlatform } from "./lib/types.js";
|
|
6
6
|
export type { ActiveModelId, AudioModelId, DeprecatedModelId, ImageModelId, KnownModelId, ModelAdapterKey, ModelAllowedContext, ModelAllowedResult, ModelCapabilities, ModelLifecycleStatus, ModelModality, ModelRegistryEntry, MultimodalModelId, RemovedModelId, VideoModelId } from "./lib/model-registry/index.js";
|
|
7
|
-
export type { CharacterReferenceSheetPrompt, ModelPromptOutput, ModelRouteMetadata, PromptBundle, ProviderAssetMappingEntry, ProviderFileLimitReport, ProviderReferenceTokenPolicy, ReferenceAsset, ReferenceAssetRequirement, SeedanceContinuityMode, ShotHandoffNote, StoryboardImagePrompt, StoryboardPhaseBudget, StoryboardReferenceBuildResult, StoryboardReferencePolicy, StoryboardReferenceWriteResult, VideoPromptRequest } from "./lib/storyboard-reference/index.js";
|
|
7
|
+
export type { CharacterReferenceSheetPrompt, ModelPromptOutput, ModelRouteMetadata, PromptBundle, ProviderAssetMappingEntry, ProviderFileLimitReport, ProviderReferenceTokenPolicy, ReferenceAsset, ReferenceAssetRequirement, SeedanceContinuityMode, ShotHandoffNote, StoryboardCreationMetadata, StoryboardImagePrompt, StoryboardPhaseBudget, StoryboardReferenceBuildResult, StoryboardReferencePolicy, StoryboardReferenceWriteResult, VideoPromptRequest } from "./lib/storyboard-reference/index.js";
|
package/build/lib/cli.js
CHANGED
|
@@ -542,7 +542,7 @@ generate-storyboard flags:
|
|
|
542
542
|
--dialogue Repeatable "Speaker: exact line" value
|
|
543
543
|
--audio-intent SFX/ambience direction
|
|
544
544
|
--style-intent Visual style direction
|
|
545
|
-
--storyboard-panel-count-hint
|
|
545
|
+
--storyboard-panel-count-hint GPT Image 2 storyboard sheet panel count, 1-12; does not split SHOT files by itself
|
|
546
546
|
--max-storyboard-phases Upper bound per SHOTNN storyboard phase count
|
|
547
547
|
|
|
548
548
|
Install:
|
package/build/lib/configure.js
CHANGED
|
@@ -160,6 +160,7 @@ description: Generate storyboard-reference prompt bundles from character referen
|
|
|
160
160
|
\`\`\`text
|
|
161
161
|
${vars.outputDir}/
|
|
162
162
|
├── storyboard-reference-plan.json
|
|
163
|
+
├── storyboard-prompt.md
|
|
163
164
|
├── reference-prep/
|
|
164
165
|
│ └── CHARACTER-SHEET-*.md
|
|
165
166
|
├── storyboard-prompts/
|
|
@@ -187,18 +188,21 @@ ${vars.outputDir}/
|
|
|
187
188
|
- \`maxStoryboardPhases: ${vars.maxStoryboardPhases}\`
|
|
188
189
|
- \`voiceCast\` when dialogue or narration exists
|
|
189
190
|
- \`visual_world\` for camera, lens, lighting, scale, reflection, physics, screen direction, and continuity anchors
|
|
190
|
-
4. Split the scenario into shots by dramatic beat. Use this phase budget:
|
|
191
|
+
4. Split the scenario into shots by dramatic beat. Use this video phase budget:
|
|
191
192
|
- 4-6 seconds: 1-2 phases
|
|
192
193
|
- 7-10 seconds: 2-3 phases
|
|
193
194
|
- 11-15 seconds: 3-4 phases
|
|
194
|
-
- 5+ distinct phases: split into separate \`SHOTNN.md\` files
|
|
195
|
+
- 5+ distinct real video phases, scene changes, or location/action blocks: split into separate \`SHOTNN.md\` files
|
|
196
|
+
- GPT Image 2 storyboard sheets may use 1-12 panels; 5-12 storyboard sheet panels alone do not force a split
|
|
195
197
|
5. For each shot, write a GPT Image 2 storyboard prompt:
|
|
196
198
|
- use character sheets as the only identity source
|
|
197
199
|
- use optional storyboard guides only for staging and timing
|
|
200
|
+
- use raw black-and-white rough pencil storyboard panels, strong silhouettes, visible motion, cinematic camera variety, and color-coded planning annotations
|
|
198
201
|
- include previous-shot handoff and next-shot handoff
|
|
199
202
|
- preserve shared \`visual_world\`, lighting, screen direction, and action rhythm
|
|
200
203
|
6. Build model-ready video prompt bundles:
|
|
201
204
|
- Seedance: character sheet tokens first, generated shot storyboard token next
|
|
205
|
+
- Seedance: follow storyboard panels left-to-right/top-to-bottom as visual/action/camera source, but never render arrows, labels, annotations, timestamps, or panel borders
|
|
202
206
|
- Veo: visual planning prompt with full audio direction
|
|
203
207
|
- Kling: block-structured storyboard route, not a mandatory Start+End frame route
|
|
204
208
|
7. Keep coverage inside the same \`SHOTNN.md\`; coverage uses storyboard planning prompts and does not request separate start/end still prompts.
|
|
@@ -351,13 +355,14 @@ description: Finalize storyboard-reference prompt packages after storyboard QA p
|
|
|
351
355
|
## Validate Files
|
|
352
356
|
|
|
353
357
|
1. \`${vars.outputDir}/storyboard-reference-plan.json\` exists.
|
|
354
|
-
2. \`${vars.outputDir}/
|
|
355
|
-
3. \`${vars.outputDir}/
|
|
356
|
-
4. \`${vars.outputDir}/
|
|
357
|
-
5.
|
|
358
|
-
6.
|
|
359
|
-
7.
|
|
360
|
-
8.
|
|
358
|
+
2. \`${vars.outputDir}/storyboard-prompt.md\` exists as the storyboard bootstrap alias.
|
|
359
|
+
3. \`${vars.outputDir}/reference-prep/\` contains character sheet prompt files.
|
|
360
|
+
4. \`${vars.outputDir}/storyboard-prompts/\` contains per-shot GPT Image 2 storyboard prompts.
|
|
361
|
+
5. \`${vars.outputDir}/prompt-bundles/\` contains model prompt bundles with \`storyboard_creation\` metadata.
|
|
362
|
+
6. Every \`${vars.outputDir}/shots/SHOTNN.md\` contains the required storyboard-reference sections.
|
|
363
|
+
7. Coverage stays in the same \`SHOTNN.md\`.
|
|
364
|
+
8. No generated shot contains forbidden start/end frame sections or exact first-frame reuse instructions.
|
|
365
|
+
9. \`storyboard_reference_status\` and \`storyboard_handoff_status\` are pass.
|
|
361
366
|
|
|
362
367
|
## Final Summary
|
|
363
368
|
|
|
@@ -10,6 +10,7 @@ export declare class Seedance20PromptAdapter extends BaseVideoModelPromptAdapter
|
|
|
10
10
|
private getMappingEntries;
|
|
11
11
|
private formatCharacterRoleLine;
|
|
12
12
|
private formatStoryboardRoleLine;
|
|
13
|
+
private hasDanceOrSingingIntent;
|
|
13
14
|
buildPrompt(input: AdapterInput): ModelPromptOutput;
|
|
14
15
|
validate(output: ModelPromptOutput): ModelPromptQa;
|
|
15
16
|
}
|
|
@@ -40,24 +40,37 @@ export class Seedance20PromptAdapter extends BaseVideoModelPromptAdapter {
|
|
|
40
40
|
const storyboardEntry = this.getMappingEntries(input, "storyboard_plan")[0];
|
|
41
41
|
const token = storyboardEntry?.token ?? "@Image2";
|
|
42
42
|
const alias = storyboardEntry?.legacyAlias;
|
|
43
|
-
return `Use ${token} as the shot storyboard reference for composition, blocking, camera direction, timing, action rhythm, and
|
|
43
|
+
return `Use ${token} as the shot storyboard reference and generated storyboard reference image: the complete visual/action/camera/choreography source for beat order, composition, blocking, camera direction, timing, action rhythm, framing variety, and final pose only. Do not copy storyboard text, labels, notes, arrows, panel borders, page headers, watermarks, logos, or alternate character design from ${token}.${alias ? ` Legacy alias: ${alias}.` : ""}`;
|
|
44
|
+
}
|
|
45
|
+
hasDanceOrSingingIntent(input) {
|
|
46
|
+
const combined = [
|
|
47
|
+
input.request.brief,
|
|
48
|
+
input.request.audioIntent,
|
|
49
|
+
input.request.styleIntent,
|
|
50
|
+
...input.request.dialogue.map(line => `${line.speaker}: ${line.text}`)
|
|
51
|
+
].join(" ").toLowerCase();
|
|
52
|
+
return /dance|dancing|choreograph|sing|singing|song|vocal|sarki|sark|soyl|dans/.test(combined);
|
|
44
53
|
}
|
|
45
54
|
buildPrompt(input) {
|
|
46
55
|
const audioPlan = buildAudioPlan(input);
|
|
47
56
|
const storyboardEntry = this.getMappingEntries(input, "storyboard_plan")[0];
|
|
48
57
|
const storyboardToken = storyboardEntry?.token ?? "@Image2";
|
|
49
58
|
const continuityInstruction = input.continuityMode === "continuous-shot"
|
|
50
|
-
?
|
|
51
|
-
: `
|
|
59
|
+
? `Use the generated storyboard reference ${storyboardToken} as the complete visual/action/camera/choreography source for this ${input.request.durationSeconds}-second video. Follow all ${input.storyboardImagePrompt.panelCount} beats sequentially from left-to-right, top-to-bottom as the exact visual beat order within one uninterrupted camera move. Do not reinterpret pose, action, camera angle, emotional progression, framing variety, movement logic, shot order, or final pose. Compress the full ${input.storyboardImagePrompt.panelCount}-beat sequence into the requested duration as fast readable motion snapshots, not full-length actions. No scene cuts throughout, one continuous shot.`
|
|
60
|
+
: `Use the generated storyboard reference ${storyboardToken} as the complete visual/action/camera/choreography source for this ${input.request.durationSeconds}-second video. Follow all ${input.storyboardImagePrompt.panelCount} beats sequentially from left-to-right, top-to-bottom as the exact visual beat order. Do not reinterpret pose, action, camera angle, emotional progression, framing variety, movement logic, shot order, or final pose. Compress the full ${input.storyboardImagePrompt.panelCount}-beat sequence into the requested duration as fast readable motion snapshots, not full-length actions. Use urgent rhythm, storyboard-motivated cuts, quick cuts, match cuts, whip transitions, or motivated camera moves only when the storyboard supports them. Do not add unplanned cuts, extra scene jumps, duplicate performers, or new locations.`;
|
|
52
61
|
const characterEntries = this.getMappingEntries(input, "character_identity");
|
|
53
62
|
const characterTokenText = characterEntries.map(entry => entry.token).join(", ") || "@Image1";
|
|
63
|
+
const performanceEmphasis = this.hasDanceOrSingingIntent(input)
|
|
64
|
+
? "\nFor singing or dance briefs: continuous live singing must show visible breath, synchronized mouth movement, body strain, fabric motion, grounded footwork, floor contact, and phrase-level physical effort across the full movement."
|
|
65
|
+
: "";
|
|
54
66
|
const promptText = `${this.formatCharacterRoleLine(input)}
|
|
55
67
|
${this.formatStoryboardRoleLine(input)}
|
|
56
68
|
|
|
57
69
|
[REFERENCE ROLES]
|
|
58
70
|
- Identity reference: ${characterTokenText} locks face, hair, body proportions, wardrobe, accessories, visible props, and material continuity.
|
|
59
|
-
-
|
|
60
|
-
-
|
|
71
|
+
- Storyboard reference image: ${storyboardToken} is the complete visual/action/camera/choreography source.
|
|
72
|
+
- Camera reference: ${storyboardToken} controls composition, camera direction, framing, screen direction, shot order, framing variety, and lens rhythm only.
|
|
73
|
+
- Action reference: ${storyboardToken} controls blocking, pose logic, timing, action rhythm, phase order, choreography, and emotional progression only.
|
|
61
74
|
- Audio reference: use the Audio Plan text below for dialogue, SFX, ambience, and music intent; do not infer audio from storyboard annotations unless explicitly requested.
|
|
62
75
|
|
|
63
76
|
${continuityInstruction}
|
|
@@ -69,13 +82,13 @@ ${input.request.brief}
|
|
|
69
82
|
${formatPhaseLines(input.interpretation.phases)}
|
|
70
83
|
|
|
71
84
|
[GPT IMAGE 2 STORYBOARD SOURCE]
|
|
72
|
-
Use the generated storyboard image from ${input.storyboardImagePrompt.outputPath} as ${storyboardToken}. It has ${input.storyboardImagePrompt.panelCount} panel(s), follows the shot handoff, and is not an identity source. Treat colored arrows, panel labels,
|
|
85
|
+
Use the generated storyboard image from ${input.storyboardImagePrompt.outputPath} as ${storyboardToken}. It has ${input.storyboardImagePrompt.panelCount} panel(s), follows the shot handoff, and is not an identity source. Treat colored arrows, panel labels, lens notes, framing marks, and page headers as planning annotations only; never render storyboard annotations, arrows, labels, notes, timestamps, page headers, panel borders, or storyboard text into the video.
|
|
73
86
|
|
|
74
87
|
[CAMERA]
|
|
75
88
|
${input.interpretation.cameraPlan.framing}, ${input.interpretation.cameraPlan.movement}, ${input.interpretation.cameraPlan.lens}, ${input.interpretation.cameraPlan.stabilization}. Preserve ${input.interpretation.cameraPlan.screenDirection}.
|
|
76
89
|
|
|
77
90
|
[PERFORMANCE]
|
|
78
|
-
Visible
|
|
91
|
+
Keep the same performer identity from ${characterTokenText}; do not duplicate the character. Visible performance must include breath, mouth movement when dialogue or singing is present, body strain, fabric motion, floor or prop contact, and emotional escalation while preserving exact identity. Acting stays concrete and physically grounded: gaze, breathing, posture, hand behavior, and facial tension evolve from the brief without changing wardrobe or body design.${performanceEmphasis}
|
|
79
92
|
|
|
80
93
|
[AUDIO]
|
|
81
94
|
Dialogue: ${buildDialogueTranscript(input)}.
|
|
@@ -84,9 +97,9 @@ Ambience: ${audioPlan.ambience.join(", ")}.
|
|
|
84
97
|
Music: NONE.
|
|
85
98
|
|
|
86
99
|
[CONTINUITY]
|
|
87
|
-
Identity reference stays locked to ${characterTokenText}. Storyboard ${storyboardToken} controls staging, shot order, pose logic, camera variety, emotional progression, and visual rhythm only. Character design, wardrobe, accessories, and visible props cannot be inherited from the storyboard. Storyboard text, panel borders, arrows, colored marks, lens notes, watermark, logo, and alternate character design are never identity sources and must not appear in the rendered video.
|
|
100
|
+
Identity reference stays locked to ${characterTokenText}. Storyboard ${storyboardToken} controls staging, shot order, pose logic, camera variety, framing variety, emotional progression, choreography, final pose, and visual rhythm only. Character design, wardrobe, accessories, and visible props cannot be inherited from the storyboard. Storyboard text, panel borders, arrows, colored marks, lens notes, page headers, watermark, logo, and alternate character design are never identity sources and must not appear in the rendered video.
|
|
88
101
|
|
|
89
|
-
Avoid: identity drift, face drift, outfit drift, storyboard text, panel borders, colored arrows, annotation marks, lens notes, timestamps, watermark, logo, distorted hands, rubbery motion, flicker, unnatural camera jumps.`;
|
|
102
|
+
Avoid: identity drift, face drift, outfit drift, duplicated performer, storyboard text, annotations, panel borders, colored arrows, annotation marks, lens notes, labels, notes, page headers, timestamps, watermark, logo, distorted hands, rubbery motion, flicker, unnatural camera jumps. No text, no annotations, no labels, no notes, no timestamps, no page headers, no watermark.`;
|
|
90
103
|
const output = {
|
|
91
104
|
model: this.model,
|
|
92
105
|
displayName: getDisplayName(this.model),
|
|
@@ -123,13 +136,16 @@ Avoid: identity drift, face drift, outfit drift, storyboard text, panel borders,
|
|
|
123
136
|
usesStoryboardToken: output.promptText.includes(storyboardToken) && /shot storyboard reference/i.test(output.promptText),
|
|
124
137
|
followsStoryboardOrder: continuityMode === "continuous-shot"
|
|
125
138
|
? hasNoCutsRule
|
|
139
|
+
&& /Follow all \d+ beats sequentially from left-to-right, top-to-bottom/i.test(output.promptText)
|
|
140
|
+
&& /Do not reinterpret pose, action, camera angle, emotional progression/i.test(output.promptText)
|
|
126
141
|
: /left-to-right, top-to-bottom/i.test(output.promptText)
|
|
127
|
-
&& /Do not reinterpret
|
|
142
|
+
&& /Do not reinterpret pose, action, camera angle, emotional progression/i.test(output.promptText),
|
|
128
143
|
separatesReferenceRoles: /Identity reference:/i.test(output.promptText)
|
|
144
|
+
&& /Storyboard reference image:/i.test(output.promptText)
|
|
129
145
|
&& /Camera reference:/i.test(output.promptText)
|
|
130
146
|
&& /Action reference:/i.test(output.promptText)
|
|
131
147
|
&& /Audio reference:/i.test(output.promptText),
|
|
132
|
-
blocksStoryboardIdentitySources: /Storyboard text, panel borders, arrows, colored marks, lens notes, watermark, logo, and alternate character design are never identity sources/i.test(output.promptText),
|
|
148
|
+
blocksStoryboardIdentitySources: /Storyboard text, panel borders, arrows, colored marks, lens notes, page headers, watermark, logo, and alternate character design are never identity sources/i.test(output.promptText),
|
|
133
149
|
continuityMode: continuityMode === "continuous-shot"
|
|
134
150
|
? hasNoCutsRule
|
|
135
151
|
: !hasNoCutsRule && /storyboard-motivated cuts/i.test(output.promptText),
|
|
@@ -4,4 +4,4 @@ export { resolveAssetRoles } from "./asset-role-resolver.js";
|
|
|
4
4
|
export { interpretStoryboard } from "./storyboard-interpreter.js";
|
|
5
5
|
export { renderShotMarkdown, writeStoryboardReferenceOutputs } from "./output-writer.js";
|
|
6
6
|
export { assertSafeStoryboardReferenceRequest, assertStoryboardReferenceBuildPass, validateModelPromptOutput, validatePromptBundle, validateResolvedAssetRoles } from "./validators.js";
|
|
7
|
-
export type { AdapterInput, AudioPlan, CameraPlan, CharacterReferenceSheetPrompt, ContinuityAnchors, DialogueLine, ModelPromptOutput, ModelPromptQa, ModelRouteMetadata, NormalizedVideoPromptRequest, PromptBundle, PromptBundleQa, ProviderAssetMappingEntry, ProviderFileLimitReport, ProviderReferenceTokenPolicy, ReferenceAsset, ReferenceAssetRequirement, ReferenceAssetRole, ReferenceLockStrength, ResolvedAssetRoles, SeedanceContinuityMode, ShotHandoffNote, StoryboardImagePrompt, StoryboardInterpretation, StoryboardPhase, StoryboardPhaseBudget, StoryboardReferenceBuildResult, StoryboardReferencePlan, StoryboardReferencePolicy, StoryboardReferenceWriteResult, VideoModelPromptAdapter, VideoPromptRequest, VisualWorld, VoiceCastEntry } from "./types.js";
|
|
7
|
+
export type { AdapterInput, AudioPlan, CameraPlan, CharacterReferenceSheetPrompt, ContinuityAnchors, DialogueLine, ModelPromptOutput, ModelPromptQa, ModelRouteMetadata, NormalizedVideoPromptRequest, PromptBundle, PromptBundleQa, ProviderAssetMappingEntry, ProviderFileLimitReport, ProviderReferenceTokenPolicy, ReferenceAsset, ReferenceAssetRequirement, ReferenceAssetRole, ReferenceLockStrength, ResolvedAssetRoles, SeedanceContinuityMode, ShotHandoffNote, StoryboardCreationMetadata, StoryboardImagePrompt, StoryboardInterpretation, StoryboardPhase, StoryboardPhaseBudget, StoryboardReferenceBuildResult, StoryboardReferencePlan, StoryboardReferencePolicy, StoryboardReferenceWriteResult, VideoModelPromptAdapter, VideoPromptRequest, VisualWorld, VoiceCastEntry } from "./types.js";
|
|
@@ -169,6 +169,9 @@ ${bundle.storyboardImagePrompt.promptText}
|
|
|
169
169
|
\`\`\`
|
|
170
170
|
`;
|
|
171
171
|
}
|
|
172
|
+
function renderStoryboardPromptAlias(result) {
|
|
173
|
+
return result.bundles.map(renderStoryboardPromptFile).join("\n---\n\n");
|
|
174
|
+
}
|
|
172
175
|
function renderQaReport(result) {
|
|
173
176
|
const models = result.request.targetModels.join(", ");
|
|
174
177
|
const rows = result.bundles
|
|
@@ -219,6 +222,7 @@ export async function writeStoryboardReferenceOutputs(result, rootDir = process.
|
|
|
219
222
|
const written = [];
|
|
220
223
|
const planPath = join(outputRoot, "storyboard-reference-plan.json");
|
|
221
224
|
const projectInfoPath = join(outputRoot, "project-info.md");
|
|
225
|
+
const storyboardPromptAliasPath = join(outputRoot, "storyboard-prompt.md");
|
|
222
226
|
const qaPath = join(outputRoot, "reports", "STORYBOARD-REFERENCE-QA.md");
|
|
223
227
|
await writeText(planPath, `${JSON.stringify(result.plan, null, 2)}\n`);
|
|
224
228
|
written.push(planPath);
|
|
@@ -234,6 +238,8 @@ export async function writeStoryboardReferenceOutputs(result, rootDir = process.
|
|
|
234
238
|
- Safety context: ${result.request.safetyContext}
|
|
235
239
|
`);
|
|
236
240
|
written.push(projectInfoPath);
|
|
241
|
+
await writeText(storyboardPromptAliasPath, renderStoryboardPromptAlias(result));
|
|
242
|
+
written.push(storyboardPromptAliasPath);
|
|
237
243
|
for (const prompt of result.characterReferenceSheetPrompts) {
|
|
238
244
|
const promptPath = resolve(rootDir, prompt.outputPath);
|
|
239
245
|
await writeText(promptPath, renderCharacterSheetPrompt(prompt));
|
|
@@ -42,10 +42,17 @@ function resolvePromptAdapter(model) {
|
|
|
42
42
|
}
|
|
43
43
|
return adapter;
|
|
44
44
|
}
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
45
|
+
const MAX_STORYBOARD_SHEET_PANELS = 12;
|
|
46
|
+
const DEFAULT_STORYBOARD_SHEET_PANELS = 12;
|
|
47
|
+
function getStoryboardSheetPanelCount(request) {
|
|
48
|
+
const panelCount = request.storyboardPanelCountHint ?? DEFAULT_STORYBOARD_SHEET_PANELS;
|
|
49
|
+
if (panelCount > MAX_STORYBOARD_SHEET_PANELS) {
|
|
50
|
+
throw new Error(`Invalid storyboardPanelCountHint. Expected 1-${MAX_STORYBOARD_SHEET_PANELS} panels for one GPT Image 2 storyboard sheet.`);
|
|
51
|
+
}
|
|
52
|
+
return panelCount;
|
|
53
|
+
}
|
|
54
|
+
function getVideoPhaseCount(request, phaseBudget) {
|
|
55
|
+
return request.shotCountHint ?? phaseBudget.recommendedMaxPhases;
|
|
49
56
|
}
|
|
50
57
|
function buildShotId(index) {
|
|
51
58
|
return `SHOT${String(index + 1).padStart(2, "0")}`;
|
|
@@ -172,37 +179,46 @@ function buildStoryboardImagePrompt(input) {
|
|
|
172
179
|
? `Use external storyboard guide tokens ${assets.storyboards.map(storyboard => storyboard.token).join(", ")} only for composition, blocking, camera direction, timing, and action rhythm.`
|
|
173
180
|
: "No external storyboard guide is required; infer the board from the screenplay brief, continuity notes, and visual world.";
|
|
174
181
|
const phaseDirection = interpretation.phases
|
|
175
|
-
.map(phase => `
|
|
182
|
+
.map(phase => `Phase ${phase.index}: ${phase.job}; ${phase.subjectAction}; camera behavior: ${phase.cameraBehavior}; background behavior: ${phase.backgroundBehavior}.`)
|
|
176
183
|
.join(" ");
|
|
184
|
+
const panelLabel = input.storyboardSheetPanelCount === 1
|
|
185
|
+
? "1 cinematic panel"
|
|
186
|
+
: `${input.storyboardSheetPanelCount} cinematic panels`;
|
|
177
187
|
const continuityStyle = interpretation.phases.length <= 1
|
|
178
|
-
?
|
|
179
|
-
:
|
|
188
|
+
? `Because this is a single uninterrupted beat, still create ${panelLabel} as sequential motion snapshots of one continuous camera move. Each panel must clarify entry pose, motion direction, body mechanics, camera shift, and final body intention without implying separate scenes.`
|
|
189
|
+
: `Read panels left-to-right, top-to-bottom as a planned visual beat sequence. Create ${input.storyboardSheetPanelCount} distinct beat snapshot${input.storyboardSheetPanelCount === 1 ? "" : "s"} distributed across the video phases. Each panel must show a distinct body pose, camera size/angle, movement logic, and emotional escalation, not decorative micro-poses.`;
|
|
180
190
|
return {
|
|
181
191
|
shotId,
|
|
182
192
|
outputPath: `${request.outputDir}/storyboard-prompts/${shotId}-GPT-IMAGE-2-STORYBOARD.md`,
|
|
183
193
|
provider: "gpt-image-2",
|
|
184
194
|
aspectRatio: "16:9",
|
|
185
|
-
panelCount:
|
|
186
|
-
style: "
|
|
195
|
+
panelCount: input.storyboardSheetPanelCount,
|
|
196
|
+
style: "raw-pencil-production-storyboard",
|
|
187
197
|
characterSheetIds,
|
|
188
198
|
externalStoryboardGuideIds,
|
|
189
199
|
previousShotHandoff: input.previousShotHandoff,
|
|
190
200
|
nextShotHandoff: input.nextShotHandoff,
|
|
191
|
-
promptText: `
|
|
201
|
+
promptText: `HARD NEGATIVE STORYBOARD STYLE LOCK:
|
|
202
|
+
Do not create photorealistic cinematic stills.
|
|
203
|
+
Do not create full-color rendered panels.
|
|
204
|
+
Do not create concept art, movie frames, underwater/color-grade panels, 3D render, anime, CGI, or polished illustration.
|
|
205
|
+
Only annotation arrows/marks may use color; all storyboard artwork remains black pencil on white paper.
|
|
206
|
+
|
|
207
|
+
REFERENCE LOCK: Use the generated character sheet reference${characterReferenceSheetPrompts.length === 1 ? "" : "s"} (${sheetRefs}) as the only source for character identity, face, hair, skin texture, body proportions, wardrobe, accessories, material behavior, and visible props.
|
|
192
208
|
|
|
193
209
|
Keep same: every character identity detail from the character sheet${characterReferenceSheetPrompts.length === 1 ? "" : "s"}, the declared visual world, screen direction, environmental continuity, lighting direction, prop continuity, and shot handoff logic. Storyboard text, arrows, labels, panel borders, watermarks, logos, and alternate character designs are never identity sources.
|
|
194
210
|
|
|
195
|
-
Change only:
|
|
211
|
+
Change only: Create a raw ${shotId} storyboard focused on intense physical movement and clear cinematic action from this scene: ${request.brief}. White paper production layout. 16:9 storyboard sheet, ${panelLabel}. Use exactly ${panelLabel}. The storyboard controls composition, blocking, camera direction, timing, phase order, action rhythm, and emotional progression only. ${externalGuideText}
|
|
196
212
|
|
|
197
|
-
Storyboard drawing style: raw contemporary
|
|
213
|
+
Storyboard drawing style: raw contemporary production storyboard with black-and-white rough pencil linework. Actual storyboard drawings must be black and white only. Use rough pencil lines, minimal detail, fast gesture drawing energy, simple anatomy construction, strong silhouette readability, lightweight unfinished choreography previs, not polished concept art or final render.
|
|
198
214
|
|
|
199
215
|
Panel direction: ${continuityStyle} The scene brief is: ${request.brief} Previous handoff: ${input.previousShotHandoff}. Next handoff: ${input.nextShotHandoff}. Planned panel actions: ${phaseDirection}
|
|
200
216
|
|
|
201
|
-
Camera and staging: show ${interpretation.cameraPlan.framing}, ${interpretation.cameraPlan.movement}, ${interpretation.cameraPlan.lens}; preserve ${interpretation.cameraPlan.screenDirection}. Use cinematic
|
|
217
|
+
Camera and staging: show ${interpretation.cameraPlan.framing}, ${interpretation.cameraPlan.movement}, ${interpretation.cameraPlan.lens}; preserve ${interpretation.cameraPlan.screenDirection}. Use cinematic arthouse camerawork with handheld energy, whip pans, orbit movement, overhead shots, low angles, side silhouettes, aggressive close-ups, long lens compression, inserts, and extreme negative space whenever motivated by the beat. Maintain the same environment, lighting, atmosphere, foreground, midground, and background continuity: ${interpretation.visualWorld.environment}; ${interpretation.visualWorld.lighting}; ${interpretation.visualWorld.foreground}; ${interpretation.visualWorld.midground}; ${interpretation.visualWorld.background}; ${interpretation.visualWorld.atmosphere}.
|
|
202
218
|
|
|
203
219
|
Annotation color system: red arrows for body movement, blue arrows for camera movement, green marks for framing/composition, orange marks for lighting direction, purple marks for vocal or emotional emphasis when relevant, black text only for very short lens notes and panel labels. No timestamps.
|
|
204
220
|
|
|
205
|
-
Every panel must contain visible momentum or clear behavioral change: gaze shift, breath, weight transfer, contact with ground/prop, fabric motion, hand tension, or a readable pose transition. Keep the location minimal and readable.
|
|
221
|
+
Every panel must contain visible momentum. Every panel must contain visible motion, strong body momentum, or clear behavioral change: gaze shift, breath, weight transfer, contact with ground/prop, fabric motion, hand tension, floor contact, hair or clothing motion, or a readable pose transition. Avoid static standing poses unless explicitly required by the beat. Keep the location minimal and readable. End with one overwhelming final readable movement pose or composition that preserves the shot's emotional endpoint.
|
|
206
222
|
|
|
207
223
|
Avoid: identity drift, face drift, hair drift, wardrobe drift, prop drift, material drift, alternate character design, static standing poses unless explicitly required by the beat, timestamps, long text notes, storyboard text becoming scene text, new characters, new locations, logos, watermarks, decorative borders, broken perspective, impossible contact or weight, inconsistent screen direction, inconsistent light direction, photorealistic final-render polish, cartoon style, anime style, CGI look, unsafe public-figure likeness, trademarked branding.`
|
|
208
224
|
};
|
|
@@ -291,6 +307,54 @@ function buildProviderReferenceTokens(providerAssetMapping) {
|
|
|
291
307
|
audioReference: "@audio1"
|
|
292
308
|
};
|
|
293
309
|
}
|
|
310
|
+
function buildStoryboardCreationMetadata(request, storyboardImagePrompt, providerAssetMapping) {
|
|
311
|
+
const storyboardEntry = Object.values(providerAssetMapping)
|
|
312
|
+
.find(entry => entry.role === "storyboard_plan");
|
|
313
|
+
return {
|
|
314
|
+
provider: "gpt-image-2",
|
|
315
|
+
prompt_path: storyboardImagePrompt.outputPath,
|
|
316
|
+
alias_path: `${request.outputDir}/storyboard-prompt.md`,
|
|
317
|
+
source_mode: storyboardImagePrompt.externalStoryboardGuideIds.length > 0
|
|
318
|
+
? "generated-with-external-guide"
|
|
319
|
+
: "generated",
|
|
320
|
+
panel_count: storyboardImagePrompt.panelCount,
|
|
321
|
+
default_panel_count: DEFAULT_STORYBOARD_SHEET_PANELS,
|
|
322
|
+
style_contract: "raw-pencil-production-storyboard",
|
|
323
|
+
forbidden_visual_modes: [
|
|
324
|
+
"photorealistic stills",
|
|
325
|
+
"full-color panels",
|
|
326
|
+
"concept-art strip",
|
|
327
|
+
"CGI render"
|
|
328
|
+
],
|
|
329
|
+
annotation_colors_allowed: true,
|
|
330
|
+
reading_order: "left-to-right, top-to-bottom",
|
|
331
|
+
character_sheet_ids: storyboardImagePrompt.characterSheetIds,
|
|
332
|
+
external_storyboard_guide_ids: storyboardImagePrompt.externalStoryboardGuideIds,
|
|
333
|
+
seedance_token: storyboardEntry?.token ?? "@Image2",
|
|
334
|
+
annotation_policy: {
|
|
335
|
+
rendered_in_video: false,
|
|
336
|
+
color_system: {
|
|
337
|
+
red: "body movement",
|
|
338
|
+
blue: "camera movement",
|
|
339
|
+
green: "framing / composition",
|
|
340
|
+
orange: "lighting direction",
|
|
341
|
+
purple: "vocal / emotional emphasis",
|
|
342
|
+
black: "short lens notes and panel labels"
|
|
343
|
+
},
|
|
344
|
+
forbidden_in_video: [
|
|
345
|
+
"arrows",
|
|
346
|
+
"annotation marks",
|
|
347
|
+
"lens notes",
|
|
348
|
+
"panel labels",
|
|
349
|
+
"timestamps",
|
|
350
|
+
"panel borders",
|
|
351
|
+
"watermark",
|
|
352
|
+
"logo"
|
|
353
|
+
]
|
|
354
|
+
},
|
|
355
|
+
prompt_text: storyboardImagePrompt.promptText
|
|
356
|
+
};
|
|
357
|
+
}
|
|
294
358
|
function buildStoryboardReferencePolicy(request, phaseBudget, providerFileLimits, bundles, providerReferenceTokens, maxPhases, splitRequired) {
|
|
295
359
|
const continuityModes = Array.from(new Set(bundles.map(bundle => bundle.continuityMode)));
|
|
296
360
|
return {
|
|
@@ -325,9 +389,9 @@ function buildStoryboardReferencePolicy(request, phaseBudget, providerFileLimits
|
|
|
325
389
|
provider: "gpt-image-2",
|
|
326
390
|
generated_per_shot: true,
|
|
327
391
|
aspect_ratio: "16:9",
|
|
328
|
-
max_panels_per_shot:
|
|
392
|
+
max_panels_per_shot: MAX_STORYBOARD_SHEET_PANELS,
|
|
329
393
|
panel_budget: phaseBudget.policy,
|
|
330
|
-
professional_prompt_target_words: "
|
|
394
|
+
professional_prompt_target_words: "240-420 words per shot storyboard prompt"
|
|
331
395
|
},
|
|
332
396
|
role_separation: {
|
|
333
397
|
character_identity: `${providerReferenceTokens.characterIdentities.join(", ")} control identity, face, hair, body proportions, wardrobe, accessories, and visible props.`,
|
|
@@ -376,15 +440,16 @@ export function buildStoryboardReferencePromptBundles(input) {
|
|
|
376
440
|
const voiceCast = buildVoiceCast(request);
|
|
377
441
|
const phaseBudget = buildStoryboardPhaseBudget(request.durationSeconds, request.storyboardReferenceMode.maxStoryboardPhases);
|
|
378
442
|
const providerFileLimits = buildProviderFileLimitReport(request, characterReferenceSheetPrompts.length + 1);
|
|
379
|
-
const
|
|
443
|
+
const storyboardSheetPanelCount = getStoryboardSheetPanelCount(request);
|
|
444
|
+
const videoPhaseCount = getVideoPhaseCount(request, phaseBudget);
|
|
380
445
|
const maxPhases = phaseBudget.effectiveMaxStoryboardPhases;
|
|
381
|
-
const splitRequired =
|
|
446
|
+
const splitRequired = videoPhaseCount > maxPhases;
|
|
382
447
|
if (splitRequired && !request.storyboardReferenceMode.splitStoryboardOverload) {
|
|
383
|
-
throw new Error(`Storyboard has ${
|
|
448
|
+
throw new Error(`Storyboard has ${videoPhaseCount} video phases, which exceeds maxStoryboardPhases=${maxPhases}. Enable splitStoryboardOverload or split the storyboard manually.`);
|
|
384
449
|
}
|
|
385
450
|
const phaseCounts = splitRequired && request.storyboardReferenceMode.splitStoryboardOverload
|
|
386
|
-
? getSplitPhaseCounts(
|
|
387
|
-
: [Math.min(
|
|
451
|
+
? getSplitPhaseCounts(videoPhaseCount, maxPhases)
|
|
452
|
+
: [Math.min(videoPhaseCount, maxPhases)];
|
|
388
453
|
const generatedAt = new Date().toISOString();
|
|
389
454
|
const bundles = [];
|
|
390
455
|
let previousShotHandoff = "Project opening: start from the screenplay's first visual beat.";
|
|
@@ -402,11 +467,13 @@ export function buildStoryboardReferencePromptBundles(input) {
|
|
|
402
467
|
assets,
|
|
403
468
|
shotId,
|
|
404
469
|
interpretation,
|
|
470
|
+
storyboardSheetPanelCount,
|
|
405
471
|
characterReferenceSheetPrompts,
|
|
406
472
|
previousShotHandoff,
|
|
407
473
|
nextShotHandoff: handoffNote.exitHandoff
|
|
408
474
|
});
|
|
409
475
|
const providerAssetMapping = buildProviderAssetMapping(assets, characterReferenceSheetPrompts, storyboardImagePrompt);
|
|
476
|
+
const storyboard_creation = buildStoryboardCreationMetadata(request, storyboardImagePrompt, providerAssetMapping);
|
|
410
477
|
const referenceAssetRequirements = buildReferenceAssetRequirements(providerAssetMapping);
|
|
411
478
|
const modelPrompts = buildModelPrompts(request, {
|
|
412
479
|
assets,
|
|
@@ -431,6 +498,7 @@ export function buildStoryboardReferencePromptBundles(input) {
|
|
|
431
498
|
providerFileLimits,
|
|
432
499
|
handoffNote,
|
|
433
500
|
storyboardImagePrompt,
|
|
501
|
+
storyboard_creation,
|
|
434
502
|
referenceAssetRequirements,
|
|
435
503
|
providerAssetMapping,
|
|
436
504
|
qa: { verdict: "pass", checks: {}, issues: [], splitRequired },
|
|
@@ -128,13 +128,46 @@ export interface StoryboardImagePrompt {
|
|
|
128
128
|
provider: "gpt-image-2";
|
|
129
129
|
aspectRatio: "16:9";
|
|
130
130
|
panelCount: number;
|
|
131
|
-
style: "
|
|
131
|
+
style: "raw-pencil-production-storyboard";
|
|
132
132
|
characterSheetIds: string[];
|
|
133
133
|
externalStoryboardGuideIds: string[];
|
|
134
134
|
previousShotHandoff: string;
|
|
135
135
|
nextShotHandoff: string;
|
|
136
136
|
promptText: string;
|
|
137
137
|
}
|
|
138
|
+
export interface StoryboardCreationMetadata {
|
|
139
|
+
provider: "gpt-image-2";
|
|
140
|
+
prompt_path: string;
|
|
141
|
+
alias_path: string;
|
|
142
|
+
source_mode: "generated" | "generated-with-external-guide";
|
|
143
|
+
panel_count: number;
|
|
144
|
+
default_panel_count: 12;
|
|
145
|
+
style_contract: "raw-pencil-production-storyboard";
|
|
146
|
+
forbidden_visual_modes: [
|
|
147
|
+
"photorealistic stills",
|
|
148
|
+
"full-color panels",
|
|
149
|
+
"concept-art strip",
|
|
150
|
+
"CGI render"
|
|
151
|
+
];
|
|
152
|
+
annotation_colors_allowed: true;
|
|
153
|
+
reading_order: "left-to-right, top-to-bottom";
|
|
154
|
+
character_sheet_ids: string[];
|
|
155
|
+
external_storyboard_guide_ids: string[];
|
|
156
|
+
seedance_token: string;
|
|
157
|
+
annotation_policy: {
|
|
158
|
+
rendered_in_video: false;
|
|
159
|
+
color_system: {
|
|
160
|
+
red: "body movement";
|
|
161
|
+
blue: "camera movement";
|
|
162
|
+
green: "framing / composition";
|
|
163
|
+
orange: "lighting direction";
|
|
164
|
+
purple: "vocal / emotional emphasis";
|
|
165
|
+
black: "short lens notes and panel labels";
|
|
166
|
+
};
|
|
167
|
+
forbidden_in_video: string[];
|
|
168
|
+
};
|
|
169
|
+
prompt_text: string;
|
|
170
|
+
}
|
|
138
171
|
export type ProviderAssetMappingRole = "character_identity" | "storyboard_plan" | "style_reference" | "camera_reference" | "action_reference" | "prop_reference";
|
|
139
172
|
export interface ProviderAssetMappingEntry {
|
|
140
173
|
token: string;
|
|
@@ -254,6 +287,7 @@ export interface PromptBundle {
|
|
|
254
287
|
providerFileLimits: ProviderFileLimitReport;
|
|
255
288
|
handoffNote: ShotHandoffNote;
|
|
256
289
|
storyboardImagePrompt: StoryboardImagePrompt;
|
|
290
|
+
storyboard_creation: StoryboardCreationMetadata;
|
|
257
291
|
referenceAssetRequirements: ReferenceAssetRequirement[];
|
|
258
292
|
providerAssetMapping: Record<string, ProviderAssetMappingEntry>;
|
|
259
293
|
qa: PromptBundleQa;
|
|
@@ -113,6 +113,15 @@ export function validatePromptBundle(bundle, assets, voiceCast = []) {
|
|
|
113
113
|
hasCharacterReference: assets.characters.length >= 1,
|
|
114
114
|
hasStoryboardReference: assets.storyboards.length >= 1 || Boolean(bundle.storyboardImagePrompt),
|
|
115
115
|
hasStoryboardImagePrompt: Boolean(bundle.storyboardImagePrompt?.promptText.trim()),
|
|
116
|
+
hasStoryboardCreationMetadata: Boolean(bundle.storyboard_creation?.prompt_text.trim())
|
|
117
|
+
&& bundle.storyboard_creation?.prompt_text === bundle.storyboardImagePrompt.promptText
|
|
118
|
+
&& bundle.storyboard_creation?.prompt_path === bundle.storyboardImagePrompt.outputPath
|
|
119
|
+
&& bundle.storyboard_creation?.panel_count === bundle.storyboardImagePrompt.panelCount
|
|
120
|
+
&& bundle.storyboard_creation?.default_panel_count === 12
|
|
121
|
+
&& bundle.storyboard_creation?.style_contract === "raw-pencil-production-storyboard"
|
|
122
|
+
&& bundle.storyboard_creation?.forbidden_visual_modes.includes("photorealistic stills")
|
|
123
|
+
&& bundle.storyboard_creation?.annotation_colors_allowed === true
|
|
124
|
+
&& bundle.storyboard_creation?.annotation_policy.rendered_in_video === false,
|
|
116
125
|
storyboardPromptHasReferenceLockStructure: hasGptImageStillPromptContract(bundle.storyboardImagePrompt?.promptText ?? ""),
|
|
117
126
|
hasAvoidLineEverywhere: Object.values(bundle.modelPrompts).every(output => Boolean(output) && hasAvoidOrNegativePrompt(output.promptText)),
|
|
118
127
|
storyboardPromptHasAvoidLine: hasAvoidOrNegativePrompt(bundle.storyboardImagePrompt?.promptText ?? ""),
|
package/build/lib/templates.js
CHANGED
|
@@ -35,7 +35,7 @@ function buildStoryboardPlatformGuard(config) {
|
|
|
35
35
|
- Do not generate main-shot \`ILK FRAME\`, \`İLK FRAME\`, or \`SON FRAME\` sections.
|
|
36
36
|
- Do not use exact first-frame reuse instructions, \`SHOTNN_START\`, \`SHOTNN_END\`, or mandatory Start+End transition fields.
|
|
37
37
|
- If no character reference is available through the user, an in-context image, \`--character-ref\`, or \`refs/character.png\`, stop and request one.
|
|
38
|
-
- Required storyboard outputs: \`${config.outputDir}/storyboard-reference-plan.json\`, \`${config.outputDir}/reference-prep/\`, \`${config.outputDir}/storyboard-prompts/\`, \`${config.outputDir}/prompt-bundles/\`, \`${config.outputDir}/shots/SHOTNN.md\`, and \`${config.outputDir}/reports/STORYBOARD-REFERENCE-QA.md\`.
|
|
38
|
+
- Required storyboard outputs: \`${config.outputDir}/storyboard-reference-plan.json\`, \`${config.outputDir}/storyboard-prompt.md\`, \`${config.outputDir}/reference-prep/\`, \`${config.outputDir}/storyboard-prompts/\`, \`${config.outputDir}/prompt-bundles/\`, \`${config.outputDir}/shots/SHOTNN.md\`, and \`${config.outputDir}/reports/STORYBOARD-REFERENCE-QA.md\`.
|
|
39
39
|
`;
|
|
40
40
|
}
|
|
41
41
|
function buildSeedanceProfile(active, storyboardReferenceActive = false, maxStoryboardPhases = 4) {
|
|
@@ -13,7 +13,7 @@ Use this skill when the user provides:
|
|
|
13
13
|
- a video brief or scenario text
|
|
14
14
|
- optional external storyboard guide images
|
|
15
15
|
|
|
16
|
-
The output is a production workflow, not only a video prompt. First create one reusable GPT Image 2 character sheet prompt per reference character. Then create one GPT Image 2 storyboard prompt per `SHOTNN.md`. The generated shot storyboard is the staging reference for the final video model prompt.
|
|
16
|
+
The output is a production workflow, not only a video prompt. First create one reusable GPT Image 2 character sheet prompt per reference character. Then create one GPT Image 2 storyboard prompt per `SHOTNN.md`. If no external storyboard image is supplied, this generated prompt is the mandatory storyboard bootstrap step. The generated shot storyboard is the staging reference for the final video model prompt.
|
|
17
17
|
|
|
18
18
|
## Reference Prep
|
|
19
19
|
|
|
@@ -36,11 +36,13 @@ For each shot, generate a professional GPT Image 2 storyboard prompt:
|
|
|
36
36
|
|
|
37
37
|
- provider: `gpt-image-2`
|
|
38
38
|
- aspect ratio: `16:9`
|
|
39
|
-
- panel budget:
|
|
40
|
-
-
|
|
41
|
-
-
|
|
39
|
+
- storyboard sheet panel budget: default is 12 cinematic panels in one GPT Image 2 storyboard sheet; an explicit storyboard panel hint may request 1-12 panels
|
|
40
|
+
- video phase budget: 4-6s = 1-2 phases, 7-10s = 2-3 phases, 11-15s = 3-4 phases
|
|
41
|
+
- hard cap: max 4 video phases per shot unless the configured project cap is lower
|
|
42
|
+
- split policy: 5+ distinct real video phases, scene changes, or location/action blocks must become separate chained `SHOTNN.md` files; 5-12 storyboard sheet panels alone do not force a split
|
|
42
43
|
- target detail: dense professional storyboard direction, concrete blocking and camera language, no decorative prose
|
|
43
|
-
- storyboard art grammar: black
|
|
44
|
+
- storyboard art grammar: white paper 16:9 production storyboard sheet, actual drawings black and white only, rough pencil lines, minimal detail, fast gesture drawing energy, simple anatomy construction, strong silhouette readability, unfinished previsualization feel
|
|
45
|
+
- hard negative style lock: do not create photorealistic cinematic stills, full-color rendered panels, concept art, movie frames, underwater/color-grade panels, 3D render, anime, CGI, or polished illustration
|
|
44
46
|
- annotation grammar: red arrows = body movement, blue arrows = camera movement, green marks = framing/composition, orange marks = lighting direction, purple marks = vocal/emotional emphasis, black text = very short lens notes and panel labels
|
|
45
47
|
- continuity: include previous shot handoff, next shot handoff, shared `visual_world`, screen direction, lighting, and action rhythm
|
|
46
48
|
|
|
@@ -75,9 +77,10 @@ Seedance 2.0:
|
|
|
75
77
|
- Map character sheet images to `@Image1`, `@Image2`, ... with legacy aliases `@image1`, `@image2`, ...
|
|
76
78
|
- Map the generated shot storyboard to the next image token, for example one character means `@Image2`, two characters means `@Image3`.
|
|
77
79
|
- Character image tokens control identity, face, body proportions, wardrobe, accessories, and visible props.
|
|
78
|
-
- The storyboard token controls composition, blocking, camera direction, timing, action rhythm, and phase order only.
|
|
79
|
-
- Follow
|
|
80
|
-
-
|
|
80
|
+
- The storyboard token is the complete visual/action/camera/choreography source and controls composition, blocking, camera direction, timing, action rhythm, framing variety, final pose, and phase order only.
|
|
81
|
+
- Follow all storyboard beats left-to-right, top-to-bottom. Do not reinterpret pose, action, camera angle, emotional progression, framing variety, movement logic, shot order, or final pose.
|
|
82
|
+
- Compress the full 12-beat default storyboard sheet into the requested duration as readable motion snapshots while preserving the duration-aware video phase budget.
|
|
83
|
+
- Treat storyboard arrows, labels, notes, lens notes, page headers, panel borders, and colored marks as planning annotations only; never render them into the video.
|
|
81
84
|
- Use explicit timeline phases when the storyboard has multiple beats.
|
|
82
85
|
- Use `No scene cuts throughout, one continuous shot` only for a true single uninterrupted camera move.
|
|
83
86
|
- For multi-phase storyboard prompts, use only the planned phase transitions and do not add unplanned cuts.
|
|
@@ -108,6 +111,7 @@ Each shot file contains:
|
|
|
108
111
|
- provider reference tokens
|
|
109
112
|
- GPT Image 2 storyboard prompt
|
|
110
113
|
- storyboard interpretation
|
|
114
|
+
- storyboard_creation metadata in `SHOTNN.bundle.json`
|
|
111
115
|
- audio plan
|
|
112
116
|
- prompt bundle for requested models
|
|
113
117
|
- QA verdict
|
|
@@ -116,6 +120,7 @@ Generated files:
|
|
|
116
120
|
|
|
117
121
|
```text
|
|
118
122
|
$OUTPUT_DIR/storyboard-reference-plan.json
|
|
123
|
+
$OUTPUT_DIR/storyboard-prompt.md
|
|
119
124
|
$OUTPUT_DIR/reference-prep/CHARACTER-SHEET-*.md
|
|
120
125
|
$OUTPUT_DIR/storyboard-prompts/SHOTNN-GPT-IMAGE-2-STORYBOARD.md
|
|
121
126
|
$OUTPUT_DIR/prompt-bundles/SHOTNN.bundle.json
|