---
name: persistence
description: >-
  Character persistence for Seedance. Turns ONE character image into a style-locked character sheet by way of video, so the character holds across every later generation. Writes two coverage clip prompts (Five-View Turnaround + Expression Sheet, locked static shots on neutral grey, hard cuts, no camera movement), then a bundled ffmpeg script finds the real cuts, pulls one frame per view, and builds a 1080x1440 four-quadrant sheet. Delivery is English only and headerless, with no Chinese twin, no UPLOAD MAP, no rig echo, no title line, because headers confuse Seedance on Venice. Use whenever the user says "persistence", "persistence pass", "lock this character", "character sheet from this image", "turnaround clip", "expression sheet", "pull frames for refs", or wants a Seedance generation for harvesting references rather than a shot. Overrides the host prompters' delivery rules. Clips are frame sources only, never video references.
---

# Persistence

Put the character in front of the camera before the shoot. Neutral background, still, turn, emote. The clip never goes in the edit. Its frames become the character sheet, and the sheet is what holds the character steady for the next hundred generations.

## DELIVERY CONTRACT (read first, this is what makes Persistence different)

Persistence writes its own prompts and owns its own delivery. The host Seedance prompters (seedance-prompter-v3, seedance-prompter-25, encode-script) have standing rules that do NOT apply here. When Persistence fires, these rules win, even if the brief carries a `PROMPTER:` line. A `PROMPTER:` line only picks the body format (YAML for 2.0, bracketed prose for 2.5).

1. **English only.** No Chinese translation block, no bilingual fields, no call to a translator skill. Every character inside the fence is English. The only non-word tokens allowed are the reference token and timestamps.
2. **No header.** Nothing sits above the first prompt field. No UPLOAD MAP, no rig echo, no "Clip A" label, no `title:` field, no comment lines, no dividers. The fence opens on `reference_handling:` (YAML) or `[Global Setting]` (2.5 prose) and closes on the last field. Venice passes the whole pasted text to Seedance, so any header text gets read as scene content.
3. **One fence per clip, and the prompt fence is the last fence in its message.** Deliver Clip A alone first. Clip B is written after Clip A has been generated and harvested (it runs from a pulled face frame), in its own message.
4. **Attach instruction goes outside the fence, as one plain sentence** above it in chat: which single file to attach. Never formatted as a map, never with arrows, never inside the fence.
5. **No dialogue section, no four suggestions, no scene breakdown.** After the fence, at most two plain sentences: what a good result looks like, and "tell me when the clip is in."
6. **Reference token:** `@image1` by default (lowercase, no space; the Night Shift deck translates it for Venice). If the user says they are pasting straight into Venice's own UI, write `<Image 1>` instead. One reference image per clip, so there is never an `@image2`.
7. **Length:** keep each prompt under 6,000 characters. Check with `wc -c` when in doubt.

Self-check before sending: is the first line inside the fence a prompt field? Is there any non-English text anywhere in the message? Is there exactly one fence? If any answer is wrong, fix it before delivering.

## WHY VIDEO, NOT AN IMAGE MODEL

- Image edit models re-render. They read the character, then repaint it in their own color science, line quality, and lighting habits. Grain, texture, and the specific weirdness of the source go first.
- Seedance image-to-video continues. Frame one is the image; every following frame inherits its pixels. A pulled frame is the same character, new angle, same feel, already tuned to how the video model renders, so scene generations that reference it hold style with little fight.
- Cost: two 15-second clips per character, generated once, reused across every scene, series, and sequel.

## THE TWO CLIPS

Both: **Seedance reference-to-video, 15s, 3:4, 720p, one reference image, audio on but near-silent.** 3:4 matches the sheet.

### CLIP A: FIVE-VIEW TURNAROUND

Skeleton (YAML form; fill every quoted value, drop bracketed blocks that do not apply):

