agentleFS
puntorigenpuntorigen/avatar-skills/caption-word-reveal/SKILL.md

caption-word-reveal

Skill3 starsChanged 4 months agoMITView on GitHub

Word-by-word ("karaoke") burned-in captions for avatar reels: each word appears at the instant it's spoken, building up the SAME phrase unit in place (frozen layout, no reflow), and the phrase clears when the next one begins. Use when the user wants captions/subtitles where words form the sentence as the narration says them (word-by-word reveal, karaoke captions, "las palabras van apareciendo") on any reel produced by the avatar-reel-composer pipeline.

The file

We split this skill into the rules it gives an agent

3 rules. About 0 are common, 2 are distinctive, and 1 is very specific to this project.

  • ≈0

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈2

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 1

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Distinctive:

    If a polish pass (golden-flash / SFX) was applied, re-run it afterward so the effects sit on top of the freshly captioned video (see …

    line 53
  2. Distinctive:

    Frame-snapped timeline: Every reveal-state boundary is rounded to the fps grid and durations accumulate in whole frames, so the reveal …

    line 72
  3. Very specific:

    One lossless alpha overlay: All per-word states are baked into a SINGLE transparent qtrle (.mov) track via an ffconcat list and composited …

    line 76

≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

Caption word-by-word reveal

Karaoke-style captions for reels: instead of a whole phrase popping in at once, each aligned word appears the moment it's spoken, building the phrase up in place; already-spoken words stay lit and the phrase clears when the next phrase starts (same "replace" progression as the static captions).

This is already implemented in the avatar-reel-composer finishing pass (finish_reel.py) — this skill is how to apply/tune it and the invariants to keep. It is the default caption mode (caption_reveal="word").

When to use

  • The user wants captions where the words form the sentence as they're spoken ("palabra por palabra formando la frase", karaoke captions, word reveal).
  • Applying that look to a new reel, or re-captioning an already-finished reel without regenerating any video.

Requirements

  • A reel folder produced by compose_reel.py (has video_track.mp4, narration.mp3, reel_manifest.json).
  • Word-level timings at narration.align.json (faster-whisper alignment) — the reveal is driven by each word's start. Without it, captions are skipped.

How to apply

A) New reel — set it in the storyboard finish block

"finish": { "enabled": true, "subtitles": true, "caption_reveal": "word" }

Then compose normally; caption_reveal defaults to "word", so a finish block already gets the reveal unless you set "phrase".

B) Any existing reel — re-caption in place (no re-render of video)

python3 .cursor/skills/avatar-reel-composer/scripts/finish_reel.py <reel_dir> \
    --caption-reveal word --no-music

--no-music reuses the existing bed and only rebuilds the caption layer. Drop it (or add --music-prompt "…") to also (re)build music. Re-running is idempotent. To revert to static phrase-replace captions use --caption-reveal phrase.

If a polish pass (golden-flash / SFX) was applied, re-run it afterward so the effects sit on top of the freshly captioned video (see avatar-reel-composer Polish). Tune text with the same knobs as static captions: --max-words, --no-emphasis, --casing, --fontsize, --y-frac, --regular-font, --emph-font.

How it works (invariants — keep these when tuning)

The reveal reuses the SAME phrase units and setup/payoff styling as the static captions; only the presentation differs. Four properties keep it from looking janky — preserve them:

  1. Frozen layout, no reflow. The wrap, font size and every word's x/y are computed ONCE from the FULL phrase, then frozen. Drawing the first k words reproduces the head of the finished line — words never recenter or jump as they arrive. (_reveal_fit_fs locks the size with the static fit rule; _positioned_tokens freezes positions.)
  2. Replace, not accumulate. A phrase clears to blank only when the next phrase begins — the viewer never reads stale, not-yet/​already-spoken text stacked up.
  3. Frame-snapped timeline. Every reveal-state boundary is rounded to the fps grid and durations accumulate in whole frames, so the reveal can't drift against the frame-locked picture (same anti-drift discipline as the video assembly). Long reels stay in sync to the end.
  4. One lossless alpha overlay. All per-word states are baked into a SINGLE transparent qtrle (.mov) track via an ffconcat list and composited in one overlay pass — not ~hundreds of overlays. RLE + argb keeps the serif edges crisp. (build_reveal_track → overlay_reveal_track.)

Styling matches the static captions: serif (Georgia), subtitle casing (lowercase, intentional ALL-CAPS + accents kept, no trailing dot), white with a soft shadow/outline; the breath-group payoff is bold-italic.

Verify

Extract a few frames spanning a phrase and confirm words accrue left→right without the line shifting, and that the last words land in sync near the reel's end (where drift would show first):

ffmpeg -y -ss <t> -i <reel_dir>/final.mp4 -frames:v 1 /tmp/rev_check.png

Files (in the avatar-reel-composer skill)

  • scripts/finish_reel.py
    • _event_tokens — per-word display strings + spoken start times + payoff split.
    • _reveal_fit_fs / _positioned_tokens — lock font size + freeze full-phrase word positions.
    • render_reveal_state — render one state (first k words lit).
    • build_reveal_track — bake all states into one frame-snapped transparent qtrle track.
    • overlay_reveal_track — composite the track over the base video in one pass.
    • finish(..., caption_reveal="word"|"phrase") / CLI --caption-reveal (default word).
  • scripts/compose_reel.py — passes finish.caption_reveal through to finish().

See the avatar-reel-composer skill for the full finishing pass (caption phrasing, emphasis, music, polish).

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.