@slatesvideo/shared 0.4.1 → 0.4.3

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/package.json CHANGED
@@ -1,59 +1,64 @@
1
- {
2
- "name": "@slatesvideo/shared",
3
- "version": "0.4.1",
4
- "description": "Shared operations layer for the Slates MCP server and CLI: auth, cloud/desktop clients, and the single tool surface both consume. Most users want @slatesvideo/mcp-server or @slatesvideo/cli instead.",
5
- "license": "MIT",
6
- "type": "module",
7
- "main": "./dist/index.js",
8
- "types": "./dist/index.d.ts",
9
- "exports": {
10
- ".": {
11
- "import": "./dist/index.js",
12
- "types": "./dist/index.d.ts"
13
- },
14
- "./auth": "./dist/auth.js",
15
- "./clients/cloud": "./dist/clients/cloud.js",
16
- "./clients/desktop": "./dist/clients/desktop.js",
17
- "./operations": "./dist/operations/index.js",
18
- "./prompts": {
19
- "import": "./dist/prompts/index.js",
20
- "types": "./dist/prompts/index.d.ts"
21
- }
22
- },
23
- "files": ["dist", "!dist/**/*.map", "skills", "README.md"],
24
- "scripts": {
25
- "build": "node scripts/embed-skills.mjs && tsc",
26
- "typecheck": "node scripts/embed-skills.mjs && tsc --noEmit",
27
- "prepublishOnly": "npm run build"
28
- },
29
- "repository": {
30
- "type": "git",
31
- "url": "git+https://github.com/EricDisero/slates-mcp.git",
32
- "directory": "packages/shared"
33
- },
34
- "homepage": "https://slates.video",
35
- "bugs": {
36
- "url": "https://github.com/EricDisero/slates-mcp/issues"
37
- },
38
- "keywords": [
39
- "slates",
40
- "mcp",
41
- "model-context-protocol",
42
- "ai-video",
43
- "video-generation",
44
- "image-generation",
45
- "claude",
46
- "veo",
47
- "kling",
48
- "seedance"
49
- ],
50
- "engines": {
51
- "node": ">=18"
52
- },
53
- "dependencies": {
54
- "zod": "^3.23.0"
55
- },
56
- "devDependencies": {
57
- "typescript": "^5.7.0"
58
- }
59
- }
1
+ {
2
+ "name": "@slatesvideo/shared",
3
+ "version": "0.4.3",
4
+ "description": "Shared operations layer for the Slates MCP server and CLI: auth, cloud/desktop clients, and the single tool surface both consume. Most users want @slatesvideo/mcp-server or @slatesvideo/cli instead.",
5
+ "license": "MIT",
6
+ "type": "module",
7
+ "main": "./dist/index.js",
8
+ "types": "./dist/index.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "import": "./dist/index.js",
12
+ "types": "./dist/index.d.ts"
13
+ },
14
+ "./auth": "./dist/auth.js",
15
+ "./clients/cloud": "./dist/clients/cloud.js",
16
+ "./clients/desktop": "./dist/clients/desktop.js",
17
+ "./operations": "./dist/operations/index.js",
18
+ "./prompts": {
19
+ "import": "./dist/prompts/index.js",
20
+ "types": "./dist/prompts/index.d.ts"
21
+ }
22
+ },
23
+ "files": [
24
+ "dist",
25
+ "!dist/**/*.map",
26
+ "skills",
27
+ "README.md"
28
+ ],
29
+ "scripts": {
30
+ "build": "node scripts/embed-skills.mjs && tsc",
31
+ "typecheck": "node scripts/embed-skills.mjs && tsc --noEmit",
32
+ "prepublishOnly": "npm run build"
33
+ },
34
+ "repository": {
35
+ "type": "git",
36
+ "url": "git+https://github.com/EricDisero/slates-mcp.git",
37
+ "directory": "packages/shared"
38
+ },
39
+ "homepage": "https://slates.video",
40
+ "bugs": {
41
+ "url": "https://github.com/EricDisero/slates-mcp/issues"
42
+ },
43
+ "keywords": [
44
+ "slates",
45
+ "mcp",
46
+ "model-context-protocol",
47
+ "ai-video",
48
+ "video-generation",
49
+ "image-generation",
50
+ "claude",
51
+ "veo",
52
+ "kling",
53
+ "seedance"
54
+ ],
55
+ "engines": {
56
+ "node": ">=18"
57
+ },
58
+ "dependencies": {
59
+ "zod": "^3.23.0"
60
+ },
61
+ "devDependencies": {
62
+ "typescript": "^5.7.0"
63
+ }
64
+ }
@@ -41,10 +41,10 @@ If text only: skip step 2's reference and generate the turnaround from prompt-on
41
41
  - On success bind via `slates_set_character_expression_asset`.
