Communitygithub.com

munna-68/animation-video-skill

Turn a story, idea or voiceover script into a finished hand-animated 2D cartoon short (vertical 1080x1920 mp4, about 35-45 s) with character animation, a VoiceStudio voiceover, burned-in captions, sound effects and music, plus an Instagram caption. Use this whenever the user runs /animation-video or asks for an animated video, cartoon, animated short, reel, animated explainer, "episode", or "another one like the Mall Landlord / Link Jungle video", or pastes a logline, scene list or voiceover script and wants it animated, even if they never say the word "skill". Does everything end to end with no questions asked - script, voice, animation, sound, render.

What is animation-video-skill?

animation-video-skill is a Claude Code agent skill that turn a story, idea or voiceover script into a finished hand-animated 2D cartoon short (vertical 1080x1920 mp4, about 35-45 s) with character animation, a VoiceStudio voiceover, burned-in captions, sound effects and music, plus an Instagram caption. Use this whenever the user runs /animation-video or asks for an animated video, cartoon, animated short, reel, animated explainer, "episode", or "another one like the Mall Landlord / Link Jungle video", or pastes a logline, scene list or voiceover script and wants it animated, even if they never say the word "skill". Does everything end to end with no questions asked - script, voice, animation, sound, render.

Works with✓Claude Code~Codex CLI~Cursor
npx skills add https://github.com/munna-68/animation-video-skill/tree/HEAD

Ask in your favorite AI

Open a new chat with this agent skill pre-loaded.

Documentation

Animation video

You are making a short cartoon film from a story. The user gives you a story, a logline, a scene list or a script. You deliver a finished mp4 and an Instagram caption. You do every step yourself and you do not stop to ask for approval along the way.

The films this skill makes look hand-animated: characters that squash, stretch, blink and react, a camera that is never still, a paper-and-ink texture, and picture that hits exactly on the voice. They must NOT look like a slideshow of static pictures with text. Everything in this skill exists to get that result reliably, so follow the steps in order and use the kit instead of inventing your own system.

SK below means this skill's folder: ~/.claude/skills/animation-video.

How it works (read this once)

  • The whole film is one JavaScript file, film.js, that you write. It describes what is on screen at any time t. A script renders it frame by frame in headless Chrome and ffmpeg makes the mp4. There is no video editor and no image generation.
  • The voiceover is generated first, line by line. Its real timings are written to timeline.js. Every moment in the film is then defined relative to the voice (for example "0.2 s before line 4 starts"), so picture and voice cannot drift apart.
  • A kit gives you the hard parts ready-made: an engine (easing, camera, scenes, captions), two complete art styles with characters, poses and props, and 25 tested animation recipes.
  • You check your work by rendering still frames and looking at them. This is not optional. You cannot judge a film you have not looked at.

The steps

Create the task list from these steps and work through them in order.

#StepResult
0Preflightall tools present, VoiceStudio running
1Read the story, pick the styledecisions made, project folder created
2Write the scriptvo/script.json, at most 130 spoken words
3Generate the voiceone checked wav per line
4Build the timelinetimeline.js, film length 35-45 s
5Plan the shotsa shot plan comment at the top of film.js
6Write the filmfilm.js, scene by scene, checking stills as you go
7Review the whole filmcontact sheets viewed, defects fixed
8Exportthe mp4
9Delivermp4 + script as voiced + Instagram caption + honest notes

Step 0 - Preflight

bash ~/.claude/skills/animation-video/scripts/preflight.sh

Every line must say OK. If VoiceStudio is MISSING, ask the user to open the VoiceStudio app and wait; never substitute a different voice or skip the voiceover. Fix anything else with the command the script prints.

Step 1 - Read the story and pick the style

Do not ask the user questions unless there is no story at all. Decide these yourself:

  1. Style. There are two. Look at SK/references/characters-ink.jpg and characters-paper.jpg (use the Read tool on the images) to see them.
    • ink: thick wobbly ink outlines, chunky serif signs, warm retro cartoon. Best for stories with a villain, slapstick, shops, streets, physical gags.
    • paper: cut-paper collage, no outlines, soft shadows, elegant serif. Best for stories about phones, apps, links, nature, softer or more modern moods.
    • If the user asked for a style, use it. Otherwise, if the working folder already has an earlier episode, use the OTHER style (run head -3 */style.js 2>/dev/null to see which was used). Otherwise pick by the story.
  2. Cast. Who is the hero (the small business owner or main character)? Who or what is the obstacle (a villain, a confused customer, a maze)? Two main characters is plenty.
  3. Project folder. A short name from the story, in the user's working folder.
