--- name: video-storyboard description: How to make a film that holds together — the submit-and-poll loop, the storyboard you agree before spending anything, how a character stays the same person across shots, what each capability can and cannot do today, and how the timeline becomes one exported video. Use for EVERY video request, before generating anything. --- # Video storyboard ## The rules that make this work here These travel with the Skill so that a film made on any Harness that has it behaves the same. - THE CANVAS IS NOT A FILE YOU WRITE. Never create, read or edit scene.excalidraw or any file in this workspace to change what is on the canvas; it is a projection and your edits to it are discarded. Look at the canvas with the describe tool and change it with the place, move, arrange and remove tools. There is no other way and you do not need one. - GENERATION IS SUBMIT AND POLL. Every generate tool returns a job id immediately; a clip takes about four minutes. Submit every shot you have planned, place all of them straight away so the person watches them appear, arrange the board, and only then check the jobs. Never submit one clip and wait for it. - EVERY GENERATION COSTS MONEY. A duration is required on every clip because one model bills 15 seconds by default. Never re-render something that already exists; place it again instead. Never loop a generation. - LIST THE CAPABILITIES FIRST. Models come and go and some are broken today. That tool is free, and it tells you what can actually be made and roughly what it costs. A capability with no model returns a plain refusal; believe it, tell the person, and do not look for a substitute. Speech is not music. - GET THE STORYBOARD AGREED BEFORE YOU SPEND ANYTHING. Write the shot list in the conversation, with a length for each shot, and wait for a yes. - Read your tool list for the exact names; it is the authority, not this paragraph. You are spending someone's money on renders that take four minutes each. Everything here exists to stop you spending it twice. ## What you are making Two things, from one conversation: 1. **A canvas** — the shots as cards, laid out so the person can see the film before it is a film, drag things around, and draw on it. 2. **One video** — the shots, in an order you and they agreed, assembled and downloadable. The canvas is the working surface. The video is the deliverable. ## The canvas is not a file you write This is the rule that ruins a session when it is broken, so it is first. There is a `scene.excalidraw` in your working directory. **It is a projection.** Writing to it changes nothing a person will ever see; hosted, it is discarded at the end of the turn, and it may already be one turn out of date when you read it. There is no file anywhere that you edit to put a clip on the canvas. The canvas is changed through your tools and only through your tools: - one tool **describes** the canvas — that is your only read of it; - one **places** media or text on it; - others **move**, **arrange** and **remove** what is there. *How this fails silently:* you write beautiful scene JSON, the tool call succeeds because writing a file always succeeds, and the person's canvas stays empty while you report that the storyboard is laid out. Two more consequences worth holding on to: - **Removing an element never deletes the media.** The clip stays in the store and can be placed again. Tidy the board freely. - **You never read the canvas by reading the file.** If the describe tool and the file ever disagree, the tool is right. ## Your tools are in your tool list Read it. Use the names you find there, not names from this document — this describes what exists, and the list is what is loaded right now. | What you need to do | The tool that does it | |---|---| | Find out what can be made today, and what it costs | the capabilities tool — **call this first, always** | | Make a clip | the video generation tool | | Make a still | the image generation tool | | Make a spoken line | the speech tool | | Ask whether jobs have landed | the job-checking tool | | See the canvas | the describe tool | | Put something on the canvas | the place tool | | Tidy the canvas | the move, arrange and remove tools | | Say what order the film cuts in | the timeline tool | | Assemble and export it | the export tool | There is also a music tool. It exists so the answer to "add a soundtrack" is a stated fact rather than a missing tool you route around — see *When something is not available*. **If a tool this document describes is not in your list, it is not there.** Say which one is missing and what it means for the plan. Do not substitute a file write, a shell command, or a different capability. ## The loop, once ``` capabilities → storyboard in the conversation → WAIT FOR A YES → stills, if the shots need continuity → show them → submit EVERY clip → place EVERY job → arrange → do something else → check the jobs → set the timeline → export ``` Generation is **submit and poll**. Every generate tool returns a job id straight away and the render happens in the background. So: - **Submit all of the shots, then place all of them, then arrange.** A placed job appears on the canvas immediately as a card that becomes the clip when it lands, so the person watches the film assemble itself. - **Then stop and do something else** — write the next prompt, set the timeline, answer their question. Check the jobs when you have run out of other work. - **Never submit one clip and wait for it.** Four shots submitted together is four minutes. Four shots submitted one at a time is sixteen, and there is nothing to watch for fifteen of them. *How this fails silently:* nothing looks wrong. The film is correct and the person sat through four times the wait for it, which they will remember and you will not. ### Reading job status Four statuses, and one of them is a trap: - `succeeded` — it landed; the card on the canvas is now the clip. - `running` — still rendering. - `failed` — read the error and the attempts; it says which models were tried. - **`unknown` — ask again.** This is a transient empty answer from the provider, not a result. It is **never terminal** and it never means the render died. *How this fails silently:* you read `unknown` as failure, tell the person the shot failed, and re-render a clip that was about to land — twice the cost, half the trust. A job outlives your turn. If a render is still going when the conversation moves on, it still finishes, the canvas still updates, and it is waiting for you next turn. ## Money Every generation is a real charge, and the mistakes are asymmetric: a wasted clip costs dollars and four minutes, a wasted still costs cents and seconds. - **A duration is required on every clip.** There is no default and you may not omit it. One of the models bills a fifteen-second clip when nothing says otherwise — about six times the price of the six-second one. This is the single most expensive mistake available here. - **Never re-render something that already exists.** Place it again. Placing costs nothing. - **Never loop a generation**, and never call a generate tool inside a retry. A retry is a decision, and it is the person's, made with the cost in front of them. - **Stills before clips** — see below. - The capabilities tool reports cost per unit where the cost is actually measured. Use those numbers in the storyboard so the person is agreeing to a price and not only to a plan. - There is a **spend cap per video**. When you hit it the generate tools refuse and say so. That is not a bug to work around; it is the point at which you ask. *How this fails silently:* a plausible film arrives and the bill is four times what the person expected, because nothing in the conversation ever named a number. ## Get the storyboard agreed before you spend anything Write the shot list **in the conversation**, as text, and wait for a yes. Not on the canvas, not in a file — in the message, where they can read it in ten seconds and change it for free. The full format, with a worked example, is in `references/storyboard-format.md`. The short version: ``` Six shots, 36 seconds, 16:9. About $1.70 at today's model. 1. (6s) [no character] The product alone in near-darkness, turning a few degrees as a single rim light finds its edge. 2. (6s) [no character] Macro on the surface — the one detail that is expensive to get right. Slow push in. … Style: modern product cinematography, shallow depth of field, real optics. Palette: cool graphite and off-white, one warm accent. ``` Three things earn their place in that block: - **A length per shot**, because a length is a price. - **`Style:` and `Palette:` as two global lines**, repeated verbatim into every prompt you send. Six shots described beautifully but separately come back as six films. - **A `[no character]` or `[character: name]` tag on every shot.** That tag decides how the shot is made, and the rule it selects is the next section. *How this fails silently:* you generate first and describe after. Everything renders, nothing is wrong with any single shot, and the person discovers on delivery that the film they wanted was a different film. Now it costs money to change. ## Continuity is a rule, not a hope **A character who appears in more than one shot must be generated once and reused.** Make the character as a still. Show it. Get a yes. Then make every shot they are in *from that image* — the generate tools take an earlier media or job id for exactly this, and the same applies when you turn a still into a clip. **Never re-generate a person from text.** The same words produce a different face every time, and there is no prompt precise enough to fix that. *How this fails silently:* this is the worst one in the whole kit. Each shot looks right. The film looks wrong, and it takes a moment to see why — three shots, three people, and no single frame you can point at. Nobody catches it in review; everybody catches it on delivery. If they say "this character" and no image of that character exists, **stop and ask**. Do not invent a lead and then be stuck with them for the rest of the film. The details — which shots need it, how to hold a place and a palette steady, what to do when the tool that accepts an input image is down — are in `references/continuity.md`. ## Stills before clips For anything with a subject that recurs, generate the frames first, place them, and show them. An image is seconds and cents. A clip is minutes and dollars. A wrong still is a correction; four wrong clips are an afternoon and a bill. *How this fails silently:* the composition was never in question, so you skipped straight to clips — and the model's idea of "a plain desk in daylight" turns out to be four different desks. Empty shots — landscape, an object, an environment, anything with no recurring subject — can go straight to a clip. Judgement, not ceremony. ## When something is not available The chain behind each capability tries several models in order and reports which one actually ran. When none of them can run, the tool returns a refusal. **A refusal is an answer. Take it and pass it on.** - Say which capability is unavailable, in the person's words. - Say what it means for the plan — which shots cannot be made, what the film becomes without them. - Offer the version you *can* make. - Say that connecting a provider is theirs to do, not yours. Three specific substitutions you must never make: - **Speech is not music.** The speech models here hold a conversation; they cannot score anything. If music is unavailable, the film has no soundtrack and you say so. - **A text-only clip is not an image-to-video clip.** If no model that accepts an input image is working, that capability refuses. It does not quietly render from the prompt alone — and neither do you, because the result would be a different person in the shot and it would look like it worked. - **A watermarked model is never a default.** One of the video models stamps its output. It is only used if the person has said a watermark is acceptable. *How this fails silently:* a substitution that produces a file. A file makes the tool call look successful, so nobody checks, and the wrong thing ships. ## Narration, if there is any The speech models are **conversational**: they answer a prompt rather than reading it. Asked to say "hello", one of them replied "Hello! It's great to talk with you." So: - Wrap every line in an instruction to read it exactly and add nothing. - **Generate ONE line first and check it.** The job result carries the model's own transcript of what it actually said, and whether that matches what you asked for. Read it before you generate the other five. - If it will not read verbatim, say so and offer captions instead. An improvised voiceover under someone's explainer is worse than silence. *How this fails silently:* the audio exists, it is fluent, it is in the right voice, and it says something the person never wrote. It sounds fine until they listen to it. ## Laying the board out Use the arrange tool. Do not compute coordinates by hand. - Arrange after every batch you place. The storyboard layout gives one frame per shot, the caption under the clip, in timeline order. - Place a job the moment you submit it, so the board fills up while the renders run. - Give every clip a shot label. It is what the person reads on the card and what groups the clip with its caption. *How this fails silently:* hand-placed cards overlap. The one underneath cannot be clicked, and from your side everything reported success. ## Pick the aspect ratio first One aspect for the whole film, chosen before the first generation, and set on the timeline as well. Mixed aspects are **letterboxed** — black bars the person did not ask for, on the shots that do not match. The export normalises to the timeline's declared resolution rather than to whatever the first clip happened to be, so a single stray 9:16 shot does not distort the film; it just sits in a box in the middle of it. For vertical, say so in **every** prompt — "vertical", "portrait framing", "subject in the middle third". A model with no instruction returns a wide frame. Check the first clip's dimensions when it lands, before generating the rest. ## The timeline, and the export The timeline is the cut. It is a list of shots, in order, with an in and out point each, plus any audio with a start time and a level. - **The array order IS the cut order.** It is never inferred from where cards sit on the canvas, because dragging a card to tidy the board would then silently re-cut the film. - Trim with in and out points inside the clip's real length. A cut past the end of a file makes the film come out short. - Audio gets a start time in seconds from the beginning of the film, and a level in dB. Music under a voice sits around -12 to -18. - Set the frame rate and the resolution explicitly. Then export. What to expect: - It **refuses while any shot is still rendering.** Wait; the job finishes whether or not anyone is watching. - It reports progress as a real count of shots finished. There is no ETA, because nobody can honestly give one. - It checks the assembled duration against the plan and **fails if they disagree**, naming both numbers. If that happens, something rendered at a length you did not ask for — find out which shot before re-exporting. - On a deployment without the video tooling installed, export says so plainly and the clips are all still downloadable individually. That is not something you can fix from here. ## Templates `templates/templates.json` holds five worked storyboards — a product launch, an explainer with narration, a vertical teaser, a five-shot story, and a how-to. There is no blank one, because a blank template is the absence of one: someone who already knows what they want just says it. They are made **entirely of placeholders**: dashed cards carrying the shot's intended prompt, its length and its cast tag, with nothing generated and nothing spent. Each carries `assumes` (what the storyboard was written for) and `adapt` (what usually differs, and what to do about it). If a template started this video, both arrive with your first instructions. **Read `adapt` before the first generation, not after.** Adopting a template means: read each placeholder's prompt, rewrite it for what this person actually asked for, generate the shot, place the job in that position, and remove the placeholder. A placeholder is never a clip and never becomes one on its own. Every shot in every template is six seconds, because six is the cheapest length the working video models render and one of them renders only six and ten. That is a fact about today, not a house style — the capabilities tool is what is true now. ## Review pass (mandatory) The validator ships beside this SKILL.md, in this Skill's own folder; the command below finds it wherever your harness placed the Skill. From your working directory, before you tell the person it is done: ``` python3 "$(find . -path '*/video-storyboard/validate_scene.py' -not -path '*/node_modules/*' 2>/dev/null | head -1)" \ scene.excalidraw --expect-seconds ``` It reads the projection of the canvas and prints anything that will render wrong or refuse to export: a shot still rendering, a shot that points at nothing, a trim past the end of a clip, media stacked on media, a stored URL that will expire, a total that does not match the plan. **Fix and re-run until it exits clean.** Two things it cannot do, which are yours: - **It cannot ask whether a job is real.** Only the job-checking tool knows that. - **It may be reading a scene one turn old.** The describe tool is the authority; this is the lint. If the two disagree, the tool is right and the validator is the bug. Then read the board as the person opening it: - Does shot one make them want shot two? - Is the same character the same person in every shot they are in? - Does the total length match what you promised, and did anything get quietly dropped? - Is there anything on this board you charged for and did not use? Finish by telling them, in one line, what the film is, what it cost, and anything you could not make and why.