42
42
 
43
43
  ### 5. Hand back
44
- > "Character {name} ready. Turnaround + expressions bound. Use `@{name}` in any prompt — Slates attaches both sheets and labels them so the face stays consistent."
44
+ > "Character {name} ready. Turnaround + expressions bound. Use `@{name}` in any prompt — Slates attaches both sheets and names them as one person so the face stays consistent."
45
45
 
46
46
  ## Why both sheets (don't gate them)
47
- At scene time Slates attaches the turnaround AND the expression sheet, and writes a reference label that says: use these for the character's identity (face, skin, bone structure, body, outfit) and render the expression the SCENE describes, default neutral. That LABEL not withholding the expression sheet is what stops the multiple expressions from averaging the face to a midpoint. The close-ups carry far more facial signal (eyes, teeth, skin) than the postage-stamp faces in a full-body turnaround, so attaching both is a fidelity win. The trend is MORE references (video/audio/3D into newer models), so lean into attaching rich refs and labeling every role.
47
+ At scene time Slates attaches the turnaround AND the expression sheet and cites BOTH inline under the same name `{name} (images N and M)`. That shared NAME — not a withheld expression sheet, and not an injected "use for identity / render neutral" essayis what tells the model they're ONE person and stops the multiple expressions from averaging the face to a midpoint. (Naming-as-one-entity is each model's own official lever: NB2 "assign a distinct name", Seedance "Reference Subject_N in Image_N".) The close-ups carry far more facial signal (eyes, teeth, skin) than the postage-stamp faces in a full-body turnaround, so attaching both is a fidelity win. Critically, the app injects NO wardrobe/expression/lighting directive — the user's scene prompt owns all of that, so `@{name}` in a movie-still injection keeps the still's own clothing and lighting. The trend is MORE references (video/audio/3D into newer models), all addressed by name — lean into attaching rich refs and let the naming do the work.
48
48
 
49
49
  ## Anti-patterns
50
50
 