bash ~/.claude/skills/animation-video/scripts/new_project.sh "./film-<short-name>" ink    # or paper

This creates the project with a working starter film.js. Read that starter file now: it is short and shows the exact structure you will keep.

Step 2 - Write the script

Read SK/references/story.md first. It has the structure, the word budget and worked examples. The rules that matter most:

  • At most 130 spoken words in total. The voice speaks about 3.2 words per second, so 130 words is about 43 s. If the user's script is longer, cut it down yourself, keeping their best lines and the order of the story. Do not ask; tell them at the end what you cut. A short film that moves is always better than a long one that drags.
  • One line per beat, 5-16 words each, ids l01, l02, ... Each line becomes one audio clip and usually one visual idea.
  • Write for the ear: numbers as words ("forty", not "40"), no emoji, no symbols, brand names spelled the way they sound ("Site Keep" for SiteKeep).
  • The last line is a hook that asks viewers to comment (see Brand defaults below).

Write it to <project>/vo/script.json:

{"l01": "Meet Maya. She makes custom treats from scratch.",
 "l02": "So she set up shop inside a giant online marketplace."}

Step 3 - Generate the voice

python3 ~/.claude/skills/animation-video/scripts/voice.py "./film-<short-name>"

This takes about 20 s per line (4-5 minutes for a full script): run it with a 10 minute timeout. If it stops part-way, run the same command again; lines already voiced are kept. It generates each line with the user's voice (profile 3a02464e, "ep1 D sample-locked", English, steps 16, speed 1.0, no instruct text; these are the defaults, do not change them unless the user says so), listens to it again, and prints for every line OK or DIFF with what it heard.

Read every DIFF line and decide:

  • Fine: the same words written differently ("SiteKeep" / "Site Keep", "40" / "forty", "two" / "to", punctuation).
  • Not fine: a word is missing, added, or is a different word ("her menu" heard as "our menu"). Regenerate just those lines: voice.py <project> --only l05 l11. If a line still fails after two more tries, reword that line slightly in script.json and regenerate it.

Never ship a line with a dropped, added or wrong word.

Step 4 - Build the timeline

python3 ~/.claude/skills/animation-video/scripts/audio.py timeline "./film-<short-name>"

It prints the total length and each line's start time and duration. Then tune the pauses in <project>/film.json and run it again:

{"lead": 0.55, "gap": 0.4, "tail": 1.6, "gaps": {"l04": 0.7, "l09": 0.9}}
  • gap is the default pause after a line. Give a longer gap (0.6-0.9) after a line whose visual needs room to play out: a gag, a fall, a big reveal, the turn of the story.
  • Use 0.25-0.35 between lines that are one thought.
  • tail is how long the end card holds after the last word (1.4-1.8).
  • Target total: 35-45 s. Over 46 s: cut a line from the script and redo steps 3-4 for it.

Whenever you re-voice a line later, run audio.py timeline again. Because every cue is relative to the voice, the film re-syncs by itself.

Step 5 - Plan the shots

Read SK/references/story.md section "From script to shots". Then write the plan as a comment block at the top of film.js (not a separate document). One row per scene:

/* SHOT PLAN
   A  l01-l02  street, day      Maya pops up behind her stall, waves. Camera: slow push-in.
   B  l03-l04  same street      Landlord's shadow falls over her, sign SLAMS down (shake, dust). She jumps.
   C  l05      basement         Trapdoor opens, she hangs in the air, drops. Camera follows down.
   ...
   Z  l12      end card         Circle wipe. Question + "drop one in the comments". Hero peeks in.
*/

A good plan has: 5-8 scenes; a different picture at least every 6 s; one clear visual gag or surprise in every scene; every abstract idea turned into something physical (a fee becomes a toll gate, an algorithm becomes a trapdoor, a confusing link becomes a jungle); the mood turning from trouble to relief at the solution; and an end card.

Step 6 - Write the film