```
reference_handling: ""
style: ""
visual_feel: ""
duration: "15s"
character_modeling:
  <name>:
    base: ""
    features: ""
    signature_prop: ""
    pose_in_this_scene: ""
    [scale_logic]: ""
    [color_anchor]: ""
    [proportion_logic]: ""
cinematic_storyboard:
  "0-3s": ""
  "3-6s": ""
  "6-9s": ""
  "9-12s": ""
  "12-15s": ""
lighting: ""
production_notes:
  audio: ""
  motion_register: ""
  critical_constraint: ""
  avoid: ""
```

What each field must carry:

- **reference_handling**: the base image is the identity AND style anchor. Keep the design and its exact rendering, and name the render qualities (line, highlight behavior, palette, grain). Change ONLY three things: the pose (calm standing model-sheet views instead of the base image's pose), the background (strip the base environment, replace with a neutral seamless grey studio), and the framing per view. End with "All staging is decided by the storyboard."
- **style**: saturated with the aesthetic, and restated in visual_feel and production_notes. A cue stated once drifts. Put "flat character on neutral seamless grey studio background" inside the style line itself.
- **visual_feel**: calm, still, fully displayed, a model sheet; even readable light; hard cuts, no dissolves.
- **pose_in_this_scene**: calm standing, near-still, only micro-motion (breathing, cloth drift, one thin smoke wisp). "No combat. Character and gear identical across all five shots. Only the viewpoint changes."
- **scale_logic** (only for a deliberately outsized prop): size stated relative to the body ("its pommel clears the top of his head by a full head"), framing that keeps prop and body fully in frame, a fail test ("if it reads as a normal two-hander that fits inside his silhouette, the shot is wrong"), and a "not:" clause. Without this, oversized props shrink to human scale.
- **color_anchor** (strongly colored skin or costume): name the true color and say "render it as-is on neutral grey; do not lighten, grey out, or desaturate." Grey studios pull saturated bodies toward grey.
- **proportion_logic** (base image crops the body): design the missing part ("the reference shows no legs; long legs in proportion to the torso, standing").
- **cinematic_storyboard**, five blocks, each stated as "locked, static" with a hard cut between:
  1. 0-3s: full-body FRONT, eye level, whole figure and whole prop in frame with margin.
  2. 3-6s: full-body SIDE, a clean 90-degree profile.
  3. 6-9s: full-body BACK.
  4. 9-12s: tight FACE close-up, head and shoulders, face lifted to camera (for a prop-defined character, the prop-scale shot).
  5. 12-15s: DETAIL close-up of the one element that must never drift (mech arm, crest, hands, headdress), clean end frame.
- **lighting**: even frontal key, soft fill, faint cool rim on grey; the side view lets the key rake across for highlight behavior.
- **audio**: no music, minimal room tone, one soft breath. "This is a test, keep it quiet."
- **motion_register**: calm, near-still, no interpolation smoothing. ANY camera movement forbidden (no push, orbit, pan, tilt, zoom). No dissolves.
- **critical_constraint**: exact render of the base preserved, neutral grey, five locked views joined by hard cuts, identical character across cuts.
- **avoid**: camera movement, dissolves, the base image's environment, dramatic hero angles, combat, motion blur, photoreal/CGI/3D/smooth interpolation (when the base is 2D), jitter, warped limbs, flicker, identity drift between cuts, extra limbs, set dressing, on-screen text, captions, subtitles, watermarks.

For Seedance 2.5 bracketed prose, carry the same content under `[Global Setting]`, `[Character Styling]`, `[Timestamp Storyboard]`. The fence opens on `[Global Setting]`.

### CLIP B: EXPRESSION SHEET

Run from a **pulled face frame of Clip A**, not the base image. It is already the target texture, so the prompt says "match its rendering exactly." Same skeleton as Clip A with these changes:

- Framing locked for all five cuts: tight frontal head-and-shoulders close-up, identical framing and identical even key every cut.
- **Identity marks pinned by name** (a scar, a mark, an ornament): "must appear in every shot, same position, shape, and size; never fades, moves, shrinks, or disappears." Unpinned marks vanish by cut three.
- Five emotions pushed to their extreme, each with a read line saying what it is and what it is NOT ("pure warm joy, not smugness, not a sneer"). Typical set: joy, anger, grief, laughter, and the character's peak state. Only the expression changes.
- Micro-motion inside each hold only (breath, brow twitch, hair drift, a tear). No head turns. No camera movement.
- Audio: one matching wordless vocalization per hold (exhale, growl, shaky breath, laugh, roar) under room tone. No music, no spoken words.

## THE HARVEST (Claude does this; the user never runs anything)

The user's whole job after generating is to say the clip is done or drop the file. Claude runs the bundled tool, checks the result, and shows the sheet. Never hand the user a command. The sheet is the deliverable; the script is plumbing.

Tool: `scripts/persistence.py` in this skill folder (ffmpeg + ffprobe on PATH; Python stdlib only).

```
python3 <skill-dir>/scripts/persistence.py auto "<clip.mp4>" --out "<images folder>" --name <character>
```

That detects the real cuts, pulls one frame per view, writes `<character>_view<N>_f<frame>.png` for all five views plus `<Character> Character Sheet.png` (1080x1440). Claude then opens the sheet, looks at it, and presents it.

**QA before showing it, every time:**

- Four DIFFERENT views on the sheet? Default fill is views 1,3,4,5 = front, back, face, detail (TL, TR, BL, BR; `--pick` changes it). If two quadrants show the same view, do not show the bad sheet. Run `contact` (12 thumbnails per segment, frame numbers printed), pick a distinct clean frame per view, then `pull --frames n1,n2,n3,n4,n5` and `sheet a b c d --out ...`. Involve the user only if a view does not exist in the clip; then name it and offer a re-gen of that view.
- Frames sharp, on-model, no cut-transition smear? If a frame sits on a transition, re-pick from `contact`.
- Any burned-in text or captions in a frame? Re-pick, and if every frame has it, re-gen.
- The sheet lands in the project's images folder under the character's name. The five loose views stay beside it (the side view is a reference even though it is not on the four-up).

Expression clips get a second sheet the same way, from any four of the five holds.

How the tool finds cuts: the model does not honor the 3-second grid (real cuts have measured at 2.9s, 4.7s, 6.4s, 12.7s), so the tool ranks per-frame scene scores and takes the biggest jumps with a one-second minimum spacing. `--grid` forces the fixed grid. `pull --frames` overrides everything. Sheet spec: 1080x1440 canvas, four 534x714 quadrants, 12px black cross gutter, no outer border, stills cover-fit.

**No shell available:** write the clip prompts, then tell the user once, plainly, which frames to freeze (front, back, face, detail) and that a 2x2 grid at 1080x1440 with a thin black gutter in any image editor is the sheet.

## USING THE SHEET

- The sheet becomes the character's identity reference. Attach it in every scene prompt that features the character, described in that prompt as "character sheet = identity, not composition." Frame-one composition comes from a continuity frame or the storyboard, never from the sheet.
- Multi-panel sheets read as one reference. Say so in the scene prompt ("a multi-panel model sheet, take identity from all panels, copy none of the framings").
- Re-run Persistence when the character changes state (wounded, costume change). Each state gets its own sheet.

Scene prompts that use the sheet are written by the host prompter under the host's own delivery rules. Persistence's English-only, headerless contract covers only the two coverage clips it writes.

## CORRECTIONS THAT MADE THIS RECIPE (keep them; they are why it works)

1. A slow turnaround with a head-turn drifted; five locked static views with hard cuts did not. Motion is the enemy of a harvest.
2. An outsized prop rendered human-sized until a scale_logic block with a fail test was added.
3. Saturated red skin went grey on the grey studio until a color anchor line named the true color.
4. A base image with no legs produced guesswork until proportion_logic designed the missing body.
5. Facial identity marks vanished across cuts until pinned by name in every shot.
6. Frames pulled from a coverage clip beat the base image as the reference for the expression pass, because they are already in the video model's texture.
7. Header lines and a Chinese twin pasted with the prompt confused Seedance on Venice. The prompt now ships English only, opening on its first field.