@@ -0,0 +1,55 @@
1
+ ---
2
+ name: slates-content-policy
3
+ description: Content-policy-safe construction — build any scene safe from the first word so it hits full cinematic impact without depicting prohibited content (and without getting silently rejected or degraded by the model's filter). Read this before writing any prompt that involves conflict, creatures, crowds, destruction, weapons, or young characters. Mirror of @slatesvideo/shared/prompts content-policy fragment — SSOT: second-brain business/projects/slates/product/prompting-ssot.md.
4
+ ---
5
+
6
+ # Content-policy-safe construction — read before any risk-surface prompt
7
+
8
+ Don't depict the harm — depict the energy, the aftermath, the threat, or the scale. Build the scene safe from the first word.
9
+
10
+ Write scenes that hit full cinematic impact without ever *needing* to depict prohibited content. This is a craft move, not a compromise — the substitutions below usually read as more cinematic, not less, and they keep your generation from getting silently rejected or degraded by the model's filter. A standoff is more tense than a massacre; an evacuated city is eerier than a crowd in panic; a roar lands harder than a kill. Load this whenever a prompt involves conflict, creatures, crowds, destruction, weapons, or young characters.
11
+
12
+ ## Substitution table
13
+
14
+ | Avoid | Use instead |
15
+ |---|---|
16
+ | Civilians in panic, crowds fleeing under debris | An evacuated / empty city; abandoned streets; a lone figure for scale |
17
+ | Weapons firing into buildings or at people | Energy-discharge standoffs, searchlights sweeping, charged auras, shockwaves with no muzzle fire |
18
+ | Creatures tearing into each other, gore | A grapple / standoff — roars, near-misses, circling, an energy clash; combat that stays contained (in/on the water, never lifting into the air) |
19
+ | Destruction with people in harm's way | Destruction in uninhabited terrain — glaciers, deserts, ruins, open sea, evacuated zones |
20
+ | Realistic guns as the focus | Stylized / fantasy implements, weapons slung-not-fired, the weapon as silhouette or prop only |
21
+ | Blood, wounds, death | Impact light, dust, debris, buckling and collapse, a silhouette dropping out of frame |
22
+ | Real, named public figures | Original / anonymous characters |
23
+ | Real brand logos | Original or generalized branding — except the user's own product, which is the whole point of a brand film |
24
+
25
+ ## The safe benchmark
26
+
27
+ When a scene starts drifting risky, pull it back toward this shape: **one original creature, in a generalized monument or amphitheatre, in daylight, no weapons present, performing expressive action** (rising, roaring, spreading wings). Original design, generalized location, daylight, expressive rather than violent. That's the confirmed-safe envelope — most epic ideas re-stage into it without losing the punch.
28
+
29
+ ## Containment rule — it doubles as a physics win
30
+
31
+ Give any creature or combat scene a **containment rule** that grounds the physics at the same time:
32
+ - "the fight STAYS at the sea surface — they breach, dive, grapple, submerge, but never fly or get carried into the air"
33
+ - "boss scale locked ~2.5 human-heights, NOT kaiju-giant"
34
+ - "destruction stays in the evacuated valley"
35
+
36
+ This improves coherence (the model isn't inventing absurd escalation) AND keeps the scene inside policy — same clause buys both.
37
+
38
+ ## Scale and stakes without harm
39
+
40
+ Epic stakes come from environmental danger and reaction, not depicted victims: tiny figures diving clear of *collapsing* terrain (not being crushed), a war-horn over an *empty* field, an army *scrambling* across a frozen valley as a titan tears free of a glacier. The danger is the environment; the figures are reacting, not dying. Snow plumes, glowing runes, splintering ice, shockwaves, and dust carry the chaos.
41
+
42
+ ## Minors — hard rule
43
+
44
+ Never write romantic, sexual, or suggestive content involving or directed at minors, and never anything that sexualizes a young-presenting character. Any scene with children stays wholesome and age-appropriate. Non-negotiable — it overrides every stylistic goal.
45
+
46
+ ## Pre-flight (run before delivering any risk-surface prompt)
47
+
48
+ - [ ] No civilians depicted in panic/harm; crowds are evacuated or absent.
49
+ - [ ] No weapons firing at people/buildings; threat is energy / searchlight / silhouette.
50
+ - [ ] No creature-on-creature or creature-on-person gore; combat is grapple / standoff / roar, contained.
51
+ - [ ] Destruction is in uninhabited / evacuated terrain.
52
+ - [ ] Creatures are original ("not based on any franchise"); no real public figures; no real brand logos except the user's own product.
53
+ - [ ] Anything with children is wholesome and age-appropriate.
54
+
55
+ If a box fails, apply the substitution table before writing the prompt.
@@ -91,6 +91,14 @@ The server returns `requires_clarification` when aspect ratio or resolution is m
91
91
 
92
92
  Don't bypass the gate by silently filling in defaults. The gates exist because defaults waste money.
93
93
 
94
+ ## Video is slow + async — a timeout is NOT a failure
95
+
96
+ Video gens take minutes (Seedance 4K can run far longer). A client/CLI timeout or a slow, empty-looking response is **not** a failed generation — the job is still running on the provider.
97
+
98
+ - **Never re-submit a video gen because it "timed out."** That double-charges the user for one video. Re-rolling a slow gen is the single most expensive mistake here.
99
+ - **Poll, don't re-roll.** Use `background: true` on `slates_generate_video`, then poll `slates_get_generation_status` (free, read-only) until it reports `completed` or `failed`. In-flight jobs survive app restarts and are recovered.
100
+ - A gen has only failed when the status comes back `failed` — and a provider *rejection* **refunds** the credits, so failed isolation tests are ~free. Until you see a terminal status, the job is in flight. Wait.
101
+
94
102
  ## The 3-strike rule
95
103
 
96
104
  Stop after 3 iterations on the same prompt. Hand back to the user with what you tried and what's not working. The slot machine doesn't converge — if it's not landing, the prompt structure is wrong, not the seed.
@@ -30,7 +30,7 @@ Price the whole batch before the first generation: frame images (count × model
30
30
  Per `slates-cost-discipline` 3b: that single OK authorizes `confirm=true` for **every enumerated call in the batch** — no per-call re-asking. Re-confirm only if a call's price overruns the plan >25% or new calls get added (extra retakes, new shots).
31
31
 
32
32
  ### 5. Generate frame images
33
- Per shot: `slates_generate_image` with `referenceAssetIds` pointing at the character turnaround / environment / prior frames for consistency (label each reference's role in the prompt). Evaluate every result inline against the beat. Bind keepers via `slates_add_frame`.
33
+ Per shot: `slates_generate_image` with `referenceAssetIds` pointing at the character turnaround / environment / prior frames for consistency (Slates names each reference inline as "image N" — you don't hand-write role labels; reuse the same subject name across shots). Evaluate every result inline against the beat. Bind keepers via `slates_add_frame`.
34
34
 
35
35
  **Multi-take where it matters:** for the hook shot and any shot the whole film hangs on, generate 2-4 variants (cheap model or 1k), pull them back with `slates_get_assets_batch`, pick the strongest on composition + identity, discard the rest. Don't multi-take filler shots.
36
36
 
@@ -0,0 +1,22 @@
1
+ ---
2
+ name: slates-project-organization
3
+ description: How to keep a Slates project's assets organized — folders for film STRUCTURE, the typed tabs for reusable references — so the user and the agent can both navigate it and a human can take over the project manually.
4
+ ---
5
+
6
+ # Organizing a Slates project
7
+
8
+ Slates already gives each REUSABLE reference type its own home — the **Characters**, **Environments**, and **Styles** tabs, each with its own generation + `@mention`/`#ref` behavior. Do NOT recreate those as folders. Folders are for **structure**, never type.
9
+
10
+ **Folders = where an asset sits in the FILM**, and they mirror to real subfolders on disk (`projects/<id>/…`), so a human can open the project in Resolve/Finder and navigate it like an edit. Use them for work product, not references.
11
+
12
+ Create with `slates_create_folder`; file assets with `slates_move_assets_to_folder`. Generations land in the project's active folder, so set it before a batch.
13
+
14
+ Conventions by project type:
15
+ - **Short film / narrative:** `Shots` (scene stills) · `Clips` (generated video) · `Final` (the export). Use one folder per scene (`Scene 1`, `Scene 2`, …) instead when the piece has distinct locations/beats.
16
+ - **Ad / UGC:** `Hooks` · `B-roll` · `Talking-head` · `Final`.
17
+
18
+ Rules of thumb:
19
+ - Reusable cast / sets / look → leave in the Characters/Environments/Styles tabs. Don't fold them.
20
+ - Scene stills, clips, and the final cut → file into the structural folder they belong to, as you make them.
21
+ - One folder per asset (folders are structure). Cross-cutting status (hero take, reject, variant) is a tag concern, not a folder.
22
+ - Keep the gallery legible: work product lives in folders; the reference scaffolding (sheets, plates, style images) stays in its tabs.
@@ -80,12 +80,12 @@ Use natural language for exploration, JSON when the layout is locked and you're
80
80
 
81
81
  ## Reference images (edit path)
82
82
 
83
- In Slates, pass `referenceAssetIds` on `slates_generate_image` — FLUX routes them through its edit endpoint. Label every reference's role in the prompt text ("subject from image 1, style from image 2, background from image 3"); unlabeled references get blended unpredictably. For surgical changes to one existing image use `slates_edit_image` with `editModel: flux-2-max` (note: FLUX edits ignore extra referenceAssetIds — that's NB2-only).
83
+ In Slates, pass `referenceAssetIds` on `slates_generate_image` — FLUX routes them through its edit endpoint. Slates names each reference inline in the prompt ("the subject (image 1), the style (image 2)") in the order it sends them, so you don't hand-write role labels; the name carries the role and unnamed-by-position blending is avoided. For surgical changes to one existing image use `slates_edit_image` with `editModel: flux-2-max` (note: FLUX edits ignore extra referenceAssetIds — that's NB2-only).
84
84
 
85
85
  Reference discipline (FLUX caps refs lower than NB2's 14, so be deliberate):
86
- - **2-4 strong refs**, one per role, labeled — not 1 (warps), not many (blends).
86
+ - **2-4 strong refs**, one per role, named — not 1 (warps), not many (blends).
87
87
  - **Flat-lit identity refs** — a studio-lit / scene-lit character sheet bleeds its lighting into the output.
88
- - **Attach both character sheets, labeled for identity** — turnaround (body/proportion/outfit) + close-up expression sheet (face detail), rendering the scene's expression (default neutral); the label keeps the expressions from averaging the face.
88
+ - **Attach both character sheets, named as one entity** — turnaround (body/proportion/outfit) + close-up expression sheet (face detail), cited under the same name; the shared name keeps the expressions from averaging the face. Don't write a role essay or "render neutral" instruction — the user's prompt owns the expression, wardrobe, and lighting.
89
89
  - **Environment: describe it, don't feed a multi-panel grid** — reserve a ref for a hard exact-match, then use ONE clean establishing image.
90
90
 
91
91
  ## Character consistency across a series
@@ -99,7 +99,7 @@ Define the character exhaustively once, then repeat those exact descriptors verb
99
99
  | Generic "AI look" on photoreal | Name a camera body + lens + f-stop instead of "professional photo" |
100
100
  | Colors drift from brand spec | Bind each hex code to a named object |
101
101
  | Text garbled | Quote the exact string, specify font feel + placement + size |
102
- | Multi-reference blend chaos | Label each reference's role explicitly in the prompt |
102
+ | Multi-reference blend chaos | Name each reference inline (Slates does this from your @mentions/referenceAssetIds) — the same name for one entity, distinct names per role |
103
103
  | Wanted element missing | Move it earlier in the prompt — order is weight |
104
104
 
105
105
  ## Pre-flight: references arrive inline, refer by code
@@ -106,9 +106,9 @@ Upload 2-4 multi-angle reference photos per character/object. Tag inline:
106
106
 
107
107
  ## Reference discipline (character / environment refs)
108
108
 
109
- - **2-4 strong refs per role**, labeled (which element is which) and reused across every shot — swapping mid-sequence drifts.
109
+ - **2-4 strong refs per role**, named (the same fixed label reused verbatim) and reused across every shot — swapping mid-sequence drifts. Kling's consistency lever is **"lock the subject with a fixed label reused verbatim"** (pronoun/synonym drift breaks it), so reusing the exact name on every mention is the whole game. Slates composes this for you from `@mentions`.
110
110
  - **Flat-lit identity refs.** A studio-lit / scene-lit character sheet bleeds its lighting into the clip. Prep refs flat and plain.
111
- - **Attach both character sheets, labeled for identity** — the turnaround (body/proportion/outfit) and the close-up expression sheet (face detail). Render the scene's expression (default neutral); the label keeps the varied expressions from averaging the face.
111
+ - **Attach both character sheets, named as one entity** — the turnaround (body/proportion/outfit) and the close-up expression sheet (face detail), cited under the same name. The shared name keeps the varied expressions from averaging the face; don't write a role essay or tell it to "render neutral" — the user's prompt owns the expression, wardrobe, and lighting.
112
112
  - **Environment: describe it, don't feed a multi-panel grid.** Reserve an environment ref for a hard exact-match, then use ONE clean establishing image.
113
113
 
114
114
  ## Negative prompting — has a real field
@@ -96,27 +96,19 @@ Default to #1. Reach for #2 only when positive framing can't suppress the unwant
96
96
  ## Reference images
97
97
 
98
98
  - **Hard limit: 14 images** (10 object-fidelity + 4 character-consistency). Categories don't trade — you can't use 14 object slots even if no characters are referenced.
99
- - **Always label every reference's role** in the prompt. The model does not infer roles from order. Use the Slates composition pattern:
100
-
101
- ```
102
- Reference Image Instructions:
103
- - Image 1: Character reference (@samurai) — use for the character's identity (facial features, skin, bone structure, body, outfit); render the expression the scene describes, default neutral
104
- - Image 2: Environment reference (@temple) — use for location architecture, spatial layout, environmental lighting, and atmospheric qualities
105
- - Image 3: Style reference (#kurosawa) — use for visual style, mood, and aesthetic treatment
106
-
107
- Scene prompt: [actual prompt]
108
- ```
99
+ - **Name each reference inline Slates does this for you.** When you `@mention` a subject/environment or `#mention` a style (or pass `referenceAssetIds`), Slates composes the prompt so each reference is named inline as "image N" — e.g. `Marcus (images 1 and 2) sits across from the woman (images 3 and 4) in the cafe (image 5)`, with a trailing `Render in the visual style of image 6.` The model does NOT infer a reference's role from its position; the NAME carries it. NB2's own consistency lever is literally **"assign a distinct name to each character/object"**, so citing both of a subject's sheets under the SAME name ("Marcus") is what tells the model they are ONE person and stops the face averaging. **Do NOT hand-write a "Reference Image Instructions" block or role essays** ("use for identity, ignore the outfit, render the scene's expression") — that drags the sheet's wardrobe + studio lighting into the scene. The prompt leads; the user's words own wardrobe, expression, lighting, and action.
109
100
 
110
101
  ### Reference rules (the verified ones)
111
102
  1. **2-4 strong refs beat both extremes.** Not 1 (warps toward itself), not 12 (averages worse). Start with 2-3 focused refs — each adds context AND variables to balance.
112
- 2. **One reference per ROLE, labeled** (identity / style-grade / environment). Same-role competitors drift.
113
- 3. **Identity refs: attach both sheets, labeled — don't gate them.** A character's turnaround (body/proportion/outfit) AND its close-up expression sheet (high-res face: eyes, skin, teeth) both go in. The label ("use for identity; render the scene's expression, default neutral") is what stops the varied expressions from averaging the face. An *unlabeled* expression sheet hurts; labeled, the close-ups are a fidelity win.
103
+ 2. **One reference per ROLE, named** (identity / style-grade / environment). Same-role competitors drift. The model doesn't infer roles from order — the inline name does it.
104
+ 3. **Identity refs: attach both sheets, named as one entity — don't gate them.** A character's turnaround (body/proportion/outfit) AND its close-up expression sheet (high-res face: eyes, skin, teeth) both go in, cited under the SAME name ("Marcus (images 1 and 2)"). That shared name not a role essay — is what stops the varied expressions from averaging the face. An *unnamed* expression sheet hurts; named as one entity, the close-ups are a fidelity win.
114
105
  4. **Flat-light identity refs.** Prep them with flat, even, shadowless lighting on a plain neutral background. Studio-lit / scene-lit sheets bleed their lighting into the generation ("green-screen pasted in front of mountains").
115
106
  5. **Environment: describe it, don't feed a grid.** Default to describing the location in words. Reserve an environment ref for a mandatory exact-match, and then use ONE clean establishing image — never a multi-panel grid fed whole.
116
107
  6. **Grids: explore, don't input.** Use grids to explore compositions, then pick a cell. Never feed a grid back in as a reference — cells share a split detail budget, so flaws propagate.
117
108
  7. **Reuse the same refs across all shots.** Swapping mid-sequence causes drift.
118
109
  8. **Legible in-shot text → bake it into the NB2 start frame**, then animate from it. Never trust text-to-video to render clean text.
119
110
  - **Character consistency is officially "not 100% perfect"** per Google. Test before bulk generations. High-resolution, front-facing reference images help most.
111
+ - **Injection is stochastic — budget 3-5 re-rolls per shot; re-roll, don't re-engineer.** First rolls miss faces/hands; the same prompt lands a clean one within a few tries.
120
112
 
121
113
  ## Common failure modes + fixes
122
114
 
@@ -1,11 +1,11 @@
1
1
  ---
2
2
  name: slates-prompting-seedance
3
- description: How to prompt Seedance 2.0 (ByteDance video model). Read before calling slates_generate_video with model seedance-2-fast or seedance-2-std. Seedance prompts have very specific structure (6-step formula + narrative timing beats) that differs from Kling and Veo — don't cross-pollinate the syntax.
3
+ description: How to prompt Seedance 2.0 (ByteDance video model). Read before calling slates_generate_video with model seedance-2. Seedance prompts have very specific structure (6-step formula + narrative timing beats) that differs from Kling and Veo — don't cross-pollinate the syntax.
4
4
  ---
5
5
 
6
6
  # Seedance 2.0 — prompting
7
7
 
8
- ByteDance's video model. Routed via PiAPI (Economy) or fal.ai (Priority). Audio always generated alongside video. Models: `seedance-2-fast` (cheaper) and `seedance-2-std` (higher quality). Up to 15s.
8
+ ByteDance's video model first-party via **BytePlus ModelArk** (credits only, no BYOK). Audio always generated alongside the video. Single model `seedance-2` across the full resolution ladder (480p / 720p / 1080p / native 4K, default 1080p), 4–15s, first+last frame + up to 9 reference images.
9
9
 
10
10
  ## Official 6-step formula
11
11
 
@@ -83,11 +83,24 @@ Reference-to-video endpoint accepts up to **9 reference images, 3 reference vide
83
83
 
84
84
  **Mutually exclusive:** First-frame/last-frame mode CANNOT be combined with reference images. The error reads `"first/last frame content cannot be mixed with reference media content."` Pick one or the other.
85
85
 
86
+ ## Faces — set `seedanceFace` for AI-character faces
87
+
88
+ Seedance routes through **two providers** depending on whether a reference shows a **face**, and the app exposes this as the "Face in Reference" toggle (param `seedanceFace` on `slates_generate_video`):
89
+
90
+ - **Faceless / object / environment refs → default route (cheapest).** Leave `seedanceFace` off.
91
+ - **An AI-character's FACE in a reference → `seedanceFace: true`.** The default (BytePlus) route's baseline moderation rejects or degrades faces, so this reroutes to the face-capable provider (relaxed mode). It costs **~10% more** — the cost key becomes `seedance-2-face-{res}-{N}s`, so the pre-flight quote already reflects it. Announce the face-route price, not the faceless one.
92
+
93
+ Rules:
94
+ - **AI-generated characters only.** Real people (yourself, an actor, a photo of a real person) are **walled on every route** — ByteDance's Feb-2026 real-person policy. Never promise "upload a real face and animate it"; it will be rejected. The toggle is for fictional/AI characters.
95
+ - It's about the **reference, not the output.** If your character refs (turnaround, expression sheet, a generated portrait) show a face, turn it on. A product shot with no person stays off.
96
+ - Don't toggle it on "just in case" — a faceless gen on the face route just burns the +10% for nothing.
97
+
86
98
  ## Reference rules (the verified ones)
87
99
 
100
+ - **Describe the ACTION, never the reference's content.** With refs attached, prompt only what is *happening* — motion, change, camera. Never re-describe what's in the reference, and never say "still / scene / from a movie / from the image." The model already sees the refs; narrating them wastes tokens and induces drift. Injection is stochastic — if a roll misses, **re-roll, don't re-engineer** (and a slow gen is not a failed one — see slates-cost-discipline).
88
101
  - **2-4 strong refs beat both extremes** — not 1 (warps), not 12 (averages worse). Start focused.
89
- - **One reference per ROLE, labeled** `@Image1 is the character`, `@Image2 is the environment`. The model needs to know what each ref is FOR; it doesn't infer roles from order.
90
- - **Character identity: attach the turnaround AND the close-up expression sheet, labeled for identity** (face/skin/body/outfit), and render the expression the SCENE describes (default neutral). That label is what keeps the varied expressions from averaging the face don't gate the expression sheet. The trend is MORE references (video/audio into Seedance), so lean into attaching rich refs and labeling every role.
102
+ - **One reference per ROLE, named in the prompt.** Seedance's official idiom is **"Reference \<Subject_N\> in \<Image_N\>"** — `Image_N` indexes the order the refs are attached, so the name + index carries the role; the model doesn't infer it from order alone. Slates composes this for you from `@mentions`: it cites each reference inline as "image N" in the exact order it sends them. You don't hand-write role labels.
103
+ - **Character identity: attach the turnaround AND the close-up expression sheet, named as one entity** cite both under the same name. The shared name not a role essay — is what keeps the varied expressions from averaging the face; don't gate the expression sheet, and don't tell it to "render neutral / ignore the outfit" (the user's prompt owns expression, wardrobe, and lighting). The trend is MORE references (video/audio into Seedance), all addressed by name — lean into attaching rich refs and let the naming do the work.
91
104
  - **Flat-lit identity refs.** A studio-lit / scene-lit character sheet bleeds its lighting into the clip ("green-screen pasted in front of mountains"). Prep refs flat and plain.
92
105
  - **Environment: describe it, don't feed a grid.** Default to words and let the model build the space to fit; reserve an environment ref for a hard exact-match, and then use ONE clean establishing image — never a multi-panel grid.
93
106
  - **Reuse the same refs across every shot** in a sequence — swapping mid-sequence drifts.
@@ -98,9 +98,9 @@ Verbatim example:
98
98
 
99
99
  ## Reference discipline (character / environment refs)
100
100
 
101
- - **2-4 strong refs per role**, labeled (name what each provided image is for) and reused across every shot.
101
+ - **2-4 strong refs per role**, named inline (Slates cites each as "image N" from your `@mentions`) and reused across every shot. The model doesn't infer a ref's role from order — the name does it.
102
102
  - **Flat-lit identity refs.** A studio-lit / scene-lit character sheet bleeds its lighting into the clip. Prep refs flat and plain.
103
- - **Attach both character sheets, labeled for identity** — the turnaround (body/proportion/outfit) and the close-up expression sheet (face detail). Render the scene's expression (default neutral); the label keeps the varied expressions from averaging the face.
103
+ - **Attach both character sheets, named as one entity** — the turnaround (body/proportion/outfit) and the close-up expression sheet (face detail), cited under the same name. The shared name keeps the varied expressions from averaging the face; don't write a role essay or "render neutral" instruction — the user's prompt owns the expression, wardrobe, and lighting.
104
104
  - **Environment: describe it, don't feed a multi-panel grid.** Reserve an environment ref for a hard exact-match, then use ONE clean establishing image.
105
105
 
106
106
  ## Negative prompting — nouns, not instructions