Before writing, read these (they are short, and they are the difference between a good film and a broken one):

  1. SK/references/engine.md - every function you can call.
  2. SK/references/kit-ink.md or kit-paper.md - your style's characters, poses, props.
  3. SK/references/recipes.js - 25 tested moves to copy. Look at recipes-<style>.jpg too.
  4. SK/references/craft.md - the timing numbers and rules that make it feel hand-animated.

Then write film.js in the starter's four sections: settings, cue times, sound cues, scenes.

Work one scene at a time. Write scene A, render two or three stills from it, look at them, fix, then go on to scene B:

node ~/.claude/skills/animation-video/scripts/render.mjs "./film-<short-name>" stills 1.2 3.5 6.0

Then open <project>/check/sheet-1.jpg with the Read tool. If the command prints PAGE ERROR, the film has a JavaScript error: fix the first one printed and run it again.

The ten rules of film.js (each one prevents a failure that has actually happened):

  1. Only edit film.js (and colours in style.js if needed). Never edit engine.js or index.html.
  2. Never type a raw time. Every cue is built from the voice: L('l04') (line start), E('l04') (line end), wt('l04', 'three rival') (when a phrase is spoken), plus or minus a small offset. Give each a name: const tSlam = L('l04') + 0.25;
  3. Start an action 0.1-0.3 s BEFORE its word so that it lands ON the word.
  4. Poses and objects use q (time stepped 12 times a second: the hand-animated feel). Camera, shake and wipes use t (smooth).
  5. Nothing may be visible before its cue. Use pop(...) or if (q < tCue) ... so things appear when the voice mentions them, not before.
  6. No Math.random(), no Date, no CSS animation, no setTimeout. Use h(n) for randomness. The film must give the same picture every time for the same t.
  7. Draw backgrounds much bigger than the screen (for example x from -1000 to 2080) so camera moves and shake never show an empty edge.
  8. Draw order is depth: things drawn later are in front. Background first, then far objects, characters, near objects, then effects.
  9. Keep important things inside x 70-1010 and y 180-1400. The captions sit at y 1420-1560 and Instagram's own buttons cover everything below y 1600 and the right edge.
  10. Every sound belongs to a visible event and is declared with sfx(time, name) at the same cue time as the event. One music(...) bed for the trouble part, another for the relief.

The quality bar. Before you call a scene done, it must have all of these:

  • Life in every frame. The hero blinks and breathes (POSE.idle(q)), something in the background moves (cloud, sign sway, floating shapes), and the camera has at least a slow push-in. A frame where nothing moves for more than a second is a defect.
  • Entrances and exits are animated, never a plain cut-in: pop with overshoot, drop with a bounce, hop in, zip off with anticipation (recipes 1-6).
  • Impacts hit on one frame, together: squash + screen shake + dust or burst + a sound (recipe 3). This single thing does more for "feel" than anything else.
  • Characters act. They look at what is happening (look), react a beat AFTER it happens (recipe 9), and change pose and face when the story's mood changes. Never leave a character in one pose for a whole scene.
  • One gag per scene that makes the idea physical and a little funny.
  • Readable text. Signs and labels are at least 40 px tall, 1-4 words, high contrast, on screen for at least 1 s, never covered by a character or the captions.
  • A real transition between scenes (recipes 19-20, or a fast camera move within one world), not just one picture replacing another.

Step 7 - Review the whole film

node ~/.claude/skills/animation-video/scripts/render.mjs "./film-<short-name>" check 36

Open both contact sheets (check/sheet-1.jpg, sheet-2.jpg) with the Read tool. Each shows 18 frames in time order, left to right, top to bottom; the times are printed by the command. Go through this list on every frame, and write down what you find before fixing anything:

  • Text cut off, overlapping other text, or covered by a character or prop
  • Captions covering something important, or a brand name split or misspelled (set CAPTION.replace, or move the action up)
  • A big empty area (more than a third of the frame with nothing in it): zoom the camera in, or move things, or add background detail
  • Something visible before the voice has mentioned it, or still there after it should be gone
  • A character or key prop partly off-screen, tiny (under 250 px tall), or hidden
  • A hand, arm or object passing through something it should be in front of or behind
  • Two frames in a row (2+ seconds apart) that look identical: add motion or a camera move
  • The wrong emotion on a face for that moment in the story
  • The end card: question readable, comment prompt visible, nothing overlapping

