@slatesvideo/shared 0.5.5 → 0.5.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +1 -1
- package/dist/index.js +2 -2
- package/dist/operations/index.d.ts +81 -1
- package/dist/operations/index.js +435 -10
- package/dist/prompts/character-sheet.d.ts +2 -1
- package/dist/prompts/character-sheet.js +82 -13
- package/dist/prompts/model-facts.d.ts +1 -1
- package/dist/prompts/model-facts.js +32 -0
- package/dist/prompts/prompting-tips.d.ts +1 -1
- package/dist/prompts/prompting-tips.js +194 -0
- package/dist/prompts/reference-rules.d.ts +19 -2
- package/dist/prompts/reference-rules.js +18 -1
- package/dist/skills/content.js +5 -2
- package/exports/slates-prompt-builder/generated/reference-character.md +9 -4
- package/exports/slates-prompt-builder/generated/slates-prompt-builder-manifest.json +6 -6
- package/exports/slates-prompt-builder/generated/slates-prompt-builder.skill +0 -0
- package/package.json +1 -1
- package/skills/slates-character-identity.md +9 -4
- package/skills/slates-model-selection.md +26 -0
- package/skills/slates-prompting-elevenlabs.md +131 -0
- package/skills/slates-prompting-seed-audio.md +110 -0
- package/skills/slates-prompting-suno.md +110 -0
|
@@ -11,14 +11,45 @@
|
|
|
11
11
|
// 2. One authoritative face avoids averaging competing renderings.
|
|
12
12
|
// 3. One generation means one asset to inspect and bind.
|
|
13
13
|
//
|
|
14
|
-
//
|
|
15
|
-
//
|
|
16
|
-
//
|
|
17
|
-
//
|
|
14
|
+
// EXPRESSION IS A SLIGHT SMILE WITH THE TEETH JUST VISIBLE (Eric, 2026-07-30,
|
|
15
|
+
// replacing the v1 neutral default). The v1 note called neutral's missing
|
|
16
|
+
// dental information a "known cost, revisit only if a receipt shows invented
|
|
17
|
+
// teeth" — this is that revisit, and it arrived from the other direction:
|
|
18
|
+
// Eric hand-edited a sheet to smiling and the result "worked really well".
|
|
19
|
+
//
|
|
20
|
+
// WHY: a closed-mouth portrait carries ZERO dental information, so every
|
|
21
|
+
// downstream shot where the character smiles has to invent teeth, and teeth are
|
|
22
|
+
// person-specific and stable — inventing them is a highly visible identity
|
|
23
|
+
// break. The smile also records the nasolabial fold, the eye crinkle and where
|
|
24
|
+
// the cheeks sit raised, none of which a neutral mouth shows.
|
|
25
|
+
//
|
|
26
|
+
// THE COST, NAMED: `references-read-literally.md` says a baked-in property is
|
|
27
|
+
// read as a property of the SUBJECT, so a smile risks a character who smiles
|
|
28
|
+
// through a beat that asked for grief. Survivable because the 2026-06-26
|
|
29
|
+
// doctrine still holds — the user's prompt owns expression, and downstream
|
|
30
|
+
// prompts name an emotional register on every delivered line.
|
|
31
|
+
//
|
|
32
|
+
// SLIGHT, never a grin: a broad smile deforms eyes, cheeks and mouth enough
|
|
33
|
+
// that the model has to un-deform it for any neutral shot.
|
|
34
|
+
//
|
|
35
|
+
// NON-HUMANS ARE CARVED OUT (Eric, 2026-07-30). A smile clause on a horse, a
|
|
36
|
+
// dragon or a robot produces bared teeth. Non-human characters get a natural
|
|
37
|
+
// neutral expression instead. NOTE THE SCOPE DIFFERS from the A-pose carve-out
|
|
38
|
+
// beside it: that one is anatomical (quadruped / non-bipedal), this one is
|
|
39
|
+
// about having a human mouth — so a BIPEDAL robot or humanoid alien is covered
|
|
40
|
+
// by this carve-out and not by that one. Two carve-outs, deliberately, because
|
|
41
|
+
// one predicate does not fit both.
|
|
42
|
+
//
|
|
43
|
+
// Receipt strength: N=1, and it is a "looked right" judgement, not a scored
|
|
44
|
+
// identity-hold comparison against the neutral sheets. HOW YOU'D KNOW THIS IS
|
|
45
|
+
// BEATEN: a character smiling through a beat prompted angry or grieving, or
|
|
46
|
+
// identity holding measurably worse than neutral did. Reverting is one line.
|
|
18
47
|
//
|
|
19
48
|
// THE FRONT PANEL IS HEADLESS (shipped 2026-07-22, receipt-gated). The face is
|
|
20
|
-
// cropped off the front body panel
|
|
21
|
-
//
|
|
49
|
+
// cropped off the front body panel, taking competing face renderings 2 → 1.
|
|
50
|
+
// ONLY the face — the body, neck, arms and hands render normally; see the
|
|
51
|
+
// 2026-07-30 (b) note below for what happens when that isn't said. The BACK
|
|
52
|
+
// panel keeps its head: it has no
|
|
22
53
|
// face to compete with the portrait, and it is the only panel where hair fall
|
|
23
54
|
// reads. The rule is "kill every competing rendering of the FACE", not "kill
|
|
24
55
|
// every head".
|
|
@@ -27,9 +58,45 @@
|
|
|
27
58
|
// real generations (research/model-prompting-research.md, "Head-crop receipt"):
|
|
28
59
|
// 1. It is prompt-reachable. NB2 renders a clean invisible-mannequin panel
|
|
29
60
|
// with no refusal. THIS DEPENDS ON THE PHRASING: it is framed as FRAMING
|
|
30
|
-
// ("cropped at the collarbone,
|
|
31
|
-
//
|
|
32
|
-
//
|
|
61
|
+
// ("cropped at the collarbone, invisible-mannequin presentation"), a
|
|
62
|
+
// standard e-commerce genre with deep training data. Never phrase it as
|
|
63
|
+
// removal or decapitation.
|
|
64
|
+
//
|
|
65
|
+
// 2026-07-30 (a) — THE PHRASING NARROWED, and the receipt above was
|
|
66
|
+
// MODEL-SCOPED. "framed from the collarbone down with the head not shown"
|
|
67
|
+
// passed NB2 and is a HARD 422 on gpt-image-2: fal returns
|
|
68
|
+
// content_policy_violation with loc ["body","prompt"], so the text is
|
|
69
|
+
// rejected before any image is read. Diagnosis: "the head not shown"
|
|
70
|
+
// states an anatomical ABSENCE — a headless human body — which reads as
|
|
71
|
+
// gore to OpenAI's classifier. "cropped at the collarbone" states a
|
|
72
|
+
// CAMERA fact and carries the same instruction.
|
|
73
|
+
// RULE: describe an exclusion as a framing choice, never as a missing
|
|
74
|
+
// body part. The "invisible-mannequin" genre anchor is KEPT because the
|
|
75
|
+
// NB2 receipt says it is what makes the panel reachable there.
|
|
76
|
+
// HOW YOU'D KNOW THIS IS BEATEN: a front panel that comes back with a
|
|
77
|
+
// head on it, meaning "cropped at the collarbone" alone is too weak
|
|
78
|
+
// without the absence clause. If that happens, the fix is a
|
|
79
|
+
// model-conditional phrasing, not restoring the 422.
|
|
80
|
+
//
|
|
81
|
+
// 2026-07-30 (b) — THE GENRE ANCHOR HAS TO BE SCOPED TO THE FACE, and
|
|
82
|
+
// this one cost real generations. "an invisible-mannequin presentation
|
|
83
|
+
// WHERE THE CLOTHING HOLDS ITS OWN SHAPE" is the e-commerce genre stated
|
|
84
|
+
// in full — and the full genre means NO BODY AT ALL, an empty outfit
|
|
85
|
+
// photographed on nothing. Eric's sheets came back with the skin removed:
|
|
86
|
+
// no neck, no hands, no forearms, a floating garment. The genre anchor
|
|
87
|
+
// was doing exactly what it says.
|
|
88
|
+
// Eric's replacement, verbatim, and the default since: "an invisible-
|
|
89
|
+
// mannequin presentation with just the face cropped out." Same anchor
|
|
90
|
+
// (still what makes the panel reachable on NB2), bounded so the only
|
|
91
|
+
// thing missing is the face.
|
|
92
|
+
// RULE: a genre anchor imports the WHOLE genre unless you bound it —
|
|
93
|
+
// name what STAYS, not just what goes. This is the same failure shape as
|
|
94
|
+
// (a) from the opposite side: (a) was an exclusion phrased too
|
|
95
|
+
// anatomically, (b) was an exclusion scoped too widely.
|
|
96
|
+
// HOW YOU'D KNOW THIS IS BEATEN: front panels returning with a head on
|
|
97
|
+
// them — "just the face cropped out" would then be reading as a face
|
|
98
|
+
// edit rather than a crop, leaving the collarbone clause to carry it
|
|
99
|
+
// alone.
|
|
33
100
|
// 2. The literal-reading law does NOT fire on it. This was the real risk and
|
|
34
101
|
// it is ours, not the source corpus's: `references-read-literally.md` says
|
|
35
102
|
// a baked-in property is read as a property of the SUBJECT, and this panel
|
|
@@ -65,11 +132,12 @@ import { renderStyleInstruction } from './style-library.js';
|
|
|
65
132
|
* that cannot match the portrait's, so the sheet would carry two competing
|
|
66
133
|
* identities and the model averages them. A back view has no face to compete
|
|
67
134
|
* with, and it is the only panel where hair fall reads. See the header comment
|
|
68
|
-
* for the receipt and for why the phrasing must stay
|
|
135
|
+
* for the receipt, and for why the phrasing must stay FRAMING rather than
|
|
136
|
+
* removal and must be SCOPED TO THE FACE rather than to the whole body.
|
|
69
137
|
*/
|
|
70
138
|
export const CHARACTER_SHEET_PANELS_DESC = 'a large chest-up portrait on the left at a three-quarter angle (never dead-on), ' +
|
|
71
|
-
'a full-body front view in a relaxed A-pose in the centre,
|
|
72
|
-
'an invisible-mannequin presentation
|
|
139
|
+
'a full-body front view in a relaxed A-pose in the centre, cropped at the collarbone — ' +
|
|
140
|
+
'an invisible-mannequin presentation with just the face cropped out, ' +
|
|
73
141
|
'and a full-body back view on the right with the head and hair fully visible';
|
|
74
142
|
/** Panel identifiers, in sheet order. */
|
|
75
143
|
export const BODY_POSE_LABELS = ['portrait', 'front', 'back'];
|
|
@@ -89,8 +157,9 @@ export function buildCharacterIdentityPrompt(userStyle) {
|
|
|
89
157
|
`${CHARACTER_SHEET_PANELS_DESC}. ` +
|
|
90
158
|
`The portrait is the largest panel and occupies roughly a quarter to a third of the sheet — it is the sole authority for the face, so render it at maximum facial detail. ` +
|
|
91
159
|
`No second rendering of the face anywhere on the sheet. ` +
|
|
92
|
-
`
|
|
160
|
+
`A slight natural smile with the teeth just visible, and identical appearance, wardrobe and hair across all three panels. ` +
|
|
93
161
|
`${styleDirective(userStyle)} ${IDENTITY_LIGHTING_CLAUSE} ${IDENTITY_CRAFT_CLAUSE} ` +
|
|
162
|
+
`For non-human characters, use a natural neutral expression instead of a smile. ` +
|
|
94
163
|
`For quadruped or non-bipedal characters, replace the A-pose with a natural standing stance, show the whole animal including the head on both body panels, and keep the same three-panel layout. ` +
|
|
95
164
|
`No text, no labels, no captions, no panel borders.`);
|
|
96
165
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export interface ModelFact {
|
|
2
2
|
id: string;
|
|
3
3
|
label: string;
|
|
4
|
-
kind: 'image' | 'video';
|
|
4
|
+
kind: 'image' | 'video' | 'audio';
|
|
5
5
|
/** Max reference images (image models) — null if not applicable. */
|
|
6
6
|
maxRefImages: number | null;
|
|
7
7
|
/** Max ingredient images (video models) — null if not applicable. */
|
|
@@ -103,6 +103,38 @@ export const MODEL_FACTS = [
|
|
|
103
103
|
maxIngredients: 0, // prompt + source clip ONLY — no element/style refs on this endpoint
|
|
104
104
|
notes: 'VIDEO-TO-VIDEO EDIT, prompt-only — THE EDIT-FIDELITY WINNER (7/09 head-to-head vs Kling edit on real talking footage: lips held perfectly, audio near-identical, both action beats landed). Takes an EXISTING 3-10s clip and changes what the prompt names, footage-synced (prop/effect/environment/lighting swaps). Fidelity is EARNED by prompt discipline: ONE short instruction + "Keep everything else the same." — long descriptive prompts DESTROY it (Google-documented + 7/09 receipt). Never name objects as metaphors ("candle-like" → literal candle). Quirk: occasional tail jitter/doubled last speech beat — trim the tail. NO reference images (identity swaps needing refs → Kling edit); bit-exact audio needs → Kling keep_audio or segment-splice. 720p output, cheapest edit seat (~2/3 of Kling edit Std).',
|
|
105
105
|
},
|
|
106
|
+
{
|
|
107
|
+
id: 'seed-audio',
|
|
108
|
+
label: 'Seed Audio 1.0',
|
|
109
|
+
kind: 'audio',
|
|
110
|
+
maxRefImages: 1, // ONE image XOR up to 3 audio clips — the two inputs are mutually exclusive.
|
|
111
|
+
maxIngredients: null,
|
|
112
|
+
notes: 'DEFAULT audio model — the one-pass SCENE workhorse: dialogue, SFX, and ambience together from ONE plain sentence. Route here for continuity beds, room tone, crowd/nature soundscapes, and quick scratch VO. AUDIO-ONLY: cannot generate images or video. 🚨 THERE IS NO DURATION PARAMETER — length comes from the words, so you MUST NAME THE LENGTH IN THE PROMPT TEXT ("... 15 seconds"). Slates appends the requested length automatically and BILLS the requested seconds, so a prompt that fights the number wastes credits. Prompts are ONE plain sentence, no production jargon and no SFX:/Ambient: prefixes (those are Kling syntax and hurt here). Say the crowd size out loud — "applause" returns a full room when the joke was three people. 1-120s. Inputs: ONE image (describe-what-you-see scoring) XOR up to 3 audio clips referenced in the prompt as @Audio1-@Audio3, never both. 20 preset voices, or leave voice unset and let the scene cast itself.',
|
|
113
|
+
},
|
|
114
|
+
{
|
|
115
|
+
id: 'eleven-v3',
|
|
116
|
+
label: 'ElevenLabs Eleven v3 (TTS)',
|
|
117
|
+
kind: 'audio',
|
|
118
|
+
maxRefImages: null,
|
|
119
|
+
maxIngredients: null,
|
|
120
|
+
notes: 'CONTROLLED, REPEATABLE named-voice VOICEOVER — route here whenever the exact words matter and must be re-renderable in the same voice (ad reads, narration, character lines to lip-sync against). AUDIO-ONLY. The text field IS the script: it is spoken verbatim, so never put stage directions in it. 1-5000 characters, billed per 100-character bucket, so trimming a sentence genuinely saves credits. 20 preset voices (Rachel default) — pick one and keep it for the whole piece. stability 0-1 trades consistency against expressiveness (low = more emotive and more variable). No voice cloning on this route. Word-level timestamps come back free and are what a future caption pass consumes. For scene ambience or SFX rather than speech, use seed-audio / eleven-sfx.',
|
|
121
|
+
},
|
|
122
|
+
{
|
|
123
|
+
id: 'eleven-sfx',
|
|
124
|
+
label: 'ElevenLabs Sound Effects v2',
|
|
125
|
+
kind: 'audio',
|
|
126
|
+
maxRefImages: null,
|
|
127
|
+
maxIngredients: null,
|
|
128
|
+
notes: 'ONE-SHOT SOUND EFFECT with an EXACT duration — route here for a single hit that must land on a frame (door slam, whoosh, impact, UI blip) or for a seamless loop. AUDIO-ONLY. 0.5-22s, and Slates always sends the duration explicitly (a null duration means a non-deterministic charge, so it is never left to the model). Describe the physical CAUSE, not the label: "heavy oak door slams shut in a stone hallway" beats "door sound". Text caps at 450 characters. loop=true produces a seamless bed. prompt_influence 0-1: higher hugs the prompt with less variation, lower explores. For layered scenes with dialogue or room tone, seed-audio does it in one pass instead.',
|
|
129
|
+
},
|
|
130
|
+
{
|
|
131
|
+
id: 'suno',
|
|
132
|
+
label: 'Suno',
|
|
133
|
+
kind: 'audio',
|
|
134
|
+
maxRefImages: null,
|
|
135
|
+
maxIngredients: null,
|
|
136
|
+
notes: 'FULL MUSIC TRACKS with structure — route here for anything a listener would call a song or a score. AUDIO-ONLY. EVERY call returns TWO variations for one flat price, and duration is FREE up to 360s (measured 2026-07-31: a 240s track costs the same as a default one), which makes it the cheapest way to get a bed that outlasts a cut. Two modes: DESCRIPTION mode (customMode=false, prompt is a <=500-char description and the lyrics get written for you) and CUSTOM mode (customMode=true, needs style + title; prompt then holds the EXACT LYRICS, sung as written — never put a description there). instrumental=true scores a scene with no vocals. Steer with style/negativeTags rather than piling adjectives into the prompt. duration 10-360s is V5_5 + custom mode only. Unofficial API wrapper, so treat availability as best-effort.',
|
|
137
|
+
},
|
|
106
138
|
];
|
|
107
139
|
const FACT_BY_ID = new Map(MODEL_FACTS.map((m) => [m.id, m]));
|
|
108
140
|
export function getModelFact(id) {
|
|
@@ -16,7 +16,7 @@ export interface PromptingTipsEntry {
|
|
|
16
16
|
/** Footer callout paragraphs. */
|
|
17
17
|
footer?: string[];
|
|
18
18
|
}
|
|
19
|
-
export type PromptingTipsKey = 'seedance' | 'kling' | 'kling-edit' | 'veo' | 'omni-flash' | 'omni-flash-edit' | 'nano-banana' | 'nano-banana-lite';
|
|
19
|
+
export type PromptingTipsKey = 'seedance' | 'kling' | 'kling-edit' | 'veo' | 'omni-flash' | 'omni-flash-edit' | 'nano-banana' | 'nano-banana-lite' | 'seed-audio' | 'eleven-v3' | 'eleven-sfx' | 'suno';
|
|
20
20
|
export declare const PROMPTING_TIPS: Record<PromptingTipsKey, PromptingTipsEntry>;
|
|
21
21
|
/** Null when no tips exist for the key — callers render an honest fallback. */
|
|
22
22
|
export declare function getPromptingTips(key: string): PromptingTipsEntry | null;
|
|
@@ -359,6 +359,196 @@ const NANO_BANANA_LITE = {
|
|
|
359
359
|
: card),
|
|
360
360
|
],
|
|
361
361
|
};
|
|
362
|
+
// ── Audio lane ──────────────────────────────────────────────────
|
|
363
|
+
// The four audio surfaces prompt NOTHING like the video models. The single
|
|
364
|
+
// most expensive mistake is bringing Kling's "SFX:" / "Ambient noise:" syntax
|
|
365
|
+
// to Seed Audio, which reads it as literal text. Every entry below leads with
|
|
366
|
+
// what the surface actually wants.
|
|
367
|
+
const SEED_AUDIO = {
|
|
368
|
+
label: 'Seed Audio 1.0',
|
|
369
|
+
intro: [
|
|
370
|
+
'Seed Audio builds a whole audio scene — dialogue, effects and ambience together — from one plain sentence. Write it the way you would describe the moment to a person standing next to you, not the way you would write a video prompt.',
|
|
371
|
+
'It has no duration setting. Length comes from the words, so Slates appends your chosen duration to the prompt ("… 15 seconds") and bills exactly that. Set the duration control to what you actually want and let the sentence stay clean.',
|
|
372
|
+
],
|
|
373
|
+
columns: [
|
|
374
|
+
[
|
|
375
|
+
{
|
|
376
|
+
heading: 'One plain sentence',
|
|
377
|
+
example: 'nature soundscape, wide open field cicadas and birds and a loon.',
|
|
378
|
+
note: 'No shot language, no production jargon, no formatting. Plain description outperforms anything that reads like a spec sheet.',
|
|
379
|
+
},
|
|
380
|
+
{
|
|
381
|
+
heading: 'Duration lives in the prompt',
|
|
382
|
+
example: 'tiny applause of 2 or 3 people at an open mic. 15 seconds',
|
|
383
|
+
note: 'The duration control writes this for you. Do not also type a different length into your sentence — the two will fight and you pay for the one you selected.',
|
|
384
|
+
critical: true,
|
|
385
|
+
},
|
|
386
|
+
{
|
|
387
|
+
heading: 'Say the crowd size',
|
|
388
|
+
example: 'tiny applause of 2 or 3 people · a packed arena roaring',
|
|
389
|
+
note: '"Applause" alone returns a full room. Scale words are the single highest-leverage edit on any crowd, traffic or nature bed.',
|
|
390
|
+
},
|
|
391
|
+
{
|
|
392
|
+
heading: 'Cut beds longer than the shot',
|
|
393
|
+
note: 'Ask for a few seconds more than the clip needs so the edit has handles to fade in and out of. Beds that end exactly on the cut always sound clipped.',
|
|
394
|
+
},
|
|
395
|
+
],
|
|
396
|
+
[
|
|
397
|
+
{
|
|
398
|
+
heading: 'No Kling syntax here',
|
|
399
|
+
example: '✗ SFX: heavy boots\n✓ heavy boots on wet pavement, a siren far off',
|
|
400
|
+
note: 'The "SFX:" and "Ambient noise:" prefixes belong to Kling video prompts. Seed Audio treats them as words in the scene and the result gets worse.',
|
|
401
|
+
critical: true,
|
|
402
|
+
},
|
|
403
|
+
{
|
|
404
|
+
heading: 'Dialogue in quotes',
|
|
405
|
+
example: 'a tired bartender says, "we closed twenty minutes ago", glasses clinking behind him',
|
|
406
|
+
note: 'Speech goes in quotes inside the same sentence as the room. Pick a preset voice for a specific speaker, or leave it unset and let the scene cast itself.',
|
|
407
|
+
},
|
|
408
|
+
{
|
|
409
|
+
heading: 'References',
|
|
410
|
+
example: 'match the room tone of @Audio1',
|
|
411
|
+
note: 'Up to 3 audio clips (max 30s each), referenced as @Audio1–@Audio3 — OR one image to score what is in frame. Never both in the same generation.',
|
|
412
|
+
},
|
|
413
|
+
{
|
|
414
|
+
heading: 'Know its seat',
|
|
415
|
+
note: 'Scenes, beds and room tone in one pass. For an exact script in a repeatable voice use Eleven v3; for a single effect on a specific frame use Sound Effects; for a song use Suno.',
|
|
416
|
+
},
|
|
417
|
+
],
|
|
418
|
+
],
|
|
419
|
+
};
|
|
420
|
+
const ELEVEN_V3 = {
|
|
421
|
+
label: 'ElevenLabs Eleven v3',
|
|
422
|
+
intro: [
|
|
423
|
+
'Eleven v3 speaks your text verbatim in a named voice. It is the controlled, repeatable lane: the same text and the same voice give you a read you can regenerate after a script tweak without the performance drifting.',
|
|
424
|
+
'Billing is per 100 characters of text, rounded up — so tightening a sentence genuinely costs less, and a stray pasted paragraph genuinely costs more.',
|
|
425
|
+
],
|
|
426
|
+
columns: [
|
|
427
|
+
[
|
|
428
|
+
{
|
|
429
|
+
heading: 'The text field is the script',
|
|
430
|
+
example: '✗ (excited) Say this fast: Grab yours today!\n✓ Grab yours today!',
|
|
431
|
+
note: 'Everything you type gets spoken. Stage directions, character names and bracketed notes will be read out loud.',
|
|
432
|
+
critical: true,
|
|
433
|
+
},
|
|
434
|
+
{
|
|
435
|
+
heading: 'Punctuate for pace',
|
|
436
|
+
example: 'It works. Every time. · It works — every time…',
|
|
437
|
+
note: 'Full stops, commas, dashes and ellipses are your only timing controls. Rewrite the punctuation before you touch the settings.',
|
|
438
|
+
},
|
|
439
|
+
{
|
|
440
|
+
heading: 'Pick a voice and stay',
|
|
441
|
+
note: '20 preset voices. Choosing one per character or per piece is what makes a series sound deliberate; swapping voices mid-piece reads as a mistake.',
|
|
442
|
+
},
|
|
443
|
+
],
|
|
444
|
+
[
|
|
445
|
+
{
|
|
446
|
+
heading: 'Stability',
|
|
447
|
+
example: '0.3 emotive · 0.5 default · 0.8 steady',
|
|
448
|
+
note: 'Lower is more expressive and more variable take-to-take. Higher is flatter and more repeatable. Raise it for long narration, lower it for a single dramatic line.',
|
|
449
|
+
},
|
|
450
|
+
{
|
|
451
|
+
heading: 'Spell out the tricky bits',
|
|
452
|
+
example: 'SKU → "ess kay you" · 2026 → "twenty twenty six"',
|
|
453
|
+
note: 'Acronyms, product names, prices and years are where TTS embarrasses itself. Write the pronunciation you want.',
|
|
454
|
+
},
|
|
455
|
+
{
|
|
456
|
+
heading: 'Know its seat',
|
|
457
|
+
note: 'Exact words, repeatable voice, lines you will lip-sync against. Ambience, crowds and rooms belong to Seed Audio; one-shot effects to Sound Effects.',
|
|
458
|
+
},
|
|
459
|
+
],
|
|
460
|
+
],
|
|
461
|
+
footer: [
|
|
462
|
+
'Word-level timestamps come back with every generation at no extra cost — that is what a future caption pass will read, so there is no reason to turn them off.',
|
|
463
|
+
],
|
|
464
|
+
};
|
|
465
|
+
const ELEVEN_SFX = {
|
|
466
|
+
label: 'ElevenLabs Sound Effects',
|
|
467
|
+
intro: [
|
|
468
|
+
'Sound Effects makes one short sound with an exact length — the lane for a hit that has to land on a specific frame, or a seamless loop you can lay under a whole scene.',
|
|
469
|
+
'Duration is always sent explicitly (0.5–22s). Billing is per second, so the length you pick is the price you pay.',
|
|
470
|
+
],
|
|
471
|
+
columns: [
|
|
472
|
+
[
|
|
473
|
+
{
|
|
474
|
+
heading: 'Describe the cause, not the label',
|
|
475
|
+
example: '✗ door sound\n✓ heavy oak door slams shut in a stone hallway',
|
|
476
|
+
note: 'Material, weight and room are what separate a usable effect from a stock-library shrug. Name all three.',
|
|
477
|
+
critical: true,
|
|
478
|
+
},
|
|
479
|
+
{
|
|
480
|
+
heading: 'One sound per generation',
|
|
481
|
+
note: 'This surface makes a single event. A door, then footsteps, then a siren is three generations layered on the timeline — or one Seed Audio scene.',
|
|
482
|
+
},
|
|
483
|
+
{
|
|
484
|
+
heading: 'Duration is the edit',
|
|
485
|
+
example: '0.8s for an impact · 4s for a whoosh · 22s for a bed',
|
|
486
|
+
note: 'Ask for roughly the length you need. A 4-second request for a door slam pads the tail with room tone you then have to trim.',
|
|
487
|
+
},
|
|
488
|
+
],
|
|
489
|
+
[
|
|
490
|
+
{
|
|
491
|
+
heading: 'Loops',
|
|
492
|
+
example: 'steady rain on a canvas tent (loop on, 12s)',
|
|
493
|
+
note: 'Turn loop on for anything continuous — rain, engine hum, crowd murmur — and it will tile without a seam.',
|
|
494
|
+
},
|
|
495
|
+
{
|
|
496
|
+
heading: 'Prompt influence',
|
|
497
|
+
example: '0.3 default · 0.7 literal',
|
|
498
|
+
note: 'Higher hugs your wording with less variation between takes; lower explores. Raise it when a re-roll keeps wandering off the brief.',
|
|
499
|
+
},
|
|
500
|
+
{
|
|
501
|
+
heading: 'Know its seat',
|
|
502
|
+
note: 'One precise effect on a known frame. Full rooms and layered scenes are cheaper and better in one Seed Audio pass.',
|
|
503
|
+
},
|
|
504
|
+
],
|
|
505
|
+
],
|
|
506
|
+
};
|
|
507
|
+
const SUNO = {
|
|
508
|
+
label: 'Suno',
|
|
509
|
+
intro: [
|
|
510
|
+
'Suno writes full music. Every generation returns TWO variations for one flat price, and length is free up to six minutes — so there is never a reason to generate a bed that is shorter than your edit.',
|
|
511
|
+
'The one thing to get right is which mode you are in, because it changes what the prompt field means.',
|
|
512
|
+
],
|
|
513
|
+
columns: [
|
|
514
|
+
[
|
|
515
|
+
{
|
|
516
|
+
heading: 'Description mode',
|
|
517
|
+
example: 'brooding synthwave for a night drive, analog bass, no vocals',
|
|
518
|
+
note: 'The prompt is a description (max 500 characters) and the lyrics get written for you. This is the fast path when you just need a mood.',
|
|
519
|
+
},
|
|
520
|
+
{
|
|
521
|
+
heading: 'Custom mode — the prompt IS the lyrics',
|
|
522
|
+
example: 'Style: dream pop, hazy\nTitle: Blue Hour\nPrompt: [Verse 1] The lights come on…',
|
|
523
|
+
note: 'In custom mode the prompt is sung exactly as written. Putting a description there gets your description sung back at you.',
|
|
524
|
+
critical: true,
|
|
525
|
+
},
|
|
526
|
+
{
|
|
527
|
+
heading: 'Instrumental',
|
|
528
|
+
note: 'Turn instrumental on to score a scene with no vocals — style and title still steer it, and the prompt field is ignored.',
|
|
529
|
+
},
|
|
530
|
+
],
|
|
531
|
+
[
|
|
532
|
+
{
|
|
533
|
+
heading: 'Steer with style, not adjectives',
|
|
534
|
+
example: 'Style: 90s trip-hop, dusty breakbeat, Rhodes\nAvoid: brass, EDM drops',
|
|
535
|
+
note: 'Genre, era, instrumentation and tempo belong in the style field. Negative tags remove what keeps creeping in.',
|
|
536
|
+
},
|
|
537
|
+
{
|
|
538
|
+
heading: 'Length is free',
|
|
539
|
+
example: '10–360 seconds',
|
|
540
|
+
note: 'A six-minute track costs exactly what a default one does. Ask for longer than the cut needs and trim on the timeline.',
|
|
541
|
+
},
|
|
542
|
+
{
|
|
543
|
+
heading: 'Two songs, both yours',
|
|
544
|
+
note: 'Both variations land in the gallery. They are genuinely different takes on the same brief — audition both before re-rolling.',
|
|
545
|
+
},
|
|
546
|
+
],
|
|
547
|
+
],
|
|
548
|
+
footer: [
|
|
549
|
+
'Files are hosted by the provider for a limited window — Slates downloads and stores them on your machine as soon as the track finishes, so nothing expires out from under a project.',
|
|
550
|
+
],
|
|
551
|
+
};
|
|
362
552
|
export const PROMPTING_TIPS = {
|
|
363
553
|
seedance: SEEDANCE,
|
|
364
554
|
kling: KLING,
|
|
@@ -368,6 +558,10 @@ export const PROMPTING_TIPS = {
|
|
|
368
558
|
'omni-flash-edit': OMNI_FLASH_EDIT,
|
|
369
559
|
'nano-banana': NANO_BANANA,
|
|
370
560
|
'nano-banana-lite': NANO_BANANA_LITE,
|
|
561
|
+
'seed-audio': SEED_AUDIO,
|
|
562
|
+
'eleven-v3': ELEVEN_V3,
|
|
563
|
+
'eleven-sfx': ELEVEN_SFX,
|
|
564
|
+
suno: SUNO,
|
|
371
565
|
};
|
|
372
566
|
/** Null when no tips exist for the key — callers render an honest fallback. */
|
|
373
567
|
export function getPromptingTips(key) {
|
|
@@ -20,8 +20,25 @@ export declare const IDENTITY_LIGHTING = "flat, even, shadowless lighting";
|
|
|
20
20
|
* crushes hair and wardrobe silhouettes.** A deep neutral grey holds both.
|
|
21
21
|
*/
|
|
22
22
|
export declare const IDENTITY_PLATE_HEX = "#3a3a3c";
|
|
23
|
-
|
|
24
|
-
|
|
23
|
+
/**
|
|
24
|
+
* 🚨 THE HEX IS EMITTED WITHOUT ITS `#` AND THAT IS LOAD-BEARING (2026-07-30).
|
|
25
|
+
*
|
|
26
|
+
* `#` is a REFERENCE-TOKEN SIGIL in the desktop's prompt composer
|
|
27
|
+
* (`slate/src/shared/promptComposition.ts` — `/([@#])([\w-]+)/g`), and an
|
|
28
|
+
* unresolved `#token` is SILENTLY DELETED. So `#3a3a3c` never survived to any
|
|
29
|
+
* model: fal echoed back `deep neutral-grey background ()` on a real 2026-07-30
|
|
30
|
+
* request. The plate value has been doing nothing since the composer shipped.
|
|
31
|
+
*
|
|
32
|
+
* Writing it bare keeps the value in the prompt. `IDENTITY_PLATE_HEX` keeps its
|
|
33
|
+
* `#` because it is a colour constant and may have non-prompt consumers.
|
|
34
|
+
*
|
|
35
|
+
* GENERAL RULE FOR THIS FILE: never emit `#` or `@` into prompt text. Both are
|
|
36
|
+
* sigils downstream and both mangle silently — no error, no log, just missing
|
|
37
|
+
* words. HOW YOU'D KNOW THIS IS BEATEN: the composer stops treating bare
|
|
38
|
+
* `#hex` as a token, or starts leaving unresolved tokens intact.
|
|
39
|
+
*/
|
|
40
|
+
export declare const IDENTITY_BACKGROUND: string;
|
|
41
|
+
export declare const IDENTITY_LIGHTING_CLAUSE: string;
|
|
25
42
|
/**
|
|
26
43
|
* Craft clauses every identity reference wants — the eye and skin detail that
|
|
27
44
|
* survives downstream, plus the two "reads literally" guards. Crushed-black
|
|
@@ -96,7 +96,24 @@ export const IDENTITY_LIGHTING = 'flat, even, shadowless lighting';
|
|
|
96
96
|
* crushes hair and wardrobe silhouettes.** A deep neutral grey holds both.
|
|
97
97
|
*/
|
|
98
98
|
export const IDENTITY_PLATE_HEX = '#3a3a3c';
|
|
99
|
-
|
|
99
|
+
/**
|
|
100
|
+
* 🚨 THE HEX IS EMITTED WITHOUT ITS `#` AND THAT IS LOAD-BEARING (2026-07-30).
|
|
101
|
+
*
|
|
102
|
+
* `#` is a REFERENCE-TOKEN SIGIL in the desktop's prompt composer
|
|
103
|
+
* (`slate/src/shared/promptComposition.ts` — `/([@#])([\w-]+)/g`), and an
|
|
104
|
+
* unresolved `#token` is SILENTLY DELETED. So `#3a3a3c` never survived to any
|
|
105
|
+
* model: fal echoed back `deep neutral-grey background ()` on a real 2026-07-30
|
|
106
|
+
* request. The plate value has been doing nothing since the composer shipped.
|
|
107
|
+
*
|
|
108
|
+
* Writing it bare keeps the value in the prompt. `IDENTITY_PLATE_HEX` keeps its
|
|
109
|
+
* `#` because it is a colour constant and may have non-prompt consumers.
|
|
110
|
+
*
|
|
111
|
+
* GENERAL RULE FOR THIS FILE: never emit `#` or `@` into prompt text. Both are
|
|
112
|
+
* sigils downstream and both mangle silently — no error, no log, just missing
|
|
113
|
+
* words. HOW YOU'D KNOW THIS IS BEATEN: the composer stops treating bare
|
|
114
|
+
* `#hex` as a token, or starts leaving unresolved tokens intact.
|
|
115
|
+
*/
|
|
116
|
+
export const IDENTITY_BACKGROUND = `a plain, deep neutral-grey background (hex ${IDENTITY_PLATE_HEX.replace('#', '')})`;
|
|
100
117
|
export const IDENTITY_LIGHTING_CLAUSE = `Render on ${IDENTITY_BACKGROUND} with ${IDENTITY_LIGHTING} so the sheet captures the character's identity, not scene lighting.`;
|
|
101
118
|
/**
|
|
102
119
|
* Craft clauses every identity reference wants — the eye and skin detail that
|