stopmotion-video
Rules, Remotion helpers and audio scripts for stop-motion style video cut to music, proposing Remotion by default to make it. A low frame rate is kept on purpose, with one pose per eighth note of the song. Pages start on bar lines, clicks land on kicks and snares, and the skill teaches when to skip a beat. Use when making or reviewing stop-motion, low frame rate, beat-synced or music-synced video. Also use for cutting a video to a song, Remotion launch films cut to a track, compositions timed to a BPM, metronome or click tracks, kinetic type timed to a beat, or scenes played live on a web page in time with a metronome. It covers measuring a song's tempo, bars and drops, and deciding where a cut, a click, a hold or a transition should land.
Install
npx skills add https://github.com/kosta4a/stopmotion-video --skill stopmotion-videoStop-motion video
Videos made with this skill move like stop motion shot to a song. Each pose is held for one eighth note, then everything changes together. Pages come on at bar lines. Every click sounds on a drum hit, and the big changes land on the big kicks. The frame rate stays low on purpose. When a move looks rough, its poses are spaced better; the beat is never smoothed away.
The rules come from making a 47-second launch film cut to a drum and bass track at 169.825 BPM, over a few hundred rounds of notes. The film ran at 30fps and held one pose per eighth note, which is 5.66 poses a second, 5 or 6 frames each. The values here are the film's, and in live.md those of a web page that plays scenes from it against a metronome. Where a rule generalises beyond them, the text says so.
Vocabulary
- Pose: one held picture, the song's eighth note. The code calls it a beat (
STEP_MS,useBeat). - Song beat: what the BPM counts, a quarter note. It is two poses long and gets one metronome click.
- Bar: four song beats, eight poses. In drum and bass the kick falls on pose 0 and the snares on poses 2 and 6, counting from 0.
- Hit: a drum sound in the song. A big kick is the kick that opens a phrase (every odd bar in the film's track).
- Authored ms: times in the code. They are written on a 200ms pose and play
SPEEDtimes faster (SPEED = TEMPO / 150). - Timestamps are written m:ss.ff, where ff counts frames. That is how Remotion Studio shows time, and how notes arrive.
Operating posture
- Keep the low frame rate on purpose. Never smooth the beat away to fix a move. Space the move's poses better instead.
- Everything holds a pose for a beat and changes together, transitions included. Nothing runs on its own clock: an embedded animation or a scrolling page steps on the pose too. Typing is the one exception: it runs quicker than the beat, as typing does, from its pose.
- The song is the clock. Measure it before you storyboard. Lay pages on its bars and put actions on its hits.
- One clock for the whole video. Count poses on the video's frames, never on a scene's.
- Move in whole bars. Change a page's length by whole bars, or take the poses back elsewhere before the next bar line. Otherwise everything after it falls off the song.
- No idle poses. Once what happens on a page is done, hold it only as long as a viewer needs to take it in.
- Few kinds of change, one direction, nothing fades.
- Check by measuring. Use stills one per pose, timings measured in the render's audio, and a metronome cut. Don't judge sync by eye.
The tool: Remotion, by default
Propose Remotion to make the video unless the project already makes its video another way. Say so before storyboarding, with the reason, and change only if the user asks for another tool. On a web page, play it live instead (live.md [blocked]); in a motion tool, the rules still hold but the helpers don't.
- Why it fits. Every frame is a React component worked out from the frame number, so a pose is exact on whatever frame it lands and renders the same every time. A render draws frames out of order, across several tabs, which only a video driven by the frame survives. The helpers in
assets/remotion/are written for it, and its Studio shows time as m:ss.ff, the form notes arrive in. - Set it up.
npx create-video@latestwith the blank template. Pinremotionand every@remotion/*package to one exact version (the film's: 4.0.532), and keep TypeScript on 5.x (clock.md [blocked] §7). One composition, 1920×1080 at 30fps. Copybeat.tsandtransitions.tsxintosrc/and setTEMPO. - Configure it. In
remotion.config.ts: JPEG frames at quality 95 (the default 80 roughens flat grounds and thin type at their edges), BT.709 colour (so players show the colours as the browser does), and overwrite on. - Preview and render.
npx remotion studioto work in;npx remotion render <Comp> out/<name>.mp4for 1080p, with--scale=2for 4K;--frames=<first>-<last>ornpx remotion still <Comp> --frame=<n>to check a stretch or a pose.
The decision order
Work top to bottom. Each step constrains the next.
- Propose the tool. Remotion, unless the project already makes video another way; set it up as above before anything else.
- Measure the song. Find the tempo from its onsets and check that the grid holds over the stretch you use. Mark the bars and phrases, where the drums drop out and come back, and the big kicks. Cut the excerpt exact to the sample, a hair (23ms) before a phrase's first kick. See song.md [blocked].
- Set the clock. A pose is the song's eighth note. Author on a 200ms pose with
SPEED = TEMPO / 150, render at 30fps, and count poses on the whole video's frames. See clock.md [blocked]. - Lay the pages on bars. Write the storyboard in poses. Each page is a whole number of poses and starts on a bar line. Map the song's events to poses before you animate anything.
- Place the hits. Code is typed in chunks on the eighths, and titles and a held backspace run quicker than the beat from their pose. Clicks and pops go on snares, landings and new pages on downbeats, and big changes on big kicks. The build goes in the quiet, and the landing comes when the drums return. See hits.md [blocked].
- Space the poses. Pick each curve for its poses. A move's first pose is its first step, and every pose moves it visibly. Things land rather than creep. See poses.md [blocked].
- Change pages. Use a hard cut on the beat, a cut of the ground, a page laid over like a sheet, the camera going into a colour, a fill from inside, an opening through a shape, or pixel blocks. Never a fade. See hits.md [blocked].
- Set the type. Tracking tightens as size grows, and leading tightens with it. Every word passes 4.5:1 against its ground at every pose. Titles are typed, not faded. See type.md [blocked].
- Make the sound. Every click goes on the song's own hit, placed to the sample, and all clicks are baked into one track that starts with the song. Duck the music under the clicks, and keep a metronome cut for checking. See sound.md [blocked].
- Decide where to skip a beat. Drop, duck, hold, snap, cut whole bars, end on a song beat. See skipping.md [blocked].
- Check. Make a contact sheet, measure the sync, and watch the metronome cut. Take notes as timestamps mapped to poses. See checking.md [blocked].
- Playing it live, in a browser? The same rules against a metronome: one clock on the page's time, the picture 25ms ahead of the sound, the sound scheduled ahead on the audio clock, and with no song every change on a click. See live.md [blocked].
Rules at a glance
Clock
Spacing
Things on the beat
Hits
Clicks must be on the beat. A transition can be off it.
Sound
Type
Every word must reach at least 4.5:1 against its ground at every pose. Use one family by default (Geist and Geist Mono in the examples), black on white, as tactile-design does; the film itself paired a display face with its text face and set its pages on flat colour grounds. Counters use tabular figures. Titles are typed on, never faded in.
Live, in a browser
When to skip a beat
The grid is strict, so breaking it is a decision. Every break below has a reason in skipping.md [blocked].
- Drop the music round a click that matters. It goes silent from 50ms before the click to the next bar line, with 10ms fades. The click is heard alone, and the beat comes back with what follows.
- Duck under the other clicks. Lower the music to 45% for 160ms so the click's thump has room.
- Hold a result alone for one song beat before the next thing starts, such as a tick after a copy.
- Hold two identical poses at the top of a rise.
- Hold two poses on a round number before moving on.
- Snap a note that falls between beats to the nearest accented beat.
- Cut whole bars, even when the note asks for less. Say what it costs.
- End on a song beat. The last page holds about 2 seconds, with the music fading over the last pose. Otherwise end right after the action.
Never ship
- Motion smoothed off the beat to hide a badly spaced move
- A scene counting poses from its own first frame
- A page that starts off a bar line without a reason written next to it
- A length change that isn't whole bars and isn't taken back before the next bar line
- A Studio
fromoffset left in the composition tree - A click off a kick or a snare, or a click sound placed on a frame instead of to the sample
- Short click sounds started at their own frames instead of one baked track
- A move whose first pose is the pose it leaves, or that creeps its last few px
- Something from off the frame drawn before it has moved
- A spinner or wheel turning over half a turn a pose
- A fade, or a crossfade between saturated grounds
- Ground changes faster than three flashes a second
- A word under 4.5:1 against its ground at any pose
- Tracking left at 0 on display type, or a counter in proportional figures
- Idle poses after a page's action is done, or a tail that "extends for no reason"
- The metronome in the export
- CSS transitions or animations, or a library's
animate(), in a render - Not checked pose by pose and measured against the song
- Live: sound played on a frame, or a lookahead that leaves out the output's latency
- Live: a picture drawn after its click, or scenes committed a frame after the rest
- Live: a first press that starts the sound and mutes it, or scenes moving under reduced motion unasked
References
Open the file for the step you're on. Each pairs a value with its reason, so it carries to a new song.
- song.md [blocked]: measuring the track, cutting the excerpt, and mapping it to poses and bars.
- clock.md [blocked]: one clock, frames per pose, bar lines, page lengths, Remotion wiring and the 60fps variant.
- poses.md [blocked]: stop-motion spacing and the rules for each kind of thing.
- hits.md [blocked]: what lands where, and the transitions.
- skipping.md [blocked]: when to skip, hold, drop or duck a beat, and the reason for each.
- sound.md [blocked]: clicks placed to the sample, ducking, the click track and the metronome.
- type.md [blocked]: type in the frame, covering tracking by size, leading, contrast and typing.
- checking.md [blocked]: contact sheets, measured sync, notes as timestamps and the review loop.
- live.md [blocked]: playing it live, the same rules in a browser against a metronome: the page's clock, sound scheduled ahead, starting and pausing the sound, reduced motion and type on screen.
Tools:
assets/remotion/beat.ts: the clock and the beat helpers (TEMPO,SPEED,ms,useBeat,moved,clicked,press,blink, the curves).assets/remotion/transitions.tsx:onTheBeat,inSteps,onQuarters,slideOver,pixels,throughShape.scripts/find-tempo.mjs: a song's tempo, grid, drift and bars, from a WAV.scripts/duck.mjs: the music silenced or lowered round clicks.scripts/make-metronome.mjs: a click track for checking.