Fix what you found, then render stills at just those times to confirm (render.mjs <project> stills 4.2 11.8). Look at single frames full size (check/f003.jpg) when a sheet is too small to judge. Do at most two full review rounds; do not polish forever, and do not skip the review either.

Step 8 - Export

bash ~/.claude/skills/animation-video/scripts/build.sh "./film-<short-name>" "./<short-name>.mp4"

This takes 2-10 minutes (paper style is slower): run it in the background or with a 10 minute timeout. It renders every frame, mixes voice + sound effects + music, and prints a check. Confirm: h264 1080x1920 at 30 fps with aac audio, duration equal to the timeline total, mean volume between -16 and -19 dB. If the render prints PAGE ERROR, fix it and run again.

Step 9 - Deliver

Give the user, in this order and briefly:

  1. The mp4 as a link, with its length.
  2. The script exactly as voiced (and, if you shortened theirs, one line saying what you cut and why).
  3. The Instagram caption (see story.md, "The caption").
  4. Honest notes: anything you could not verify (you have looked at stills, not watched the video play with sound), and any line the voice check flagged.

Brand defaults

The user makes these for SiteKeep (sitekeep.studio, websites for small businesses). Unless the story is clearly for something else:

  • Spoken as "Site Keep" in the script; shown as "SiteKeep" everywhere on screen. The starter already sets CAPTION.replace = { 'Site Keep': 'SiteKeep' }.
  • The story turns when the hero switches to SiteKeep; show the brand name on screen then.
  • The last spoken line and the end card ask viewers to drop a small business in the comments for the next episode.
  • The Instagram caption ends with a call to action to DM the word "KEEP".

For any other brand or a story with no brand, keep the same shape (hook, problem, turn, payoff, comment prompt) and leave SiteKeep out.

When something goes wrong

What you seeWhat to do
PAGE ERROR ... is not definedA typo or a function from the other style. Check the name in engine.md / your kit file.
PAGE ERROR ... Cannot read properties of undefined (reading 'start')A line id that is not in the script, e.g. L('l13') when the script ends at l12.
PAGE ERROR ... attribute ... Expected number, "NaN"A calculation produced NaN, usually a misspelled cue name or dividing by zero.
Stills are blank or one flat colourYour scenes do not cover that time. Check each scene(from, to, ...) range; together they must cover 0 to END.
Something appears in the wrong placeYou mixed local and absolute coordinates. Inside G(x, y, inner) the inner drawing is relative to (x, y). Inside pop(x, y, u, inner) it is NOT.
Things drift or jump between rendersYou used Math.random() or state kept between frames. Use h(n) and pure functions of q.
Cannot reach VoiceStudioAsk the user to open the VoiceStudio app, then rerun.
VoiceStudio stopped respondingThe app quit or restarted mid-run. Ask the user to reopen it, wait 20 s, run the same voice.py command again (finished lines are kept).
timeline.js is missing / No voice file for lineSteps were skipped: run voice.py, then audio.py timeline, before rendering.
unknown sfx nameValid names: pop ding tick coin thud slam whoosh fall snip magic.
Render is very slowToo many P(...) shadows or filters. Wrap whole objects in one P, not each small shape.
Voice and picture out of syncYou typed a raw time somewhere, or forgot to rerun audio.py timeline after re-voicing.

Reference files

Read the ones marked * before writing the film. Open the images with the Read tool.

FileWhat it is
references/story.md *Script structure, word budget, turning lines into shots, the caption
references/engine.md *Every engine function with examples
references/kit-ink.md / kit-paper.md *Your style: palette, text, characters, poses, props, how to draw new things
references/recipes.js *25 tested animation moves, copy and adapt
references/craft.md *Timing numbers and the principles behind the quality bar
references/recipes-ink.jpg, recipes-paper.jpgWhat each recipe looks like
references/poses-ink.jpg, poses-paper.jpgEvery ready-made pose
references/characters-ink.jpg, characters-paper.jpgCharacter options and props
assets/examples/Two complete finished episodes to study (see assets/examples/README.md)
assets/kit/The files copied into each project. Do not edit these originals.

Related Skills