Captions
The goal: captions a viewer reads without effort. Each one is a short, complete piece of meaning, timed to the exact word, sitting in the same spot all video.
This is step 5 of the editing order: a-roll cut, b-roll, framing, headline, captions. It runs on the framed video, after the headline, so captions can stay out of the headline's way.
This skill is built for Claude Code and Runneth.
Before you start: the tools
In Runneth, everything is already installed: skip this section.
In Claude Code, this skill needs the free video tools the video-editing-setup skill installs. Check quietly that ~/.video-editing-tools/bin/ffmpeg -version runs. If it does, use the tools in ~/.video-editing-tools/bin (ffmpeg, ffprobe, python) wherever this skill says ffmpeg, ffprobe or python3, and carry on. If it doesn't, follow the video-editing-setup skill first, then come back here.
The font: Figtree Bold, the only font this skill uses. It's a free Google font. Check quietly whether it's on the computer or in a fonts folder next to the project. If it isn't, ask: "This uses Figtree, a free Google font. Want me to download it for you?" On yes, download the Figtree Bold file from Google Fonts (fonts.google.com/specimen/Figtree) into a fonts folder next to the project, and carry on. This check applies in Runneth too.
What it needs
- The video, framed and with the headline on (or its timing).
- The script, if there is one, so names and product words are spelled right.
- When the headline is on screen and where it sits.
Step 0: Ask about the style first
Ask these one at a time, waiting for each answer:
- "Do you want captions one word at a time, or a few words at a time?"
- Only for a few words at a time: "Do you want the word being said to light up in a different colour?"
- Only if yes: "Which colour?" Offer bright yellow (#FFFF3A) as the default, or their brand colour.
Step 1: Get every word with its time
- Transcribe the video's own sound with word timings (faster-whisper
base,word_timestamps=True,vad_filter=False). The timings must come from this exact video, because every cut moves them. - Use the script's spelling for names, brands and product words, and keep the transcript's timing.
- Every spoken word gets a caption. Nothing that wasn't said gets one.
Step 2: Split into chunks by meaning (a few words at a time only)
- Usually 1 to 3 words a chunk, up to about 5 when that keeps a phrase whole and it still fits the width.
- Keep together: a noun with its describing words ("a sleep drink"), names ("Claude skill"), a verb with its little words ("go to bed"), and short complete thoughts ("but that's how I felt").
- Each chunk ends on a word that carries meaning. Little words (the, a, of, to, and, because, that, I) start the next chunk instead.
- Each chunk shows from its first word until the next chunk starts, so the screen never flashes empty mid-sentence.
- Read the whole list once like a viewer and fix any break that reads awkwardly.
Step 3: The look
Every caption uses Figtree Bold, white, with a black outline. No box, no shadow, no pop-in or bounce: captions just appear. Mostly lowercase, with I, names and brands capitalised, and no full stops or commas at the end.
- One word at a time: about 140px with a 6px outline, one word on screen at a time. Each word stays until the next one starts. A long word shrinks to fit about 720px wide. Skip the chunking in Step 2.
- A few words at a time: about 60px with a 3px outline, using the chunks from Step 2.
- With the word lighting up: the word being said changes to the chosen colour inside the chunk, karaoke style.
- Without: the whole chunk stays white.
Step 4: Where they sit
- Centred, at chest height, about y 1260 to 1305 in a 1080x1920 video: below the chin, above the app's caption and buttons.
- Inside the safe area: The safe zones come from the post-preview skill: keep everything inside x 100 to 880, y 290 to 1340 on a 1080x1920 frame (the one box that's safe on Reels, Stories, Feed, TikTok and Facebook). Check post-preview for a placement's exact covered areas when something runs close to an edge. Centred captions therefore keep every letter (outline included) within x 200 to 880, which is about 680px wide, and above y 1340. Measure each chunk's width; a chunk too wide gets split.
- Clear of the headline. While the headline is on screen, captions sit below it with a clear gap; when the headline sits low, captions move down within the safe area rather than overlapping it.
- The same spot all video, so the eye always knows where to look.
- Captions sit below the mouth, never across the face. Every caption clears the eyes, nose and mouth. When the face sits so low that the caption spot would cover it, the framing is what's wrong: send it back to framing to fix (or move the caption down within the safe area while it's fixed).
Step 5: Build and burn
- Write the captions as an ASS subtitle file. With the word lighting up, use one event per word so the colour moves with the speech. Letter spacing goes in an inline
\fsptag. - Point the renderer at a fonts folder holding only the Figtree Bold file, so the right weight is used:
ass=captions.ass:fontsdir=fonts. - Burn in one pass from the full-quality video (x264, slow, crf 14 to 18), sound copied untouched.
Step 6: Check before anyone sees it
- Every word, once, on time: compare the caption list to the transcript word for word.
- A frame from every chunk: inside the safe area, nothing cut off, nothing overlapping the headline, and the whole caption below the mouth. Use a face detector or read each frame; a caption across any part of the face fails the check.
- With the word lighting up, the colour lands on the word being said, checked at a few points through the video.
Step 7: Learn from the editor
When the editor changes a split, a word or the look, ask why (unless they said). Write the reason as a rule in "Caption rules from the editor" below, worded as what should be true. Reasons you came up with yourself are marked "(AI)" and never change the rules.
Caption rules from the editor
(Empty to start. Add each rule the editor gives.)