name: stanglivideo description: Make motion design videos in code with Remotion, cut to music with sound effects that land on the frame. Use when someone asks for a promo, launch film, product video, explainer, social cut, landing loop or any "motion design video", for a product or not. It checks the machine, studies 2 to 5 videos the user likes (frames, spectrogram, volume), stops for the user's approval on look, claims, music and storyboard, builds from the product's own design, scores the film offline and will not call it done until a sync, loudness and picture gate passes. Optional modes: re-study the reference galleries for new entries, and generate photos or footage loops with Gemini when code cannot draw them.
stanglivideo
A film that looks like the product made it, moves on the beat, and sounds right: every sound on its frame, every word on screen long enough to read, nothing outside the frame. Built in Remotion from code, so it stays editable.
Paths below are relative to this skill's folder unless they start with a film project path. $PY is the python the
doctor prints (the skill's .venv).
Every run starts here
-
Doctor. First run (no
.venvor notaste.mdin this folder):node scripts/doctor.mjs --setup. It creates.venv, installsrequirements.txtand createstaste.mdfromtaste.example.md. Later runs:node scripts/doctor.mjs. It checks Node 18+, Python 3.10+ with numpy and scipy, a full ffmpeg, and the companion skill. If Node itself is missing, the doctor cannot run: say so and give the install line below. -
Tell the user plainly what is missing. For every FAIL, one short line: what is missing, why the skill needs it, and the exact command to fix it on their system. Then stop until they say it is done, and run the doctor again.
Missing Why Windows Mac Node 18+ builds and renders the film winget install --id OpenJS.NodeJS.LTS -ebrew install nodePython 3.10 to 3.13 scores the sound and runs the checks winget install --id Python.Python.3.12 -ebrew install [email protected]ffmpeg (full build) analysis, encoding, loudness checks winget install --id Gyan.FFmpeg -ebrew install ffmpegcompanion skill Remotion API rules npx skills add remotion-dev/skillssame After installing Node, Python or ffmpeg the user must open a new terminal so it is on the PATH, then run
node scripts/doctor.mjs --setupagain.GEMINI_API_KEYis optional: mention it only when a generated image or loop is actually wanted. -
Companion skill (required).
remotion-best-practices, Remotion's official skills. Not bundled here. Use it for Remotion API questions (media, fonts, captions, rendering options). -
Taste. Read
references/base-rules.mdandtaste.md(create it fromtaste.example.mdif it is still missing). These are the user's standing rules;taste.mdwins on conflict.
Non-negotiables
- Their design wins. Colors, type, components, logo, voice and claims come from the product. Never carry another product's taste in, including anything in this skill that their design contradicts.
- Every frame is a pure function of time. No CSS transitions or keyframes, no timers, no
Date.now(), noMath.random(seededrand), no state carried between frames. - One timing source. Each film's
src/films/<film>/cues.jsonholds every cue time. The film's TSX imports it and the score reads it (sound/cues.py). Neither ever holds a literal time. - Measure, never guess. Beats from the audio, positions from the debug overlay, colors from decoded pixels.
- Honest claims. Show only what the product does. The banned list is approved by the user before writing copy.
- Ask first before committing, pushing or publishing anything, and before every paid API call.
- No em or en dashes in any copy, file or message.
Workflow and approval gates
Each STOP is a hard gate: ask (AskUserQuestion), wait, and record the answer in the project's BRAND.md.
- Intake (required). Ask for 2 to 5 videos the user likes, one line each on what they like, including the sound.
Run
node scripts/intake/intake.mjs <project>/intake <videos...>and read every sheet. See references/intake.md. - Discovery. Learn the product: rules files, tokens (light and dark), components, logo, landing page, real screens and copy, claims. See references/discovery.md.
- Interview. The brief and the ingredients. See references/interview.md. Then:
- STOP: light or dark. Per film when there are several; a set mixes both if the product has both themes.
- STOP: banned claims. Show what the films will claim and the list of what they must never say (from the code, the site and the user). Wait for approval of both lists.
- Brand kit. Fill
templates/BRAND.mdinto the project. Every rule cites its source. - Music. Survey and measure candidates. STOP: music pick. See references/music.md.
- Story. Fill
templates/film-prompt.md; write the beat plan ascues.json. See references/story.md and references/ingredients.md. - Project.
node scripts/new-project.mjs <dir>,npm install. One kit insrc/kit/; one folder per film. See references/engine.md. - Storyboard. Build the scenes, render 5 to 8 stills per film (in the project:
node scripts/stills.mjs), tile them. STOP: storyboard approval before any full render. See references/review.md. - Render. In the project:
node scripts/render.mjs <Composition> out/<film>.mp4(safety built in). Contact sheet, look, fix. - Score. In the project:
sound/scores/<film>.pyfromcues.json;$PY sound/render.py <film>. See references/sound-rules.md. - Gate (mandatory). In the project:
$PY scripts/gate.py <film>. Nothing is called done until it passes. See references/render.md. - Deliver. Paths, lengths, loudness, peak, gate result, what changed. Keep every version.
The sync gate
- Whooshes are placed by their peak on the fastest frame of the move (
align="peak";kit/speed.tsfinds the fastest frame of a camera move; anE.outentrance is fastest at its start, anE.exitleave at its end). - Pops land on the frame the element lands. Chings on the frame the final number shows.
- Risers end on the hit (
align="end"). - Every sound carries a label naming its on-screen event.
- After every mix:
sound/check.py(no sound before its picture change),scripts/final-check.py(-14 LUFS within 1 LU, true peak -2 dBFS or lower, loudness range 4 LU or more, no silence, picture identical to the silent render, equal lengths) andscripts/verify.py, all run byscripts/gate.py. A flag is fixed by moving the sound (or the cue), never by exempting it without looking at its sheet.
Taste memory
references/base-rules.mdships with the skill: corrections from real films, as general rules.taste.md(git-ignored, fromtaste.example.md) is this machine's. Every new correction the user gives is written there as a general rule before you fix the film, phrased so it would have prevented the problem in any film. Read it at the start of every run.- A rule that holds across films can be promoted to
base-rules.mdby a pull request to this skill, never by a silent edit.
Safety (built into the scripts)
templates/project/scripts/safety.mjs, used by every bundle and render: free disk is checked first (10 GB minimum),
at most two renders run at once, temp bundles are deleted after every job and stale ones before. Render with
concurrency 1 on a machine short of memory. Stop only processes you started.
Optional modes
- Generated media. Only for what code cannot draw: real photos, photographic textures, cutouts, and filmed
backgrounds (silk, liquid, light) when the user wants a real filmed look.
scripts/gemini/image.mjstakes reference images so outputs match a chosen look, plus aspect, size, resize and chroma key;scripts/gemini/video.mjsmakes Veo clips from a palette-matched first frame (or native loops). Key fromGEMINI_API_KEYin the environment only; every call prints its cost and runs only after the user's yes. See references/gemini.md. - Media tools (free, any clip).
scripts/media/loop.pyturns a clip into a seamless background loop (seam search, exact dissolve, interpolation to the film's fps, loop plus poster plus still sequence plus boundary sheet);LoopBackgroundin the kit puts it under the motion layer from the film'scues.json.scripts/media/clip.pyprobes, re-encodes to the project's format, crops edges and extracts stills or a sheet.scripts/media/imgpost.pykeys and resizes images. - Refresh. When the user asks: re-study prompt-motion.com, skillry.dev and the awesome-opus5-5-videos repo for new entries and propose reference updates by PR. See references/refresh.md.
Quality floor (always)
- Only the product's own surfaces, colors, borders and shades. No invented panels or tints.
- Readable at the delivery size. Fewer words beat smaller words. Lines people must read reveal at about 0.2 s per word and hold 2 s or more.
- Every card, and the closing mark, wholly inside the frame for every frame of every move.
- Hold each shot 5 to 6 s with one slow push; when it feels busy, cut a screen instead of speeding up.
- Text is never covered by a cursor or chip, never crosses other text, never re-centers while it builds.
- Something happens on every beat; scene boundaries land on bars; a loop's last frame equals its first.
- In a set, no two films share a structure; anything kept side by side is centred exactly.
- No effects the product's language does not use: glows, particles, click rings, bouncy easing, shaders.
Knowledge
- references/method.md: how strong code-made films are built, engines, craft rules.
- references/prompt-lessons.md: how the best prompts are written.
- references/sound-rules.md: measured sound rules and the sync fix rules.
- references/pitfalls.md: disk, memory, render, code and sound failures and fixes.
- references/reference-videos.md: reference videos and what each teaches.
- references/base-rules.md: the shipped taste.
Traps that cost real time
- Remotion stills do not forward console logs: print measurements into the frame (
kit/debug.tsx). npx remotion stillre-bundles every call: usescripts/stills.mjs(one bundle, many frames).- Remotion's bundled ffmpeg has no
tmix,selectortile: use the system ffmpeg the doctor checked. - Color range: decode frame 0 of every deliverable and check it (
verify.py --bg); a limited-range master read as full range lifts dark backgrounds to gray. interpolateColorscannot parsecolor-mix(): hex for anything that animates.- Async image components can render empty in a frame: use Remotion
<Img>. - An index computed from time is -1 just before its section: clamp it (
safeIndex). will-changeon anything the camera scales blurs its text.- A word-reveal mask clips the last letters without padding: use
kit/components.tsxWordReveal. - Video decoding inside renders is unreliable: convert loops to image sequences.