@milenyumai/film-kit 2.3.3 → 2.3.5
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/MODEL_REGISTRY.md +136 -0
- package/README.md +26 -2
- package/build/index.d.ts +3 -1
- package/build/index.js +1 -0
- package/build/lib/cli.js +26 -10
- package/build/lib/configure.js +16 -17
- package/build/lib/defaults.js +10 -0
- package/build/lib/film-kit.js +16 -1
- package/build/lib/model-registry/index.d.ts +4 -0
- package/build/lib/model-registry/index.js +3 -0
- package/build/lib/model-registry/registry.d.ts +220 -0
- package/build/lib/model-registry/registry.js +191 -0
- package/build/lib/model-registry/selectors.d.ts +23 -0
- package/build/lib/model-registry/selectors.js +80 -0
- package/build/lib/model-registry/types.d.ts +59 -0
- package/build/lib/model-registry/types.js +1 -0
- package/build/lib/model-registry/validation.d.ts +3 -0
- package/build/lib/model-registry/validation.js +42 -0
- package/build/lib/storyboard-reference/adapters/base.js +2 -5
- package/build/lib/storyboard-reference/adapters/seedance20.js +5 -5
- package/build/lib/storyboard-reference/defaults.js +2 -1
- 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 +103 -22
- package/build/lib/storyboard-reference/request-normalizer.js +6 -4
- package/build/lib/storyboard-reference/types.d.ts +25 -0
- package/build/lib/storyboard-reference/validators.js +4 -0
- package/build/lib/templates.js +1 -1
- package/build/lib/types.d.ts +2 -1
- package/content/skills/storyboard-reference/SKILL.md +7 -4
- package/content/workflows/generate-storyboard.md +7 -6
- package/package.json +2 -1
- package/packages/gpt-image-smart/content/skills/storyboard-reference/SKILL.md +7 -4
- package/packages/gpt-image-smart/content/workflows/generate-storyboard.md +7 -6
- package/packages/hybrid/content/skills/storyboard-reference/SKILL.md +7 -4
- package/packages/hybrid/content/workflows/generate-storyboard.md +7 -6
- package/packages/hybrid-smart/content/skills/storyboard-reference/SKILL.md +7 -4
- package/packages/hybrid-smart/content/workflows/generate-storyboard.md +7 -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 +7 -4
- package/packages/multi/content/workflows/generate-storyboard.md +7 -6
- package/packages/studio/content/skills/storyboard-reference/SKILL.md +7 -4
- package/packages/studio/content/workflows/generate-storyboard.md +7 -6
|
@@ -47,8 +47,8 @@ export class Seedance20PromptAdapter extends BaseVideoModelPromptAdapter {
|
|
|
47
47
|
const storyboardEntry = this.getMappingEntries(input, "storyboard_plan")[0];
|
|
48
48
|
const storyboardToken = storyboardEntry?.token ?? "@Image2";
|
|
49
49
|
const continuityInstruction = input.continuityMode === "continuous-shot"
|
|
50
|
-
?
|
|
51
|
-
: `
|
|
50
|
+
? `Use the generated storyboard reference ${storyboardToken} as the complete visual, action, camera, and choreography source for this ${input.request.durationSeconds}-second video. Follow the single storyboard beat exactly. No scene cuts throughout, one continuous shot.`
|
|
51
|
+
: `Use the generated storyboard reference ${storyboardToken} as the complete visual, action, camera, and 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 actions, poses, camera angles, emotional progression, frame variety, movement logic, shot order, or the final pose. Compress the full ${input.storyboardImagePrompt.panelCount}-beat sequence into the full 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
52
|
const characterEntries = this.getMappingEntries(input, "character_identity");
|
|
53
53
|
const characterTokenText = characterEntries.map(entry => entry.token).join(", ") || "@Image1";
|
|
54
54
|
const promptText = `${this.formatCharacterRoleLine(input)}
|
|
@@ -69,13 +69,13 @@ ${input.request.brief}
|
|
|
69
69
|
${formatPhaseLines(input.interpretation.phases)}
|
|
70
70
|
|
|
71
71
|
[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,
|
|
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, lens notes, and framing marks as planning annotations only; never render arrows, annotation marks, notes, labels, timestamps, panel borders, or storyboard text into the video.
|
|
73
73
|
|
|
74
74
|
[CAMERA]
|
|
75
75
|
${input.interpretation.cameraPlan.framing}, ${input.interpretation.cameraPlan.movement}, ${input.interpretation.cameraPlan.lens}, ${input.interpretation.cameraPlan.stabilization}. Preserve ${input.interpretation.cameraPlan.screenDirection}.
|
|
76
76
|
|
|
77
77
|
[PERFORMANCE]
|
|
78
|
-
Visible
|
|
78
|
+
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.
|
|
79
79
|
|
|
80
80
|
[AUDIO]
|
|
81
81
|
Dialogue: ${buildDialogueTranscript(input)}.
|
|
@@ -86,7 +86,7 @@ Music: NONE.
|
|
|
86
86
|
[CONTINUITY]
|
|
87
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.
|
|
88
88
|
|
|
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.`;
|
|
89
|
+
Avoid: identity drift, face drift, outfit drift, duplicated performer, storyboard text, annotations, panel borders, colored arrows, annotation marks, lens notes, timestamps, watermark, logo, distorted hands, rubbery motion, flicker, unnatural camera jumps. No text, no annotations, no timestamps, no watermark.`;
|
|
90
90
|
const output = {
|
|
91
91
|
model: this.model,
|
|
92
92
|
displayName: getDisplayName(this.model),
|
|
@@ -1,9 +1,10 @@
|
|
|
1
|
+
import { listActiveVideoModelIds } from "../model-registry/index.js";
|
|
1
2
|
export const STORYBOARD_REFERENCE_MODE = "storyboard-reference";
|
|
2
3
|
export const DEFAULT_STORYBOARD_DURATION_SECONDS = 8;
|
|
3
4
|
export const DEFAULT_STORYBOARD_ASPECT_RATIO = "16:9";
|
|
4
5
|
export const DEFAULT_STORYBOARD_LANGUAGE = "NONE";
|
|
5
6
|
export const DEFAULT_STORYBOARD_OUTPUT_DIR = "./outputs";
|
|
6
|
-
export const DEFAULT_STORYBOARD_TARGET_MODELS =
|
|
7
|
+
export const DEFAULT_STORYBOARD_TARGET_MODELS = listActiveVideoModelIds();
|
|
7
8
|
export const DEFAULT_STORYBOARD_REFERENCE_RUNTIME = {
|
|
8
9
|
enabled: true,
|
|
9
10
|
maxStoryboardPhases: 4,
|
|
@@ -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));
|
|
@@ -1,19 +1,57 @@
|
|
|
1
1
|
import { resolveAssetRoles } from "./asset-role-resolver.js";
|
|
2
|
+
import { GenericPromptAdapter } from "./adapters/generic.js";
|
|
2
3
|
import { Kling30PromptAdapter } from "./adapters/kling30.js";
|
|
3
4
|
import { Seedance20PromptAdapter } from "./adapters/seedance20.js";
|
|
4
5
|
import { Veo31PromptAdapter } from "./adapters/veo31.js";
|
|
6
|
+
import { getModelAdapterKey, requireModel } from "../model-registry/index.js";
|
|
5
7
|
import { normalizeVideoPromptRequest } from "./request-normalizer.js";
|
|
6
8
|
import { buildStoryboardPhaseBudget, inferContinuityMode, interpretStoryboard } from "./storyboard-interpreter.js";
|
|
7
9
|
import { assertSafeStoryboardReferenceRequest, validateCharacterReferenceSheetPrompts, validateModelPromptOutput, validatePromptBundle } from "./validators.js";
|
|
8
10
|
const ADAPTERS = {
|
|
9
11
|
veo31: new Veo31PromptAdapter(),
|
|
10
|
-
|
|
11
|
-
|
|
12
|
+
seedance20: new Seedance20PromptAdapter(),
|
|
13
|
+
kling30: new Kling30PromptAdapter()
|
|
12
14
|
};
|
|
13
|
-
function
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
15
|
+
function buildGenericCapabilities(model) {
|
|
16
|
+
const registryModel = requireModel(model);
|
|
17
|
+
const capabilities = {
|
|
18
|
+
supportsImageReference: Boolean(registryModel.capabilities.characterReference),
|
|
19
|
+
supportsMultipleImageReferences: Boolean(registryModel.capabilities.multipleImageReferences),
|
|
20
|
+
supportsStoryboardReference: Boolean(registryModel.capabilities.storyboardReference),
|
|
21
|
+
supportsAudio: Boolean(registryModel.capabilities.audioPlan),
|
|
22
|
+
supportsDialogue: Boolean(registryModel.capabilities.dialogue),
|
|
23
|
+
supportsCustomStoryboardPhases: Boolean(registryModel.capabilities.customStoryboardPhases),
|
|
24
|
+
preferredPromptShape: "natural-language"
|
|
25
|
+
};
|
|
26
|
+
if (registryModel.durationRange?.maxSeconds !== undefined) {
|
|
27
|
+
capabilities.maxDurationSeconds = registryModel.durationRange.maxSeconds;
|
|
28
|
+
}
|
|
29
|
+
if (registryModel.capabilities.maxStoryboardPhases !== undefined) {
|
|
30
|
+
capabilities.maxStoryboardPhases = registryModel.capabilities.maxStoryboardPhases;
|
|
31
|
+
}
|
|
32
|
+
return capabilities;
|
|
33
|
+
}
|
|
34
|
+
function resolvePromptAdapter(model) {
|
|
35
|
+
const adapterKey = getModelAdapterKey(model);
|
|
36
|
+
if (adapterKey === "generic") {
|
|
37
|
+
return new GenericPromptAdapter(model, buildGenericCapabilities(model));
|
|
38
|
+
}
|
|
39
|
+
const adapter = ADAPTERS[adapterKey];
|
|
40
|
+
if (!adapter) {
|
|
41
|
+
throw new Error(`Model ${model} does not have a storyboard-reference video adapter.`);
|
|
42
|
+
}
|
|
43
|
+
return adapter;
|
|
44
|
+
}
|
|
45
|
+
const MAX_STORYBOARD_SHEET_PANELS = 12;
|
|
46
|
+
function getStoryboardSheetPanelCount(request, phaseBudget) {
|
|
47
|
+
const panelCount = request.storyboardPanelCountHint ?? phaseBudget.recommendedMaxPhases;
|
|
48
|
+
if (panelCount > MAX_STORYBOARD_SHEET_PANELS) {
|
|
49
|
+
throw new Error(`Invalid storyboardPanelCountHint. Expected 1-${MAX_STORYBOARD_SHEET_PANELS} panels for one GPT Image 2 storyboard sheet.`);
|
|
50
|
+
}
|
|
51
|
+
return panelCount;
|
|
52
|
+
}
|
|
53
|
+
function getVideoPhaseCount(request, phaseBudget) {
|
|
54
|
+
return request.shotCountHint ?? phaseBudget.recommendedMaxPhases;
|
|
17
55
|
}
|
|
18
56
|
function buildShotId(index) {
|
|
19
57
|
return `SHOT${String(index + 1).padStart(2, "0")}`;
|
|
@@ -140,37 +178,37 @@ function buildStoryboardImagePrompt(input) {
|
|
|
140
178
|
? `Use external storyboard guide tokens ${assets.storyboards.map(storyboard => storyboard.token).join(", ")} only for composition, blocking, camera direction, timing, and action rhythm.`
|
|
141
179
|
: "No external storyboard guide is required; infer the board from the screenplay brief, continuity notes, and visual world.";
|
|
142
180
|
const phaseDirection = interpretation.phases
|
|
143
|
-
.map(phase => `
|
|
181
|
+
.map(phase => `Phase ${phase.index}: ${phase.job}; ${phase.subjectAction}; camera behavior: ${phase.cameraBehavior}; background behavior: ${phase.backgroundBehavior}.`)
|
|
144
182
|
.join(" ");
|
|
145
183
|
const continuityStyle = interpretation.phases.length <= 1
|
|
146
184
|
? "Because this is a single uninterrupted beat, show one decisive action moment with a clear entry pose, motion direction, and final body intention inside the same panel."
|
|
147
|
-
:
|
|
185
|
+
: `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.`;
|
|
148
186
|
return {
|
|
149
187
|
shotId,
|
|
150
188
|
outputPath: `${request.outputDir}/storyboard-prompts/${shotId}-GPT-IMAGE-2-STORYBOARD.md`,
|
|
151
189
|
provider: "gpt-image-2",
|
|
152
190
|
aspectRatio: "16:9",
|
|
153
|
-
panelCount:
|
|
191
|
+
panelCount: input.storyboardSheetPanelCount,
|
|
154
192
|
style: "professional-production-storyboard",
|
|
155
193
|
characterSheetIds,
|
|
156
194
|
externalStoryboardGuideIds,
|
|
157
195
|
previousShotHandoff: input.previousShotHandoff,
|
|
158
196
|
nextShotHandoff: input.nextShotHandoff,
|
|
159
|
-
promptText: `REFERENCE LOCK: Use the generated character sheet reference${characterReferenceSheetPrompts.length === 1 ? "" : "s"} (${sheetRefs}) as the only source for character identity, face, hair, body proportions, wardrobe, accessories, material behavior, and visible props.
|
|
197
|
+
promptText: `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.
|
|
160
198
|
|
|
161
199
|
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.
|
|
162
200
|
|
|
163
|
-
Change only: create a
|
|
201
|
+
Change only: create a raw cinematic storyboard sheet for ${shotId}. 16:9 storyboard sheet, exactly ${input.storyboardSheetPanelCount} cinematic panel${input.storyboardSheetPanelCount === 1 ? "" : "s"}. The storyboard controls composition, blocking, camera direction, timing, phase order, action rhythm, and emotional progression only. ${externalGuideText}
|
|
164
202
|
|
|
165
|
-
Storyboard drawing style: raw contemporary film storyboard
|
|
203
|
+
Storyboard drawing style: raw contemporary film storyboard with black-and-white rough pencil linework. The actual storyboard drawings must be black-and-white only: 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.
|
|
166
204
|
|
|
167
205
|
Panel direction: ${continuityStyle} The scene brief is: ${request.brief} Previous handoff: ${input.previousShotHandoff}. Next handoff: ${input.nextShotHandoff}. Planned panel actions: ${phaseDirection}
|
|
168
206
|
|
|
169
|
-
Camera and staging: show ${interpretation.cameraPlan.framing}, ${interpretation.cameraPlan.movement}, ${interpretation.cameraPlan.lens}; preserve ${interpretation.cameraPlan.screenDirection}. Use cinematic
|
|
207
|
+
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}.
|
|
170
208
|
|
|
171
209
|
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.
|
|
172
210
|
|
|
173
|
-
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.
|
|
211
|
+
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.
|
|
174
212
|
|
|
175
213
|
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.`
|
|
176
214
|
};
|
|
@@ -259,6 +297,45 @@ function buildProviderReferenceTokens(providerAssetMapping) {
|
|
|
259
297
|
audioReference: "@audio1"
|
|
260
298
|
};
|
|
261
299
|
}
|
|
300
|
+
function buildStoryboardCreationMetadata(request, storyboardImagePrompt, providerAssetMapping) {
|
|
301
|
+
const storyboardEntry = Object.values(providerAssetMapping)
|
|
302
|
+
.find(entry => entry.role === "storyboard_plan");
|
|
303
|
+
return {
|
|
304
|
+
provider: "gpt-image-2",
|
|
305
|
+
prompt_path: storyboardImagePrompt.outputPath,
|
|
306
|
+
alias_path: `${request.outputDir}/storyboard-prompt.md`,
|
|
307
|
+
source_mode: storyboardImagePrompt.externalStoryboardGuideIds.length > 0
|
|
308
|
+
? "generated-with-external-guide"
|
|
309
|
+
: "generated",
|
|
310
|
+
panel_count: storyboardImagePrompt.panelCount,
|
|
311
|
+
reading_order: "left-to-right, top-to-bottom",
|
|
312
|
+
character_sheet_ids: storyboardImagePrompt.characterSheetIds,
|
|
313
|
+
external_storyboard_guide_ids: storyboardImagePrompt.externalStoryboardGuideIds,
|
|
314
|
+
seedance_token: storyboardEntry?.token ?? "@Image2",
|
|
315
|
+
annotation_policy: {
|
|
316
|
+
rendered_in_video: false,
|
|
317
|
+
color_system: {
|
|
318
|
+
red: "body movement",
|
|
319
|
+
blue: "camera movement",
|
|
320
|
+
green: "framing / composition",
|
|
321
|
+
orange: "lighting direction",
|
|
322
|
+
purple: "vocal / emotional emphasis",
|
|
323
|
+
black: "short lens notes and panel labels"
|
|
324
|
+
},
|
|
325
|
+
forbidden_in_video: [
|
|
326
|
+
"arrows",
|
|
327
|
+
"annotation marks",
|
|
328
|
+
"lens notes",
|
|
329
|
+
"panel labels",
|
|
330
|
+
"timestamps",
|
|
331
|
+
"panel borders",
|
|
332
|
+
"watermark",
|
|
333
|
+
"logo"
|
|
334
|
+
]
|
|
335
|
+
},
|
|
336
|
+
prompt_text: storyboardImagePrompt.promptText
|
|
337
|
+
};
|
|
338
|
+
}
|
|
262
339
|
function buildStoryboardReferencePolicy(request, phaseBudget, providerFileLimits, bundles, providerReferenceTokens, maxPhases, splitRequired) {
|
|
263
340
|
const continuityModes = Array.from(new Set(bundles.map(bundle => bundle.continuityMode)));
|
|
264
341
|
return {
|
|
@@ -293,9 +370,9 @@ function buildStoryboardReferencePolicy(request, phaseBudget, providerFileLimits
|
|
|
293
370
|
provider: "gpt-image-2",
|
|
294
371
|
generated_per_shot: true,
|
|
295
372
|
aspect_ratio: "16:9",
|
|
296
|
-
max_panels_per_shot:
|
|
373
|
+
max_panels_per_shot: MAX_STORYBOARD_SHEET_PANELS,
|
|
297
374
|
panel_budget: phaseBudget.policy,
|
|
298
|
-
professional_prompt_target_words: "
|
|
375
|
+
professional_prompt_target_words: "240-420 words per shot storyboard prompt"
|
|
299
376
|
},
|
|
300
377
|
role_separation: {
|
|
301
378
|
character_identity: `${providerReferenceTokens.characterIdentities.join(", ")} control identity, face, hair, body proportions, wardrobe, accessories, and visible props.`,
|
|
@@ -320,7 +397,7 @@ function buildStoryboardReferencePolicy(request, phaseBudget, providerFileLimits
|
|
|
320
397
|
function buildModelPrompts(request, bundleInput) {
|
|
321
398
|
const modelPrompts = {};
|
|
322
399
|
for (const model of request.targetModels) {
|
|
323
|
-
const adapter =
|
|
400
|
+
const adapter = resolvePromptAdapter(model);
|
|
324
401
|
const output = adapter.buildPrompt({ ...bundleInput, request });
|
|
325
402
|
const validatorQa = validateModelPromptOutput(output);
|
|
326
403
|
output.qa = {
|
|
@@ -344,15 +421,16 @@ export function buildStoryboardReferencePromptBundles(input) {
|
|
|
344
421
|
const voiceCast = buildVoiceCast(request);
|
|
345
422
|
const phaseBudget = buildStoryboardPhaseBudget(request.durationSeconds, request.storyboardReferenceMode.maxStoryboardPhases);
|
|
346
423
|
const providerFileLimits = buildProviderFileLimitReport(request, characterReferenceSheetPrompts.length + 1);
|
|
347
|
-
const
|
|
424
|
+
const storyboardSheetPanelCount = getStoryboardSheetPanelCount(request, phaseBudget);
|
|
425
|
+
const videoPhaseCount = getVideoPhaseCount(request, phaseBudget);
|
|
348
426
|
const maxPhases = phaseBudget.effectiveMaxStoryboardPhases;
|
|
349
|
-
const splitRequired =
|
|
427
|
+
const splitRequired = videoPhaseCount > maxPhases;
|
|
350
428
|
if (splitRequired && !request.storyboardReferenceMode.splitStoryboardOverload) {
|
|
351
|
-
throw new Error(`Storyboard has ${
|
|
429
|
+
throw new Error(`Storyboard has ${videoPhaseCount} video phases, which exceeds maxStoryboardPhases=${maxPhases}. Enable splitStoryboardOverload or split the storyboard manually.`);
|
|
352
430
|
}
|
|
353
431
|
const phaseCounts = splitRequired && request.storyboardReferenceMode.splitStoryboardOverload
|
|
354
|
-
? getSplitPhaseCounts(
|
|
355
|
-
: [Math.min(
|
|
432
|
+
? getSplitPhaseCounts(videoPhaseCount, maxPhases)
|
|
433
|
+
: [Math.min(videoPhaseCount, maxPhases)];
|
|
356
434
|
const generatedAt = new Date().toISOString();
|
|
357
435
|
const bundles = [];
|
|
358
436
|
let previousShotHandoff = "Project opening: start from the screenplay's first visual beat.";
|
|
@@ -370,11 +448,13 @@ export function buildStoryboardReferencePromptBundles(input) {
|
|
|
370
448
|
assets,
|
|
371
449
|
shotId,
|
|
372
450
|
interpretation,
|
|
451
|
+
storyboardSheetPanelCount,
|
|
373
452
|
characterReferenceSheetPrompts,
|
|
374
453
|
previousShotHandoff,
|
|
375
454
|
nextShotHandoff: handoffNote.exitHandoff
|
|
376
455
|
});
|
|
377
456
|
const providerAssetMapping = buildProviderAssetMapping(assets, characterReferenceSheetPrompts, storyboardImagePrompt);
|
|
457
|
+
const storyboard_creation = buildStoryboardCreationMetadata(request, storyboardImagePrompt, providerAssetMapping);
|
|
378
458
|
const referenceAssetRequirements = buildReferenceAssetRequirements(providerAssetMapping);
|
|
379
459
|
const modelPrompts = buildModelPrompts(request, {
|
|
380
460
|
assets,
|
|
@@ -399,6 +479,7 @@ export function buildStoryboardReferencePromptBundles(input) {
|
|
|
399
479
|
providerFileLimits,
|
|
400
480
|
handoffNote,
|
|
401
481
|
storyboardImagePrompt,
|
|
482
|
+
storyboard_creation,
|
|
402
483
|
referenceAssetRequirements,
|
|
403
484
|
providerAssetMapping,
|
|
404
485
|
qa: { verdict: "pass", checks: {}, issues: [], splitRequired },
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
+
import { validateModelAllowed } from "../model-registry/index.js";
|
|
1
2
|
import { DEFAULT_STORYBOARD_ASPECT_RATIO, DEFAULT_STORYBOARD_DURATION_SECONDS, DEFAULT_STORYBOARD_LANGUAGE, DEFAULT_STORYBOARD_OUTPUT_DIR, DEFAULT_STORYBOARD_TARGET_MODELS, STORYBOARD_REFERENCE_MODE, resolveStoryboardReferenceRuntime } from "./defaults.js";
|
|
2
|
-
const SUPPORTED_MODELS = ["veo31", "seedance-2.0", "kling-3.0"];
|
|
3
3
|
const SUPPORTED_ASPECT_RATIOS = ["16:9", "9:16", "1:1"];
|
|
4
4
|
function normalizePositiveInteger(value, fallback, fieldName) {
|
|
5
5
|
const normalized = value ?? fallback;
|
|
@@ -13,9 +13,11 @@ function assertSupportedModels(models) {
|
|
|
13
13
|
return DEFAULT_STORYBOARD_TARGET_MODELS.slice();
|
|
14
14
|
}
|
|
15
15
|
for (const model of models) {
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
16
|
+
validateModelAllowed(model, {
|
|
17
|
+
requiredModalities: ["video"],
|
|
18
|
+
referenceMode: STORYBOARD_REFERENCE_MODE,
|
|
19
|
+
usage: "storyboard target"
|
|
20
|
+
});
|
|
19
21
|
}
|
|
20
22
|
return Array.from(new Set(models));
|
|
21
23
|
}
|
|
@@ -135,6 +135,30 @@ export interface StoryboardImagePrompt {
|
|
|
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
|
+
reading_order: "left-to-right, top-to-bottom";
|
|
145
|
+
character_sheet_ids: string[];
|
|
146
|
+
external_storyboard_guide_ids: string[];
|
|
147
|
+
seedance_token: string;
|
|
148
|
+
annotation_policy: {
|
|
149
|
+
rendered_in_video: false;
|
|
150
|
+
color_system: {
|
|
151
|
+
red: "body movement";
|
|
152
|
+
blue: "camera movement";
|
|
153
|
+
green: "framing / composition";
|
|
154
|
+
orange: "lighting direction";
|
|
155
|
+
purple: "vocal / emotional emphasis";
|
|
156
|
+
black: "short lens notes and panel labels";
|
|
157
|
+
};
|
|
158
|
+
forbidden_in_video: string[];
|
|
159
|
+
};
|
|
160
|
+
prompt_text: string;
|
|
161
|
+
}
|
|
138
162
|
export type ProviderAssetMappingRole = "character_identity" | "storyboard_plan" | "style_reference" | "camera_reference" | "action_reference" | "prop_reference";
|
|
139
163
|
export interface ProviderAssetMappingEntry {
|
|
140
164
|
token: string;
|
|
@@ -254,6 +278,7 @@ export interface PromptBundle {
|
|
|
254
278
|
providerFileLimits: ProviderFileLimitReport;
|
|
255
279
|
handoffNote: ShotHandoffNote;
|
|
256
280
|
storyboardImagePrompt: StoryboardImagePrompt;
|
|
281
|
+
storyboard_creation: StoryboardCreationMetadata;
|
|
257
282
|
referenceAssetRequirements: ReferenceAssetRequirement[];
|
|
258
283
|
providerAssetMapping: Record<string, ProviderAssetMappingEntry>;
|
|
259
284
|
qa: PromptBundleQa;
|
|
@@ -113,6 +113,10 @@ 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_path === bundle.storyboardImagePrompt.outputPath
|
|
118
|
+
&& bundle.storyboard_creation?.panel_count === bundle.storyboardImagePrompt.panelCount
|
|
119
|
+
&& bundle.storyboard_creation?.annotation_policy.rendered_in_video === false,
|
|
116
120
|
storyboardPromptHasReferenceLockStructure: hasGptImageStillPromptContract(bundle.storyboardImagePrompt?.promptText ?? ""),
|
|
117
121
|
hasAvoidLineEverywhere: Object.values(bundle.modelPrompts).every(output => Boolean(output) && hasAvoidOrNegativePrompt(output.promptText)),
|
|
118
122
|
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) {
|
package/build/lib/types.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
+
import type { VideoModelId } from "./model-registry/index.js";
|
|
1
2
|
export type SupportedPlatform = "cursor" | "claude" | "copilot" | "antigravity" | "codex";
|
|
2
|
-
export type SupportedModel =
|
|
3
|
+
export type SupportedModel = VideoModelId;
|
|
3
4
|
export type KlingPreset = "ultra-realism" | "balanced" | "custom";
|
|
4
5
|
export type FilmKitPreset = "single" | "multi" | "hybrid" | "hybrid-smart" | "gpt-image-smart" | "studio";
|
|
5
6
|
export type ReferenceMode = "start-end" | "storyboard-reference" | "hybrid";
|
|
@@ -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,9 +36,10 @@ 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 follows the duration-aware phase budget, but an explicit storyboard panel hint may request 1-12 panels in one GPT Image 2 storyboard sheet
|
|
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
44
|
- storyboard art grammar: black-and-white rough pencil drawings, minimal detail, rapid gesture energy, simple anatomy construction, strong silhouette readability, unfinished previsualization feel
|
|
44
45
|
- 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
|
|
@@ -108,6 +109,7 @@ Each shot file contains:
|
|
|
108
109
|
- provider reference tokens
|
|
109
110
|
- GPT Image 2 storyboard prompt
|
|
110
111
|
- storyboard interpretation
|
|
112
|
+
- storyboard_creation metadata in `SHOTNN.bundle.json`
|
|
111
113
|
- audio plan
|
|
112
114
|
- prompt bundle for requested models
|
|
113
115
|
- QA verdict
|
|
@@ -116,6 +118,7 @@ Generated files:
|
|
|
116
118
|
|
|
117
119
|
```text
|
|
118
120
|
$OUTPUT_DIR/storyboard-reference-plan.json
|
|
121
|
+
$OUTPUT_DIR/storyboard-prompt.md
|
|
119
122
|
$OUTPUT_DIR/reference-prep/CHARACTER-SHEET-*.md
|
|
120
123
|
$OUTPUT_DIR/storyboard-prompts/SHOTNN-GPT-IMAGE-2-STORYBOARD.md
|
|
121
124
|
$OUTPUT_DIR/prompt-bundles/SHOTNN.bundle.json
|
|
@@ -33,11 +33,12 @@ description: Generate character sheet prompts, per-shot GPT Image 2 storyboard p
|
|
|
33
33
|
- exact identity, wardrobe, accessories, and visible props
|
|
34
34
|
- no labels, text, logos, watermarks, alternate designs, or extra characters
|
|
35
35
|
3. Confirm target models: `veo31`, `seedance-2.0`, `kling-3.0`, or a user-provided subset.
|
|
36
|
-
4. Select
|
|
37
|
-
- 4-6 seconds: 1-2
|
|
38
|
-
- 7-10 seconds: 2-3
|
|
39
|
-
- 11-15 seconds: 3-4
|
|
40
|
-
-
|
|
36
|
+
4. Select video phase budget and storyboard sheet panel count:
|
|
37
|
+
- 4-6 seconds: 1-2 video phases
|
|
38
|
+
- 7-10 seconds: 2-3 video phases
|
|
39
|
+
- 11-15 seconds: 3-4 video phases
|
|
40
|
+
- GPT Image 2 storyboard sheet may contain 1-12 panels
|
|
41
|
+
- 5+ distinct real video phases, scene changes, or location/action blocks: split into multiple `SHOTNN.md` files
|
|
41
42
|
5. Build `visual_world`:
|
|
42
43
|
- environment
|
|
43
44
|
- lighting
|
|
@@ -89,7 +90,7 @@ npx @milenyumai/film-kit generate-storyboard \
|
|
|
89
90
|
- Missing character reference: stop and request a valid reference.
|
|
90
91
|
- Empty brief: stop and request a brief.
|
|
91
92
|
- Public figure / real-person likeness / trademark risk: stop or safely anonymize before prompt generation.
|
|
92
|
-
- 5+
|
|
93
|
+
- 5+ real video phases: do not compress into one prompt; split shots. 5-12 storyboard sheet panels alone do not force a split.
|
|
93
94
|
- Missing GPT Image 2 character sheet prompt: output is invalid.
|
|
94
95
|
- Missing GPT Image 2 per-shot storyboard prompt: output is invalid.
|
|
95
96
|
- Missing `Avoid` / negative prompt: output is invalid.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@milenyumai/film-kit",
|
|
3
|
-
"version": "2.3.
|
|
3
|
+
"version": "2.3.5",
|
|
4
4
|
"description": "Single-package Film-Kit distribution with preset-driven cinematic runtime setup for OpenAI Codex App, Claude Code, Cursor, Copilot, and Antigravity.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./build/index.js",
|
|
@@ -36,6 +36,7 @@
|
|
|
36
36
|
"packages/gpt-image-smart/content",
|
|
37
37
|
"packages/studio/content",
|
|
38
38
|
"content",
|
|
39
|
+
"MODEL_REGISTRY.md",
|
|
39
40
|
"README.md",
|
|
40
41
|
"LICENSE"
|
|
41
42
|
],
|
|
@@ -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,9 +36,10 @@ 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 follows the duration-aware phase budget, but an explicit storyboard panel hint may request 1-12 panels in one GPT Image 2 storyboard sheet
|
|
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
44
|
- storyboard art grammar: black-and-white rough pencil drawings, minimal detail, rapid gesture energy, simple anatomy construction, strong silhouette readability, unfinished previsualization feel
|
|
44
45
|
- 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
|
|
@@ -108,6 +109,7 @@ Each shot file contains:
|
|
|
108
109
|
- provider reference tokens
|
|
109
110
|
- GPT Image 2 storyboard prompt
|
|
110
111
|
- storyboard interpretation
|
|
112
|
+
- storyboard_creation metadata in `SHOTNN.bundle.json`
|
|
111
113
|
- audio plan
|
|
112
114
|
- prompt bundle for requested models
|
|
113
115
|
- QA verdict
|
|
@@ -116,6 +118,7 @@ Generated files:
|
|
|
116
118
|
|
|
117
119
|
```text
|
|
118
120
|
$OUTPUT_DIR/storyboard-reference-plan.json
|
|
121
|
+
$OUTPUT_DIR/storyboard-prompt.md
|
|
119
122
|
$OUTPUT_DIR/reference-prep/CHARACTER-SHEET-*.md
|
|
120
123
|
$OUTPUT_DIR/storyboard-prompts/SHOTNN-GPT-IMAGE-2-STORYBOARD.md
|
|
121
124
|
$OUTPUT_DIR/prompt-bundles/SHOTNN.bundle.json
|
|
@@ -33,11 +33,12 @@ description: Generate character sheet prompts, per-shot GPT Image 2 storyboard p
|
|
|
33
33
|
- exact identity, wardrobe, accessories, and visible props
|
|
34
34
|
- no labels, text, logos, watermarks, alternate designs, or extra characters
|
|
35
35
|
3. Confirm target models: `veo31`, `seedance-2.0`, `kling-3.0`, or a user-provided subset.
|
|
36
|
-
4. Select
|
|
37
|
-
- 4-6 seconds: 1-2
|
|
38
|
-
- 7-10 seconds: 2-3
|
|
39
|
-
- 11-15 seconds: 3-4
|
|
40
|
-
-
|
|
36
|
+
4. Select video phase budget and storyboard sheet panel count:
|
|
37
|
+
- 4-6 seconds: 1-2 video phases
|
|
38
|
+
- 7-10 seconds: 2-3 video phases
|
|
39
|
+
- 11-15 seconds: 3-4 video phases
|
|
40
|
+
- GPT Image 2 storyboard sheet may contain 1-12 panels
|
|
41
|
+
- 5+ distinct real video phases, scene changes, or location/action blocks: split into multiple `SHOTNN.md` files
|
|
41
42
|
5. Build `visual_world`:
|
|
42
43
|
- environment
|
|
43
44
|
- lighting
|
|
@@ -89,7 +90,7 @@ npx @milenyumai/film-kit generate-storyboard \
|
|
|
89
90
|
- Missing character reference: stop and request a valid reference.
|
|
90
91
|
- Empty brief: stop and request a brief.
|
|
91
92
|
- Public figure / real-person likeness / trademark risk: stop or safely anonymize before prompt generation.
|
|
92
|
-
- 5+
|
|
93
|
+
- 5+ real video phases: do not compress into one prompt; split shots. 5-12 storyboard sheet panels alone do not force a split.
|
|
93
94
|
- Missing GPT Image 2 character sheet prompt: output is invalid.
|
|
94
95
|
- Missing GPT Image 2 per-shot storyboard prompt: output is invalid.
|
|
95
96
|
- Missing `Avoid` / negative prompt: output is invalid.
|
|
@@ -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,9 +36,10 @@ 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 follows the duration-aware phase budget, but an explicit storyboard panel hint may request 1-12 panels in one GPT Image 2 storyboard sheet
|
|
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
44
|
- storyboard art grammar: black-and-white rough pencil drawings, minimal detail, rapid gesture energy, simple anatomy construction, strong silhouette readability, unfinished previsualization feel
|
|
44
45
|
- 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
|
|
@@ -108,6 +109,7 @@ Each shot file contains:
|
|
|
108
109
|
- provider reference tokens
|
|
109
110
|
- GPT Image 2 storyboard prompt
|
|
110
111
|
- storyboard interpretation
|
|
112
|
+
- storyboard_creation metadata in `SHOTNN.bundle.json`
|
|
111
113
|
- audio plan
|
|
112
114
|
- prompt bundle for requested models
|
|
113
115
|
- QA verdict
|
|
@@ -116,6 +118,7 @@ Generated files:
|
|
|
116
118
|
|
|
117
119
|
```text
|
|
118
120
|
$OUTPUT_DIR/storyboard-reference-plan.json
|
|
121
|
+
$OUTPUT_DIR/storyboard-prompt.md
|
|
119
122
|
$OUTPUT_DIR/reference-prep/CHARACTER-SHEET-*.md
|
|
120
123
|
$OUTPUT_DIR/storyboard-prompts/SHOTNN-GPT-IMAGE-2-STORYBOARD.md
|
|
121
124
|
$OUTPUT_DIR/prompt-bundles/SHOTNN.bundle.json
|