@milenyumai/film-kit 2.2.0 → 2.3.0
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 +68 -17
- package/build/index.d.ts +1 -1
- package/build/lib/cli.js +2 -2
- package/build/lib/film-kit.js +6 -4
- package/build/lib/storyboard-reference/adapters/kling30.js +3 -1
- package/build/lib/storyboard-reference/adapters/seedance20.d.ts +4 -0
- package/build/lib/storyboard-reference/adapters/seedance20.js +72 -13
- package/build/lib/storyboard-reference/adapters/veo31.js +3 -1
- package/build/lib/storyboard-reference/index.d.ts +1 -1
- package/build/lib/storyboard-reference/output-writer.js +84 -6
- package/build/lib/storyboard-reference/prompt-bundle-builder.js +295 -8
- package/build/lib/storyboard-reference/request-normalizer.js +8 -4
- package/build/lib/storyboard-reference/storyboard-interpreter.d.ts +3 -1
- package/build/lib/storyboard-reference/storyboard-interpreter.js +21 -1
- package/build/lib/storyboard-reference/types.d.ts +151 -2
- package/build/lib/storyboard-reference/validators.js +2 -5
- package/build/lib/templates.js +10 -6
- package/content/ARCHITECTURE.md +4 -4
- package/content/MASTER.md +2 -2
- package/content/RULES.md +4 -4
- package/content/agents/prompt-engineer.md +7 -7
- package/content/skills/prompt-structure/SKILL.md +14 -11
- package/content/skills/reference-locking/SKILL.md +6 -4
- package/content/skills/semantic-consistency/SKILL.md +1 -1
- package/content/skills/storyboard-reference/SKILL.md +54 -13
- package/content/workflows/generate-storyboard.md +37 -16
- package/content/workflows/generate.md +7 -7
- package/content/workflows/safety-check.md +2 -2
- package/package.json +1 -1
- package/packages/gpt-image-smart/content/skills/storyboard-reference/SKILL.md +104 -12
- package/packages/gpt-image-smart/content/workflows/generate-storyboard.md +89 -12
- package/packages/hybrid/content/skills/storyboard-reference/SKILL.md +104 -12
- package/packages/hybrid/content/workflows/generate-storyboard.md +89 -12
- package/packages/hybrid-smart/content/skills/storyboard-reference/SKILL.md +104 -12
- package/packages/hybrid-smart/content/workflows/generate-storyboard.md +89 -12
- package/packages/multi/build/cli.js +39 -0
- package/packages/multi/build/index.d.ts +1 -1
- package/packages/multi/build/lib/configure.js +208 -1
- package/packages/multi/build/lib/defaults.d.ts +3 -1
- package/packages/multi/build/lib/defaults.js +32 -0
- package/packages/multi/build/lib/templates.js +146 -60
- package/packages/multi/build/lib/types.d.ts +16 -0
- package/packages/multi/content/agents/continuity-editor.md +6 -6
- package/packages/multi/content/agents/delivery-editor.md +2 -2
- package/packages/multi/content/agents/lead-director.md +18 -10
- package/packages/multi/content/agents/semantic-auditor.md +4 -5
- package/packages/multi/content/agents/shot-generator.md +9 -27
- package/packages/multi/content/skills/storyboard-reference/SKILL.md +104 -12
- package/packages/multi/content/workflows/chain-multi.md +4 -4
- package/packages/multi/content/workflows/generate-multi.md +6 -6
- package/packages/multi/content/workflows/generate-storyboard.md +89 -12
- package/packages/multi/content/workflows/generate-teammate.md +8 -14
- package/packages/multi/content/workflows/safety-check-multi.md +7 -11
- package/packages/studio/content/skills/storyboard-reference/SKILL.md +104 -12
- package/packages/studio/content/workflows/generate-storyboard.md +89 -12
|
@@ -1,19 +1,96 @@
|
|
|
1
1
|
---
|
|
2
|
-
description: Generate storyboard-
|
|
2
|
+
description: Generate character sheet prompts, per-shot GPT Image 2 storyboard prompts, and model-aware video prompt bundles from character references and a video brief
|
|
3
3
|
---
|
|
4
4
|
|
|
5
|
-
# /generate-storyboard
|
|
5
|
+
# /generate-storyboard - Storyboard Reference Video Prompt Mode
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
## Preconditions
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
- Character reference image exists.
|
|
10
|
+
- User brief or scenario text exists.
|
|
11
|
+
- Optional storyboard guide images may exist, but they are not required.
|
|
12
|
+
- `storyboard-reference` mode is explicitly requested or configured.
|
|
10
13
|
|
|
11
|
-
|
|
12
|
-
2. Bind `@storyboard1` as `storyboard_plan`, staging only.
|
|
13
|
-
3. Interpret storyboard panels: 1 continuous arc, 2-4 internal phases, 5+ split shots.
|
|
14
|
-
4. Build `visual_world`, continuity anchors, and model-specific prompts.
|
|
15
|
-
5. Generate Seedance, Veo, and Kling prompt sections for the requested model subset.
|
|
16
|
-
6. Run QA for reference lock, storyboard role separation, model grammar, avoid line, audio plan, and safety.
|
|
17
|
-
7. Write all outputs under `$OUTPUT_DIR`.
|
|
14
|
+
## Read Order
|
|
18
15
|
|
|
19
|
-
|
|
16
|
+
1. `.agent/model-profile.md`
|
|
17
|
+
2. `.agent/skills/safety-compliance/SKILL.md`
|
|
18
|
+
3. `.agent/skills/reference-locking/SKILL.md`
|
|
19
|
+
4. `.agent/skills/storyboard-reference/SKILL.md`
|
|
20
|
+
5. `.agent/skills/semantic-consistency/SKILL.md`
|
|
21
|
+
6. `.agent/skills/visual-modes/SKILL.md`
|
|
22
|
+
7. `.agent/skills/audio-design/SKILL.md` when dialogue, SFX, ambience, or voiceover exists
|
|
23
|
+
8. `.agent/skills/prompt-structure/SKILL.md`
|
|
24
|
+
|
|
25
|
+
## Flow
|
|
26
|
+
|
|
27
|
+
1. Confirm asset roles:
|
|
28
|
+
- `@character1`, `@character2`, ...: `character_identity`, exact lock
|
|
29
|
+
- optional `@storyboard1`, `@storyboard2`, ...: external storyboard guides, staging only
|
|
30
|
+
2. Generate one GPT Image 2 character sheet prompt per character reference:
|
|
31
|
+
- 16:9 production storyboard sheet
|
|
32
|
+
- front full body, back full body, left profile, right profile, three-quarter full body, close-up face
|
|
33
|
+
- exact identity, wardrobe, accessories, and visible props
|
|
34
|
+
- no labels, text, logos, watermarks, alternate designs, or extra characters
|
|
35
|
+
3. Confirm target models: `veo31`, `seedance-2.0`, `kling-3.0`, or a user-provided subset.
|
|
36
|
+
4. Select shot storyboard panel budget:
|
|
37
|
+
- 4-6 seconds: 1-2 panels/phases
|
|
38
|
+
- 7-10 seconds: 2-3 panels/phases
|
|
39
|
+
- 11-15 seconds: 3-4 panels/phases
|
|
40
|
+
- 5+ distinct phases: split into multiple `SHOTNN.md` files
|
|
41
|
+
5. Build `visual_world`:
|
|
42
|
+
- environment
|
|
43
|
+
- lighting
|
|
44
|
+
- foreground/midground/background
|
|
45
|
+
- screen direction
|
|
46
|
+
- continuity anchors
|
|
47
|
+
6. Generate one GPT Image 2 storyboard prompt per shot:
|
|
48
|
+
- use character sheets as the only identity source
|
|
49
|
+
- use optional storyboard guide only for composition, blocking, camera, timing, and rhythm
|
|
50
|
+
- include previous shot handoff and next shot handoff
|
|
51
|
+
- preserve shared location, lighting, screen direction, action rhythm, and scene continuity
|
|
52
|
+
7. Build model prompt bundle:
|
|
53
|
+
- Seedance dynamic image mapping: character sheets first, generated shot storyboard next
|
|
54
|
+
- Veo visual-planning prompt with full audio direction
|
|
55
|
+
- Kling block-structured storyboard route
|
|
56
|
+
8. Run QA gates:
|
|
57
|
+
- reference lock
|
|
58
|
+
- storyboard role separation
|
|
59
|
+
- model grammar
|
|
60
|
+
- avoid/negative prompt
|
|
61
|
+
- audio plan
|
|
62
|
+
- safety
|
|
63
|
+
9. Write outputs under `$OUTPUT_DIR`.
|
|
64
|
+
|
|
65
|
+
## CLI Equivalent
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
npx @milenyumai/film-kit generate-storyboard \
|
|
69
|
+
--character-ref ./refs/character.png \
|
|
70
|
+
--brief ./scenario.md \
|
|
71
|
+
--models veo31,seedance-2.0,kling-3.0 \
|
|
72
|
+
--duration 8 \
|
|
73
|
+
--aspect 16:9 \
|
|
74
|
+
--output-dir ./outputs
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
Optional external storyboard guide:
|
|
78
|
+
|
|
79
|
+
```bash
|
|
80
|
+
npx @milenyumai/film-kit generate-storyboard \
|
|
81
|
+
--character-ref ./refs/character.png \
|
|
82
|
+
--storyboard-ref ./refs/storyboard-guide.png \
|
|
83
|
+
--brief ./scenario.md \
|
|
84
|
+
--models seedance-2.0
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
## Fail-Closed Rules
|
|
88
|
+
|
|
89
|
+
- Missing character reference: stop and request a valid reference.
|
|
90
|
+
- Empty brief: stop and request a brief.
|
|
91
|
+
- Public figure / real-person likeness / trademark risk: stop or safely anonymize before prompt generation.
|
|
92
|
+
- 5+ storyboard phases: do not compress into one prompt; split shots.
|
|
93
|
+
- Missing GPT Image 2 character sheet prompt: output is invalid.
|
|
94
|
+
- Missing GPT Image 2 per-shot storyboard prompt: output is invalid.
|
|
95
|
+
- Missing `Avoid` / negative prompt: output is invalid.
|
|
96
|
+
- Kling prompt missing required block structure: output is invalid.
|
|
@@ -5,6 +5,7 @@ const command = args[0];
|
|
|
5
5
|
const overwrite = args.includes("--overwrite") || args.includes("-f");
|
|
6
6
|
const SUPPORTED_MODELS = ["veo31", "kling-3.0", "seedance-2.0"];
|
|
7
7
|
const SUPPORTED_KLING_PRESETS = ["ultra-realism", "balanced", "custom"];
|
|
8
|
+
const SUPPORTED_REFERENCE_MODES = ["start-end", "storyboard-reference", "hybrid"];
|
|
8
9
|
function parseFlagValue(flag) {
|
|
9
10
|
const exactIndex = args.indexOf(flag);
|
|
10
11
|
if (exactIndex >= 0 && args[exactIndex + 1]) {
|
|
@@ -34,11 +35,32 @@ function parseKlingPreset() {
|
|
|
34
35
|
}
|
|
35
36
|
throw new Error(`Invalid --kling-preset value: ${presetRaw}. Supported: ${SUPPORTED_KLING_PRESETS.join(", ")}`);
|
|
36
37
|
}
|
|
38
|
+
function parseReferenceMode() {
|
|
39
|
+
const modeRaw = parseFlagValue("--reference-mode");
|
|
40
|
+
if (!modeRaw)
|
|
41
|
+
return undefined;
|
|
42
|
+
if (SUPPORTED_REFERENCE_MODES.includes(modeRaw)) {
|
|
43
|
+
return modeRaw;
|
|
44
|
+
}
|
|
45
|
+
throw new Error(`Invalid --reference-mode value: ${modeRaw}. Supported: ${SUPPORTED_REFERENCE_MODES.join(", ")}`);
|
|
46
|
+
}
|
|
47
|
+
function parsePositiveIntegerFlag(flag) {
|
|
48
|
+
const raw = parseFlagValue(flag);
|
|
49
|
+
if (!raw)
|
|
50
|
+
return undefined;
|
|
51
|
+
const value = Number(raw);
|
|
52
|
+
if (!Number.isInteger(value) || value < 1) {
|
|
53
|
+
throw new Error(`Invalid ${flag} value: ${raw}. Expected a positive integer.`);
|
|
54
|
+
}
|
|
55
|
+
return value;
|
|
56
|
+
}
|
|
37
57
|
if (command === "init") {
|
|
38
58
|
console.log("🎬 Film-Kit Multi: Configuring multi-agent team...\n");
|
|
39
59
|
try {
|
|
40
60
|
const model = parseModel();
|
|
41
61
|
const klingPreset = parseKlingPreset();
|
|
62
|
+
const referenceMode = parseReferenceMode();
|
|
63
|
+
const maxStoryboardPhases = parsePositiveIntegerFlag("--max-storyboard-phases");
|
|
42
64
|
const configureOptions = {
|
|
43
65
|
rootDir: process.cwd(),
|
|
44
66
|
overwrite
|
|
@@ -47,6 +69,21 @@ if (command === "init") {
|
|
|
47
69
|
configureOptions.model = model;
|
|
48
70
|
if (klingPreset)
|
|
49
71
|
configureOptions.klingPreset = klingPreset;
|
|
72
|
+
if (referenceMode) {
|
|
73
|
+
configureOptions.referenceMode = referenceMode;
|
|
74
|
+
if (referenceMode === "storyboard-reference") {
|
|
75
|
+
configureOptions.storyboardReferenceMode = {
|
|
76
|
+
...configureOptions.storyboardReferenceMode,
|
|
77
|
+
enabled: true
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
if (maxStoryboardPhases !== undefined) {
|
|
82
|
+
configureOptions.storyboardReferenceMode = {
|
|
83
|
+
...configureOptions.storyboardReferenceMode,
|
|
84
|
+
maxStoryboardPhases
|
|
85
|
+
};
|
|
86
|
+
}
|
|
50
87
|
const result = await configureMultiAgents(configureOptions);
|
|
51
88
|
if (result.written.length > 0) {
|
|
52
89
|
console.log(`✅ Files written: ${result.written.length}`);
|
|
@@ -77,7 +114,9 @@ This internal CLI exists only for repository development.
|
|
|
77
114
|
Public usage:
|
|
78
115
|
npx @milenyumai/film-kit init --preset multi
|
|
79
116
|
npx @milenyumai/film-kit init --preset multi --model veo31|kling-3.0|seedance-2.0
|
|
117
|
+
npx @milenyumai/film-kit init --preset multi --model seedance-2.0 --reference-mode storyboard-reference
|
|
80
118
|
npx @milenyumai/film-kit init --preset multi --model kling-3.0 --kling-preset ultra-realism|balanced|custom
|
|
119
|
+
npx @milenyumai/film-kit init --preset multi --max-storyboard-phases 4
|
|
81
120
|
npx @milenyumai/film-kit init --preset multi --overwrite
|
|
82
121
|
`);
|
|
83
122
|
}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export type { KlingPreset, MultiAgentConfigOptions, MultiConfigureResult, SupportedModel } from "./lib/types.js";
|
|
1
|
+
export type { KlingPreset, MultiAgentConfigOptions, MultiConfigureResult, ReferenceMode, StoryboardReferenceConfig, SupportedModel } from "./lib/types.js";
|
|
2
2
|
export { configureMultiAgents } from "./lib/configure.js";
|
|
@@ -112,6 +112,18 @@ async function copyMultiContent(rootDir, overwrite, templateVars) {
|
|
|
112
112
|
}
|
|
113
113
|
function renderContentTemplate(content, vars) {
|
|
114
114
|
return content
|
|
115
|
+
.replaceAll("$REFERENCE_MODE_CONTRACT", vars.referenceModeContract)
|
|
116
|
+
.replaceAll("$SHOT_FILE_OUTPUT_CONTRACT", vars.shotFileOutputContract)
|
|
117
|
+
.replaceAll("$CONTINUITY_CONTRACT", vars.continuityContract)
|
|
118
|
+
.replaceAll("$SEEDANCE_STORYBOARD_CONTRACT", vars.seedanceStoryboardContract)
|
|
119
|
+
.replaceAll("$SHOT_SELF_CHECK_CONTRACT", vars.selfCheckContract)
|
|
120
|
+
.replaceAll("$SEMANTIC_AUDIT_CONTRACT", vars.semanticAuditContract)
|
|
121
|
+
.replaceAll("$SEMANTIC_REFERENCE_MODE_STATUS_FIELD", vars.semanticReferenceModeStatusField)
|
|
122
|
+
.replaceAll("$SEMANTIC_CONTINUITY_STATUS_FIELD", vars.semanticContinuityStatusField)
|
|
123
|
+
.replaceAll("$STORYBOARD_REFERENCE_POLICY_JSON", vars.storyboardReferencePolicyJson)
|
|
124
|
+
.replaceAll("$CHAINED_ILK_FRAME_EXACT_REUSE_REQUIRED", String(vars.chainedIlkFrameExactReuseRequired))
|
|
125
|
+
.replaceAll("$MAX_STORYBOARD_PHASES", String(vars.maxStoryboardPhases))
|
|
126
|
+
.replaceAll("$REFERENCE_MODE", vars.referenceMode)
|
|
115
127
|
.replaceAll("$OUTPUT_DIR", vars.outputDir)
|
|
116
128
|
.replaceAll("$SCENARIO_HINT", vars.scenarioHint)
|
|
117
129
|
.replaceAll("$MODEL_DISPLAY", vars.modelDisplayName)
|
|
@@ -129,6 +141,178 @@ function getModelDisplayName(model) {
|
|
|
129
141
|
function getKlingPresetDisplay(model, klingPreset) {
|
|
130
142
|
return model === "kling-3.0" ? klingPreset : "n/a (Kling-only)";
|
|
131
143
|
}
|
|
144
|
+
function isSeedanceStoryboardReference(config) {
|
|
145
|
+
return config.model === "seedance-2.0"
|
|
146
|
+
&& config.referenceMode === "storyboard-reference"
|
|
147
|
+
&& config.storyboardReferenceMode.enabled;
|
|
148
|
+
}
|
|
149
|
+
function buildStoryboardReferencePolicyJson(config) {
|
|
150
|
+
if (!isSeedanceStoryboardReference(config)) {
|
|
151
|
+
return JSON.stringify({
|
|
152
|
+
enabled: false,
|
|
153
|
+
continuity_source: "start_end_frame_chain"
|
|
154
|
+
}, null, 6);
|
|
155
|
+
}
|
|
156
|
+
return JSON.stringify({
|
|
157
|
+
enabled: true,
|
|
158
|
+
max_storyboard_phases: config.storyboardReferenceMode.maxStoryboardPhases,
|
|
159
|
+
recommended_phase_budget: {
|
|
160
|
+
"4-6s": "1-2 storyboard phases",
|
|
161
|
+
"7-10s": "2-3 storyboard phases",
|
|
162
|
+
"11-15s": "3-4 storyboard phases",
|
|
163
|
+
split_at_phase_count: 5,
|
|
164
|
+
split_target: "separate SHOTNN.md files"
|
|
165
|
+
},
|
|
166
|
+
provider_reference_tokens: {
|
|
167
|
+
character_identities: "@Image1..@ImageN generated character sheets",
|
|
168
|
+
storyboard_reference: "next @Image token after character sheets (one character -> @Image2, two characters -> @Image3)",
|
|
169
|
+
legacy_aliases: {
|
|
170
|
+
character_identities: "@image1..@imageN",
|
|
171
|
+
storyboard_reference: "matching lowercase next @image token"
|
|
172
|
+
},
|
|
173
|
+
video_reference: "@video1",
|
|
174
|
+
audio_reference: "@audio1"
|
|
175
|
+
},
|
|
176
|
+
continuity_mode: {
|
|
177
|
+
continuous_shot: "use no-cuts wording only for a single uninterrupted camera move",
|
|
178
|
+
multi_shot_storyboard: "use only planned STORYBOARD PLAN phase transitions; do not add unplanned cuts"
|
|
179
|
+
},
|
|
180
|
+
provider_file_limits: {
|
|
181
|
+
images: 9,
|
|
182
|
+
videos: 3,
|
|
183
|
+
audio: 3,
|
|
184
|
+
total_files: 12,
|
|
185
|
+
duration_seconds: "4-15"
|
|
186
|
+
},
|
|
187
|
+
character_reference_sheets: {
|
|
188
|
+
enabled: true,
|
|
189
|
+
provider: "gpt-image-2",
|
|
190
|
+
generated_once_per_character: true,
|
|
191
|
+
aspect_ratio: "16:9",
|
|
192
|
+
required_views: [
|
|
193
|
+
"front full body",
|
|
194
|
+
"back full body",
|
|
195
|
+
"left profile",
|
|
196
|
+
"right profile",
|
|
197
|
+
"three-quarter full body",
|
|
198
|
+
"close-up face"
|
|
199
|
+
]
|
|
200
|
+
},
|
|
201
|
+
storyboard_prompt_policy: {
|
|
202
|
+
enabled: true,
|
|
203
|
+
provider: "gpt-image-2",
|
|
204
|
+
generated_per_shot: true,
|
|
205
|
+
aspect_ratio: "16:9",
|
|
206
|
+
panel_budget: "4-6s: 1-2, 7-10s: 2-3, 11-15s: 3-4",
|
|
207
|
+
max_panels_per_shot: config.storyboardReferenceMode.maxStoryboardPhases,
|
|
208
|
+
target_words: "160-240 words per shot storyboard prompt"
|
|
209
|
+
},
|
|
210
|
+
material_roles: {
|
|
211
|
+
"character_sheet_tokens": "identity, face, body proportions, wardrobe, accessories, and visible props",
|
|
212
|
+
"generated_shot_storyboard_token": "composition, blocking, camera direction, timing, and action progression only"
|
|
213
|
+
},
|
|
214
|
+
storyboard_never_identity_source: [
|
|
215
|
+
"storyboard text",
|
|
216
|
+
"panel borders",
|
|
217
|
+
"watermarks",
|
|
218
|
+
"logos",
|
|
219
|
+
"alternate character designs"
|
|
220
|
+
],
|
|
221
|
+
continuity_source: "shared visual_world plus shot-to-shot storyboard handoff notes",
|
|
222
|
+
require_ilk_son_frames: false,
|
|
223
|
+
shot_handoff_notes_required: true
|
|
224
|
+
}, null, 6);
|
|
225
|
+
}
|
|
226
|
+
function buildReferenceModeContract(config) {
|
|
227
|
+
if (!isSeedanceStoryboardReference(config)) {
|
|
228
|
+
return `Reference mode: \`${config.referenceMode}\` (start/end frame chaining active).
|
|
229
|
+
- Main shots are chained by exact end-frame to first-frame reuse.
|
|
230
|
+
- \`${config.outputDir}/team-plan.json -> visual_world\` still governs perspective, lighting, scale, and identity locks.`;
|
|
231
|
+
}
|
|
232
|
+
return `Reference mode: \`storyboard-reference\` (Seedance 2.0 storyboard-supported runtime).
|
|
233
|
+
- Do not require \`ILK FRAME\` / \`SON FRAME\` sections for main shots in this mode.
|
|
234
|
+
- Generate one 16:9 GPT Image 2 character reference sheet prompt per character once, before shot storyboard work.
|
|
235
|
+
- Each \`SHOTNN.md\` must include a \`GPT IMAGE 2 STORYBOARD PROMPT\` and its own \`STORYBOARD PLAN\` with timeline phases derived from one shared \`${config.outputDir}/team-plan.json -> visual_world\`.
|
|
236
|
+
- \`${config.outputDir}/team-plan.json\` must set \`project.reference_mode: "storyboard-reference"\`, \`storyboard_reference.enabled: true\`, \`storyboard_reference.character_reference_sheets\`, \`storyboard_reference.storyboard_prompt_policy\`, \`storyboard_reference.max_storyboard_phases: ${config.storyboardReferenceMode.maxStoryboardPhases}\`, \`storyboard_reference.recommended_phase_budget\`, \`storyboard_reference.provider_reference_tokens\`, \`storyboard_reference.continuity_mode\`, \`storyboard_reference.provider_file_limits\`, and shot-level handoff notes.
|
|
237
|
+
- Duration policy: 4-6s = 1-2 phases, 7-10s = 2-3 phases, 11-15s = 3-4 phases; 5+ distinct phases split into separate \`SHOTNN.md\` files.
|
|
238
|
+
- Continuity is enforced by shared \`visual_world\`, shot-to-shot storyboard handoff notes, character/reference lock, camera direction, lighting, and action progression.`;
|
|
239
|
+
}
|
|
240
|
+
function buildShotFileOutputContract(config) {
|
|
241
|
+
if (!isSeedanceStoryboardReference(config)) {
|
|
242
|
+
return `1. main shot blocks: \`ILK FRAME\` (or \`İLK FRAME\`), \`SON FRAME\`, \`AUDIO PLAN\`, \`VIDEO\` (or \`VİDEO\`)
|
|
243
|
+
2. \`ILK/İLK FRAME\` section must always include a fenced code block
|
|
244
|
+
3. if chained, first-frame code block must contain only: \`Use SHOT[prev]_END as exact first frame\`; any new start-frame prompt requires \`CHAIN BREAK\`
|
|
245
|
+
4. 2-3 coverage sub-shots in the same file
|
|
246
|
+
5. image prompt contract (hard requirement):
|
|
247
|
+
- if references exist, \`ILK FRAME\` and \`SON FRAME\` must use \`REFERENCE LOCK\`, \`Keep same\`, and \`Change only\`
|
|
248
|
+
- face/hair/skin/body/wardrobe/accessories/prop design visible in reference are immutable
|
|
249
|
+
- \`SON FRAME\` must preserve the same visual universe and declare only one major semantic delta
|
|
250
|
+
- \`VIDEO\`: minimum 120 words
|
|
251
|
+
- each coverage video prompt: minimum 70 words`;
|
|
252
|
+
}
|
|
253
|
+
return `1. main shot blocks: \`MODEL CONTROL\`, \`INPUT ASSET ROLES\`, \`REFERENCE ASSET REQUIREMENTS\`, \`GPT IMAGE 2 STORYBOARD PROMPT\`, \`STORYBOARD PLAN\`, \`AUDIO PLAN\`, \`SEEDANCE VIDEO PROMPT\`, and coverage
|
|
254
|
+
2. \`INPUT ASSET ROLES\` must declare generated character sheet tokens (\`@Image1...\`, legacy \`@image1...\`) as identity/wardrobe/props only
|
|
255
|
+
3. \`INPUT ASSET ROLES\` must declare the generated shot storyboard token (next \`@Image\` after character sheets, legacy lowercase alias such as \`@image2\` for one character) as composition/blocking/camera/timing only
|
|
256
|
+
4. \`GPT IMAGE 2 STORYBOARD PROMPT\` must be 16:9, professional production storyboard style, 160-240 words, and use character sheets as the only identity source
|
|
257
|
+
5. \`STORYBOARD PLAN\` must include timeline phases for this shot, capped at ${config.storyboardReferenceMode.maxStoryboardPhases} phases
|
|
258
|
+
6. every phase must derive from the shared \`team-plan.json -> visual_world\` and include its handoff from the previous shot and handoff to the next shot
|
|
259
|
+
7. 2-3 coverage sub-shots stay in the same file
|
|
260
|
+
8. \`SEEDANCE VIDEO PROMPT\`: minimum 120 words; each coverage video prompt: minimum 70 words`;
|
|
261
|
+
}
|
|
262
|
+
function buildContinuityContract(config) {
|
|
263
|
+
if (!isSeedanceStoryboardReference(config)) {
|
|
264
|
+
return `- First shot \`ILK FRAME\` / \`İLK FRAME\` must match assigned chain entry.
|
|
265
|
+
- Chained \`ILK FRAME\` / \`İLK FRAME\` code blocks cannot contain a new camera, lens, lighting, action, or composition prompt.
|
|
266
|
+
- Within your batch: \`SHOT[N]_END\` must match \`SHOT[N+1]_START\`.
|
|
267
|
+
- Coverage shots are standalone and not chained.`;
|
|
268
|
+
}
|
|
269
|
+
return `- Main-shot continuity uses storyboard handoff text, not start/end frame reuse.
|
|
270
|
+
- First shot \`STORYBOARD PLAN\` must match the assigned continuity entry and shared \`${config.outputDir}/team-plan.json -> visual_world\`.
|
|
271
|
+
- Within your batch, each shot's final timeline phase must hand off clearly into the next shot's opening phase.
|
|
272
|
+
- Coverage shots are standalone and not chained.`;
|
|
273
|
+
}
|
|
274
|
+
function buildSeedanceStoryboardContract(config) {
|
|
275
|
+
if (!isSeedanceStoryboardReference(config)) {
|
|
276
|
+
return `- explicit material roles when references exist (\`@Image1\`/\`@image1\`, \`@video1\`, \`@audio1\`)
|
|
277
|
+
- use \`Use @Image1 as the first frame of the scene.\` when first-frame identity lock matters
|
|
278
|
+
- if \`@video1\` is action reference and \`@video2\` is camera reference, say so directly
|
|
279
|
+
- use \`No scene cuts throughout, one continuous shot.\` only for a true uninterrupted camera move
|
|
280
|
+
- use timeline segments only for meaningful internal beats, not decorative micro-actions
|
|
281
|
+
- when continuing a clip, use \`Extend @video1 by [N]s\` rather than rewriting it as a new cut
|
|
282
|
+
- when \`@Image1\`/\`@image1\` locks identity, keep face/body/wardrobe/prop design exact and change only one meaningful beat`;
|
|
283
|
+
}
|
|
284
|
+
return `- generate one 16:9 GPT Image 2 character sheet prompt per character once, then use those sheet images as Seedance identity references
|
|
285
|
+
- declare character sheet tokens (\`@Image1...\`, legacy \`@image1...\`) as identity, face, body proportions, wardrobe, accessories, and visible props
|
|
286
|
+
- declare the generated shot storyboard token (next \`@Image\` after character sheets, legacy lowercase alias such as \`@image2\` for one character) as composition, blocking, camera direction, timing, and action progression only
|
|
287
|
+
- never let storyboard text, panel borders, watermark, logo, alternate character design, or storyboard character design override the identity reference
|
|
288
|
+
- write one \`GPT IMAGE 2 STORYBOARD PROMPT\` per shot before the Seedance prompt; it must be 16:9, professional, 160-240 words, and continuity-aware
|
|
289
|
+
- write per-shot timeline phases under \`STORYBOARD PLAN\`, capped at ${config.storyboardReferenceMode.maxStoryboardPhases} phases
|
|
290
|
+
- follow duration budget: 4-6s = 1-2 phases, 7-10s = 2-3 phases, 11-15s = 3-4 phases; split 5+ phases into separate \`SHOTNN.md\` files
|
|
291
|
+
- use \`No scene cuts throughout, one continuous shot.\` only when that shot's storyboard plan is a single uninterrupted camera move
|
|
292
|
+
- for multi-phase storyboard shots, describe the planned phase changes directly instead of forcing continuous-shot wording
|
|
293
|
+
- when continuing a source clip, use \`Extend @video1 by [N]s\` and still preserve storyboard handoff continuity`;
|
|
294
|
+
}
|
|
295
|
+
function buildSelfCheckContract(config) {
|
|
296
|
+
if (!isSeedanceStoryboardReference(config)) {
|
|
297
|
+
return `- each \`ILK/İLK FRAME\` section contains a code block
|
|
298
|
+
- chained \`ILK/İLK FRAME\` code blocks contain only exact reuse text
|
|
299
|
+
- word-count floors pass for all prompts
|
|
300
|
+
- image prompt contract passes for main stills`;
|
|
301
|
+
}
|
|
302
|
+
return `- each file contains \`INPUT ASSET ROLES\`, \`REFERENCE ASSET REQUIREMENTS\`, \`GPT IMAGE 2 STORYBOARD PROMPT\`, \`STORYBOARD PLAN\`, \`AUDIO PLAN\`, \`SEEDANCE VIDEO PROMPT\`, and coverage
|
|
303
|
+
- no main shot requires \`ILK FRAME\` or \`SON FRAME\` sections
|
|
304
|
+
- storyboard phases are capped at ${config.storyboardReferenceMode.maxStoryboardPhases} and are not decorative micro-beats
|
|
305
|
+
- role separation passes: identity comes from generated character sheet tokens, staging comes from the generated shot storyboard token`;
|
|
306
|
+
}
|
|
307
|
+
function buildSemanticAuditContract(config) {
|
|
308
|
+
if (!isSeedanceStoryboardReference(config)) {
|
|
309
|
+
return `- Start/end pairs keep the declared invariants and change only one major semantic beat unless \`CHAIN BREAK\` is declared.
|
|
310
|
+
- Chained \`ILK/İLK FRAME\` code blocks contain only \`Use SHOT[prev]_END as exact first frame\`; any competing visual prompt is a fail and must become \`CHAIN BREAK\`.`;
|
|
311
|
+
}
|
|
312
|
+
return `- Storyboard-reference shots derive every timeline phase from the shared \`team-plan.json -> visual_world\`.
|
|
313
|
+
- Shot-to-shot continuity is expressed through storyboard handoff notes, consistent camera direction, lighting, character lock, and action progression.
|
|
314
|
+
- Main shots do not require start/end frame pairs or chained first-frame reuse text in storyboard-reference mode.`;
|
|
315
|
+
}
|
|
132
316
|
async function removePathIfExists(rootDir, relativePath) {
|
|
133
317
|
const absolutePath = join(rootDir, relativePath);
|
|
134
318
|
if (await exists(absolutePath)) {
|
|
@@ -158,6 +342,8 @@ export async function configureMultiAgents(options = {}) {
|
|
|
158
342
|
const batchSize = options.batchSize ?? fromFile?.batchSize;
|
|
159
343
|
const model = options.model ?? fromFile?.model;
|
|
160
344
|
const klingPreset = options.klingPreset ?? fromFile?.klingPreset;
|
|
345
|
+
const referenceMode = options.referenceMode ?? fromFile?.referenceMode;
|
|
346
|
+
const storyboardReferenceMode = options.storyboardReferenceMode ?? fromFile?.storyboardReferenceMode;
|
|
161
347
|
if (outputDir !== undefined)
|
|
162
348
|
merged.outputDir = outputDir;
|
|
163
349
|
if (scenarioHint !== undefined)
|
|
@@ -176,13 +362,34 @@ export async function configureMultiAgents(options = {}) {
|
|
|
176
362
|
merged.model = model;
|
|
177
363
|
if (klingPreset !== undefined)
|
|
178
364
|
merged.klingPreset = klingPreset;
|
|
365
|
+
if (referenceMode !== undefined)
|
|
366
|
+
merged.referenceMode = referenceMode;
|
|
367
|
+
if (storyboardReferenceMode !== undefined)
|
|
368
|
+
merged.storyboardReferenceMode = storyboardReferenceMode;
|
|
179
369
|
const resolved = resolveMultiOptions(merged);
|
|
370
|
+
const seedanceStoryboardReference = isSeedanceStoryboardReference(resolved);
|
|
180
371
|
const templateVars = {
|
|
181
372
|
outputDir: resolved.outputDir,
|
|
182
373
|
scenarioHint: resolved.scenarioHint,
|
|
183
374
|
model: resolved.model,
|
|
184
375
|
klingPreset: getKlingPresetDisplay(resolved.model, resolved.klingPreset),
|
|
185
|
-
modelDisplayName: getModelDisplayName(resolved.model)
|
|
376
|
+
modelDisplayName: getModelDisplayName(resolved.model),
|
|
377
|
+
referenceMode: resolved.referenceMode,
|
|
378
|
+
maxStoryboardPhases: resolved.storyboardReferenceMode.maxStoryboardPhases,
|
|
379
|
+
chainedIlkFrameExactReuseRequired: !seedanceStoryboardReference,
|
|
380
|
+
storyboardReferencePolicyJson: buildStoryboardReferencePolicyJson(resolved),
|
|
381
|
+
referenceModeContract: buildReferenceModeContract(resolved),
|
|
382
|
+
shotFileOutputContract: buildShotFileOutputContract(resolved),
|
|
383
|
+
continuityContract: buildContinuityContract(resolved),
|
|
384
|
+
seedanceStoryboardContract: buildSeedanceStoryboardContract(resolved),
|
|
385
|
+
selfCheckContract: buildSelfCheckContract(resolved),
|
|
386
|
+
semanticAuditContract: buildSemanticAuditContract(resolved),
|
|
387
|
+
semanticReferenceModeStatusField: seedanceStoryboardReference
|
|
388
|
+
? "storyboard_reference_status"
|
|
389
|
+
: "start_end_contract_status",
|
|
390
|
+
semanticContinuityStatusField: seedanceStoryboardReference
|
|
391
|
+
? "storyboard_handoff_status"
|
|
392
|
+
: "chained_ilk_frame_status"
|
|
186
393
|
};
|
|
187
394
|
await removeStaleClaudeArtifacts(resolved.rootDir);
|
|
188
395
|
// Ensure core Film-Kit system files exist (.agent/MASTER.md + skills).
|
|
@@ -1,2 +1,4 @@
|
|
|
1
|
-
import type { MultiAgentConfigOptions, ResolvedMultiConfig } from "./types.js";
|
|
1
|
+
import type { MultiAgentConfigOptions, ReferenceMode, ResolvedMultiConfig, StoryboardReferenceConfig } from "./types.js";
|
|
2
|
+
export declare const DEFAULT_STORYBOARD_REFERENCE_CONFIG: StoryboardReferenceConfig;
|
|
3
|
+
export declare function normalizeStoryboardReferenceConfig(input: Partial<StoryboardReferenceConfig> | undefined, referenceMode: ReferenceMode): StoryboardReferenceConfig;
|
|
2
4
|
export declare function resolveMultiOptions(options: MultiAgentConfigOptions): ResolvedMultiConfig;
|
|
@@ -1,12 +1,42 @@
|
|
|
1
1
|
const DEFAULT_MODEL = "veo31";
|
|
2
2
|
const DEFAULT_KLING_PRESET = "ultra-realism";
|
|
3
|
+
const DEFAULT_REFERENCE_MODE = "start-end";
|
|
4
|
+
export const DEFAULT_STORYBOARD_REFERENCE_CONFIG = {
|
|
5
|
+
enabled: false,
|
|
6
|
+
maxStoryboardPhases: 4,
|
|
7
|
+
defaultCharacterRefRole: "character_identity",
|
|
8
|
+
defaultStoryboardRefRole: "storyboard_plan",
|
|
9
|
+
generateAllModelPrompts: true,
|
|
10
|
+
strictReferenceLock: true,
|
|
11
|
+
splitStoryboardOverload: true
|
|
12
|
+
};
|
|
13
|
+
export function normalizeStoryboardReferenceConfig(input, referenceMode) {
|
|
14
|
+
const maxStoryboardPhases = input?.maxStoryboardPhases ?? DEFAULT_STORYBOARD_REFERENCE_CONFIG.maxStoryboardPhases;
|
|
15
|
+
if (!Number.isInteger(maxStoryboardPhases) || maxStoryboardPhases < 1) {
|
|
16
|
+
throw new Error("Invalid storyboardReferenceMode.maxStoryboardPhases. Expected a positive integer.");
|
|
17
|
+
}
|
|
18
|
+
return {
|
|
19
|
+
enabled: input?.enabled ?? referenceMode === "storyboard-reference",
|
|
20
|
+
maxStoryboardPhases,
|
|
21
|
+
defaultCharacterRefRole: "character_identity",
|
|
22
|
+
defaultStoryboardRefRole: "storyboard_plan",
|
|
23
|
+
generateAllModelPrompts: input?.generateAllModelPrompts ?? DEFAULT_STORYBOARD_REFERENCE_CONFIG.generateAllModelPrompts,
|
|
24
|
+
strictReferenceLock: input?.strictReferenceLock ?? DEFAULT_STORYBOARD_REFERENCE_CONFIG.strictReferenceLock,
|
|
25
|
+
splitStoryboardOverload: input?.splitStoryboardOverload ?? DEFAULT_STORYBOARD_REFERENCE_CONFIG.splitStoryboardOverload
|
|
26
|
+
};
|
|
27
|
+
}
|
|
3
28
|
export function resolveMultiOptions(options) {
|
|
4
29
|
const warnings = [];
|
|
5
30
|
const model = options.model ?? DEFAULT_MODEL;
|
|
6
31
|
const klingPreset = options.klingPreset ?? DEFAULT_KLING_PRESET;
|
|
32
|
+
const referenceMode = options.referenceMode ?? DEFAULT_REFERENCE_MODE;
|
|
33
|
+
const storyboardReferenceMode = normalizeStoryboardReferenceConfig(options.storyboardReferenceMode, referenceMode);
|
|
7
34
|
if (!options.model) {
|
|
8
35
|
warnings.push("Model not specified. Falling back to veo31. In the next major release, --model will be required.");
|
|
9
36
|
}
|
|
37
|
+
if (referenceMode === "storyboard-reference" && !storyboardReferenceMode.enabled) {
|
|
38
|
+
warnings.push("referenceMode is storyboard-reference, but storyboardReferenceMode.enabled is false.");
|
|
39
|
+
}
|
|
10
40
|
return {
|
|
11
41
|
rootDir: options.rootDir ?? process.cwd(),
|
|
12
42
|
outputDir: options.outputDir ?? "./outputs",
|
|
@@ -18,6 +48,8 @@ export function resolveMultiOptions(options) {
|
|
|
18
48
|
batchSize: options.batchSize ?? 4,
|
|
19
49
|
model,
|
|
20
50
|
klingPreset,
|
|
51
|
+
referenceMode,
|
|
52
|
+
storyboardReferenceMode,
|
|
21
53
|
warnings
|
|
22
54
|
};
|
|
23
55
|
}
|