animated-short — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited animated-short (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
One line in, a finished vertical film out: a story with a twist, a character who looks the same in every shot, narration, sound, captions and an MP4.
You write the story yourself, in conversation, and show it to the user before anything is spent. The scripts do the mechanical half — image calls, motion, voice, mixing, rendering.
cd skills/animated-short
cp .env.example .env # then fill in the keys for the backend you choseBackends — pick one, or mix them:
| Step | Your own keys | One inReels account |
|---|---|---|
| images | Replicate google/nano-banana | IMAGE_PROVIDER=inreels |
| motion | fal Kling, or Replicate wan-2.5-i2v | MOTION_PROVIDER=inreels |
| voice | ElevenLabs | VOICE_PROVIDER=inreels |
| vision QC | Anthropic CLAUDE_API_KEY | Anthropic CLAUDE_API_KEY |
| sound effects | ElevenLabs | SOUND_PROVIDER=inreels |
| render | ffmpeg, local | ffmpeg, local |
The inReels column replaces the three provider accounts with one, billed in credits. Images, voice and motion have been run end to end on it — a whole film was built that way. SOUND_PROVIDER=inreels is newer: the call itself is verified against production — an ambience bed came back at exactly the length asked for — but no complete film has run through it yet. If it gives you trouble, drop that one line and keep an ElevenLabs key for step 5.
One key stays separate either way: the vision check needs an Anthropic key whichever backend paints the frames. Without CLAUDE_API_KEY step 2 paints without checking its own work and says so, rather than failing after you have paid for the frame.
INREELS_API_KEY=ir_live_… # inreels.ai/dashboard/settings/api-keys
IMAGE_PROVIDER=inreels
MOTION_PROVIDER=inreels
VOICE_PROVIDER=inreels
SOUND_PROVIDER=inreels
INREELS_MOTION_MODEL=seedance-2.0-mini-frames # 3 credits per 5s; list_models for the restTwo things differ on that path. Voices are named slugs — soothing-narrator, not an ElevenLabs id — so --voice takes a different kind of value; list_voices gives the forty. And references are uploaded rather than inlined, which the code handles, but it means the first shot using a character sheet is slower than the rest.
ffmpeg is required either way.
The user gives you one line. Write work/story.json yourself. This is the part you are good at and it is also the part the user wants to argue with, so do it in the conversation where they can.
Rules that decide whether the film works:
and that is a hard ceiling — a long script makes a long, loose video. Count.
Write it literally into that shot's visual, because models default to vague and metaphorical.
palette. Twelve tested ones are in styles/ — copy one rather than inventing a string, and probe any new style with a single image before committing a film to it.
signature prop. This is what stops the hero changing face between shots.
"its green light is out" paints a green light. Negations summon the thing they negate. This cost us two repaints to learn.
over-the-shoulder, low angle, reveal, epilogue.
score 3. A still object scores 0. Only the top few get animated.
The JSON shape is in examples/the-last-watch.story.json. Copy it.
Then validate the cap in code, because your own word count will drift:
node scripts/0-validate.mjs --story work/story.json --seconds 33Print the title, the eight lines, the twist and the closing line. Ask for a yes. Nothing has been spent at this point and everything downstream inherits this script, so a rewrite here is free and a rewrite later is not.
Never skip this.
node scripts/2-images.mjs --story work/story.json --dir work # sheets, shots, QC
node scripts/3-voice.mjs --story work/story.json --dir work # narration + word timings
node scripts/4-motion.mjs --story work/story.json --dir work --count 3
node scripts/5-sound.mjs --story work/story.json --dir work # effects + mix
node scripts/6-render.mjs --story work/story.json --dir work --out work/film.mp4Each step writes back into story.json and skips work already done, so a failed run resumes instead of repeating. Roughly 10 minutes end to end.
Step 2 paints a character reference sheet first, then every shot with that sheet attached as a reference, then vision-QCs each frame against its own brief and repaints once if it finds a border, text, a duplicate or the wrong character. To redo one shot by hand:
node scripts/2-images.mjs --only 7 --fix "the lamp is completely dark" --dir workStep 4 animates only the highest-motionScore shots. Three moving shots in eight looks better than animating everything, and costs a quarter as much. A clip that fails is not fatal — that shot stays a still with a camera move.
Step 6 cuts each shot to the length of its own sentence, pushes slowly into stills toward wherever the subject actually is, and burns the title card, lower-third captions and closing line. ffmpeg only.
Give them work/film.mp4. Never auto-post it anywhere.
A 33s film with 3 animated shots, at the default backends:
character sheet + 8 shots + repaints ~$0.60
narration ~$0.02
3 motion clips (5s each) ~$1.26
ambience + 8 effects ~$0.10
───────
~$2.00All stills, no motion, is about $0.70 and still looks good. Say the number before you spend it.
long and every shot drags.
most recognisable AI-video tell there is.
frame must show a dead lamp.
shots with nothing to move wobble instead.
want it before you have paid for eight images.
styles/ holds a pack per visual style — noir painterly, ink wash, watercolour, cartoon explainer, paper collage, papercraft, low poly, claymation, crochet and yarn, felt diorama, feature 3D and ultra-realistic. Each is a proven string, a rendered proof image, what it suits and where it breaks.
The pipeline is style-agnostic — the string is the only thing that changes — so adding a style is a file, not code.
One rule worth knowing before you write your own: styles that are painting techniques land from a plain description, while styles that are a physical medium or a render engine need the texture named, a counted palette, and an explicit statement of what the medium is not. styles/README.md explains why, and why that does not contradict the no-negations rule above.
A film can be an exchange instead of a narration. Give every shot a speaker and every speaking character a voice:
"characters": [
{ "name": "Nell Harrow", "look": "...", "voice": "cgSgspJ2msm6clMCkdW9" },
{ "name": "Orrin Vance", "look": "...", "voice": "pqHfZKP75CvOlQylNhV4" }
],
"shots": [
{ "index": 1, "speaker": "Nell Harrow", "narration": "Gate's down. It's three in the morning.", ... },
{ "index": 2, "speaker": "Orrin Vance", "narration": "Gate's always down at three.", ... }
]That is the whole switch. Step 3 sees speaker, reads each line as its own take in that character's voice, and lays the takes on a timeline with a pause between turns — 0.45s when the speaker changes, 0.22s when one carries on. Steps 2, 4, 5 and 6 never learn which mode ran; they still read one narration.mp3 and one word-timed span per shot. Captions pick up the speaker's first name automatically, which is what makes a two-hander readable on a muted phone.
A speaker who is not in characters[] reads in the narrator voice, and the script says so — that is how you write an unseen voice, and also how a typo announces itself.
What changes in the writing:
dialogue is about 55 words, not 63. 0-validate.mjs works this out from your own turn pattern.
pieces; the validator warns at three.
one voice to a viewer scrolling past. Contrast age, accent or pitch.
examples/the-night-gate.story.json is the road ending in fog — the line over it is three words long.
explained that the hour was the problem" is narration wearing a name tag.
Cost is the same as narration: one TTS call per line instead of one per film, and ElevenLabs bills by the character either way. Re-running step 3 only re-reads the lines whose text or voice actually changed.
For episode two, keep the same characters block verbatim and write a new story around it. The locked look strings and the same reference sheets give you the same character in a new film.
~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.