@slatesvideo/shared 0.4.8 → 0.5.1

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.
@@ -12,6 +12,30 @@ export const MODEL_FACTS = [
12
12
  maxIngredients: null,
13
13
  notes: 'Default image model. 14 refs hard cap (10 object + 4 character). Brief it like a creative director, not tag soup. No negativePrompt field — use positive reframing. Best image start-frame for legible text. Knowledge cutoff Jan 2025.',
14
14
  },
15
+ {
16
+ id: 'nano-banana-2-lite',
17
+ label: 'Nano Banana 2 Lite',
18
+ kind: 'image',
19
+ maxRefImages: 4,
20
+ maxIngredients: null,
21
+ notes: 'FAST/DRAFT image tier — ~half the price of NB2 full, ~2.7× faster, 1K output ONLY. Same Gemini content filter as NB2. Route here for iteration volume and drafts where 1K is fine; keep NB2 full for final 2K/4K. Character consistency + legible text hold up.',
22
+ },
23
+ {
24
+ id: 'nano-banana-pro',
25
+ label: 'Nano Banana Pro',
26
+ kind: 'image',
27
+ maxRefImages: 14,
28
+ maxIngredients: null,
29
+ notes: 'HERO-FRAME / typography PREMIUM image tier (Gemini 3 Pro backbone; ~2× NB2 price). NB2 ≈ 95% of Pro — route here only when spatial composition, cinematic lighting/skin, fine typography-in-scene, or deep multi-element reasoning must be perfect. Up to 14 reference images (character locking, multi-subject fusion). Native 16:9 + 4K.',
30
+ },
31
+ {
32
+ id: 'gpt-image-2',
33
+ label: 'GPT Image 2',
34
+ kind: 'image',
35
+ maxRefImages: 10,
36
+ maxIngredients: null,
37
+ notes: 'TEXT/DIAGRAM/PANEL king — near-perfect character-level text, ordered panels, exact placement (~3s gens). Route here for character sheets, shot grids, and text-bearing panels. Quality tiers: medium (default, the value seat — half NB2 price at 1080p) / high (~4×, max text precision). Third filter regime (OpenAI moderate). 4K is API-only — even paid ChatGPT can\'t render it. Photoreal/character-locked/edit-heavy → Banana line instead.',
38
+ },
15
39
  {
16
40
  id: 'flux-2-max',
17
41
  label: 'FLUX.2 Max',
@@ -34,7 +58,7 @@ export const MODEL_FACTS = [
34
58
  kind: 'video',
35
59
  maxRefImages: null,
36
60
  maxIngredients: 9, // ingredient images per video gen
37
- notes: 'PREMIUM video tier — route here the moment physics, effects, destruction, or scale matter, and for hero shots. VIDEO-ONLY: cannot generate standalone images (use NB2/FLUX.2/Seedream for those). Up to 9 ingredient images. Strong I2V / own-footage restyle. Native 4K.',
61
+ notes: 'PREMIUM video tier — route here the moment physics, effects, destruction, or scale matter, and for hero shots. VIDEO-ONLY: cannot generate standalone images (use NB2/FLUX.2/Seedream for those). Up to 9 ingredient images. Strong I2V / own-footage restyle. Native 4K. Also the PREMIUM engine inside the Motion Transfer and Lip Sync tools (single-pass: driving video / dialogue are native conditioning signals — better motion fidelity, natural speech, voice cloned from a video source; video references bill input+output seconds).',
38
62
  },
39
63
  {
40
64
  id: 'kling-v3',
@@ -42,7 +66,15 @@ export const MODEL_FACTS = [
42
66
  kind: 'video',
43
67
  maxRefImages: null,
44
68
  maxIngredients: 4,
45
- notes: 'DEFAULT general-purpose video model — cost-effective, strong start-frame adherence (identity/layout/text), acting, dialogue, lip-sync, any aspect ratio. Escalate to Seedance for physics.',
69
+ notes: 'DEFAULT general-purpose video model — cost-effective, strong start-frame adherence (identity/layout/text), acting, dialogue, lip-sync, any aspect ratio. Escalate to Seedance for physics. In the Motion Transfer / Lip Sync tools, Kling (MC / lip-sync / avatar) is the cheap utility lane; Seedance is the premium single-pass lane.',
70
+ },
71
+ {
72
+ id: 'kling-v3-edit',
73
+ label: 'Kling O3 Video Edit',
74
+ kind: 'video',
75
+ maxRefImages: null,
76
+ maxIngredients: 4, // combined subject elements + style refs per edit
77
+ notes: 'VIDEO-TO-VIDEO EDIT (default edit tool) — takes an EXISTING 3–15s clip and changes only what the prompt names: character swap, environment change, style transfer. Original motion/camera/audio preserved. One pass, no masking. Use to FIX a 90%-right clip instead of re-rolling it, or to AI-edit the user\'s own footage. Elements (@ElementN = frontal + angles) lock subject identity; max 4 combined refs. Billed per second of output (≈ clip length, rounded up). Seedance edit/relocate is the alternative for style-transfer-heavy jobs.',
46
78
  },
47
79
  {
48
80
  id: 'veo-3.1',
@@ -43,4 +43,39 @@ export interface ComposeOptions {
43
43
  startVideoNumber?: number;
44
44
  }
45
45
  export declare function composeReferences(rawPrompt: string, groups: ReferenceGroup[], opts?: ComposeOptions): ComposedReferences;
46
+ export interface KlingEditElement {
47
+ /** Frontal image path/URL (element primary view) */
48
+ frontal: string;
49
+ /** Up to 3 additional angle images */
50
+ angles: string[];
51
+ /** Display name (for logging/echo) */
52
+ name: string;
53
+ }
54
+ export interface KlingEditComposition {
55
+ /** Prompt in Kling's edit notation: @Video1 (source), @ElementN, @ImageN */
56
+ prompt: string;
57
+ /** Subject elements in cited order (@Element1..) */
58
+ elements: KlingEditElement[];
59
+ /** Style/appearance reference image paths in cited order (@Image1..) */
60
+ styleImages: string[];
61
+ }
62
+ /** fal cap: max 4 combined element + style-image references per edit request. */
63
+ export declare const KLING_EDIT_MAX_REFS = 4;
64
+ /**
65
+ * Compose references for the Kling O3 edit endpoint. Unlike the "image N"
66
+ * naming every other model parses, Kling's edit endpoint has its OWN official
67
+ * notation: `@Video1` (the source clip), `@Element1..` (subjects, frontal +
68
+ * angle images), `@Image1..` (style/appearance refs). This adapter translates
69
+ * the one-ordered-list groups into that notation — the same prompt-is-law
70
+ * principle, different citation tokens.
71
+ *
72
+ * - character/environment groups → elements (media[0] = frontal, rest = angles,
73
+ * max 3 angles per fal's schema)
74
+ * - style/pinned image groups → @ImageN style refs
75
+ * - video groups are ignored here — the source clip is transported separately
76
+ * and is always @Video1
77
+ * - combined element+image count is capped at KLING_EDIT_MAX_REFS (style refs
78
+ * trimmed first — subjects are the feature)
79
+ */
80
+ export declare function composeKlingEdit(rawPrompt: string, groups: ReferenceGroup[]): KlingEditComposition;
46
81
  //# sourceMappingURL=reference-composer.d.ts.map
@@ -172,4 +172,85 @@ export function composeReferences(rawPrompt, groups, opts = {}) {
172
172
  orderedVideoPaths,
173
173
  };
174
174
  }
175
+ /** fal cap: max 4 combined element + style-image references per edit request. */
176
+ export const KLING_EDIT_MAX_REFS = 4;
177
+ /**
178
+ * Compose references for the Kling O3 edit endpoint. Unlike the "image N"
179
+ * naming every other model parses, Kling's edit endpoint has its OWN official
180
+ * notation: `@Video1` (the source clip), `@Element1..` (subjects, frontal +
181
+ * angle images), `@Image1..` (style/appearance refs). This adapter translates
182
+ * the one-ordered-list groups into that notation — the same prompt-is-law
183
+ * principle, different citation tokens.
184
+ *
185
+ * - character/environment groups → elements (media[0] = frontal, rest = angles,
186
+ * max 3 angles per fal's schema)
187
+ * - style/pinned image groups → @ImageN style refs
188
+ * - video groups are ignored here — the source clip is transported separately
189
+ * and is always @Video1
190
+ * - combined element+image count is capped at KLING_EDIT_MAX_REFS (style refs
191
+ * trimmed first — subjects are the feature)
192
+ */
193
+ export function composeKlingEdit(rawPrompt, groups) {
194
+ const elements = [];
195
+ const styleImages = [];
196
+ const styleNums = [];
197
+ let body = rawPrompt;
198
+ // Subjects first — they own the @ElementN numbering.
199
+ const subjectGroups = groups.filter((g) => (g.kind === 'character' || g.kind === 'environment') && g.media.some((m) => m.mediaKind === 'image'));
200
+ for (const g of subjectGroups) {
201
+ if (elements.length >= KLING_EDIT_MAX_REFS)
202
+ break;
203
+ const imgs = g.media.filter((m) => m.mediaKind === 'image').map((m) => m.path);
204
+ if (imgs.length === 0)
205
+ continue;
206
+ const n = elements.length + 1;
207
+ elements.push({ frontal: imgs[0], angles: imgs.slice(1, 4), name: g.name });
208
+ if (g.token) {
209
+ // Replace every @token occurrence with the element citation.
210
+ const escaped = g.token.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
211
+ const re = new RegExp(`${escaped}\\b`, 'gi');
212
+ if (re.test(body)) {
213
+ body = body.replace(re, `@Element${n}`);
214
+ }
215
+ else {
216
+ body = `${body}\n@Element${n} is ${g.name}.`;
217
+ }
218
+ }
219
+ else {
220
+ body = `${body}\n@Element${n} is ${g.name}.`;
221
+ }
222
+ }
223
+ // Style / pinned refs take the remaining slots as @ImageN.
224
+ for (const g of groups) {
225
+ if (g.kind !== 'style' && g.kind !== 'pinned')
226
+ continue;
227
+ for (const m of g.media) {
228
+ if (m.mediaKind !== 'image')
229
+ continue;
230
+ if (elements.length + styleImages.length >= KLING_EDIT_MAX_REFS)
231
+ break;
232
+ styleImages.push(m.path);
233
+ const n = styleImages.length;
234
+ if (g.kind === 'style')
235
+ styleNums.push(n);
236
+ if (g.token) {
237
+ const escaped = g.token.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
238
+ body = body.replace(new RegExp(`${escaped}\\b`, 'gi'), `@Image${n}`);
239
+ }
240
+ }
241
+ }
242
+ if (styleNums.length > 0) {
243
+ const cites = styleNums.map((n) => `@Image${n}`).join(' and ');
244
+ body = `${body}\nApply the visual style of ${cites}.`;
245
+ }
246
+ // The source clip is always @Video1 — anchor the instruction to it.
247
+ if (!/@Video1\b/i.test(body)) {
248
+ body = `Edit @Video1: ${body}`;
249
+ }
250
+ return {
251
+ prompt: body.replace(/[ \t]{2,}/g, ' ').trim(),
252
+ elements,
253
+ styleImages,
254
+ };
255
+ }
175
256
  //# sourceMappingURL=reference-composer.js.map