Auto captions skill for Claude Code, free and MIT licensed: Auto Captions Skill lets your agent add captions to your videos on your own computer. It transcribes the speech with a time for every word, proofreads names and numbers before anything is burned in, renders creator-style captions in the shape each app wants, writes SRT and VTT subtitle files, and translates the captions with the same timing. It also works in Codex, Cursor and OpenClaw.
There is no watermark, no per-minute limit and no paid API. Transcription runs locally with faster-whisper (or mlx-whisper on Apple Silicon), and the captions are drawn with Pillow and encoded with ffmpeg. This post covers what it does, the example in the repo, and the parts that are code.
npx skills add social-media-skills/auto-captions-skill -g -a claude-code -y Repo: github.com/social-media-skills/auto-captions-skill
From the example in the repo: two clips of NASA astronaut Nichole Ayers on the International Space Station, captioned in English and Spanish (NASA footage, no endorsement implied).
Where auto captions go wrong
A caption generator gets most words right and the important ones wrong. Names, brands and numbers are what speech engines mishear, and they drop commas, which decide where a caption breaks. A misspelled name burned into a video can't be fixed after posting. Then the captions sit under the app's buttons, split "9 or 10 minutes" across two screens, and nobody gets a subtitle file for accessibility.
The agent you already use is a good proofreader. So the skill splits the work: scripts do the timing, chunking and rendering; the agent reads every line and fixes what the engine got wrong.
What the skill does
- Asks where the videos will go, which names must be spelled right, and which languages.
- Transcribes with
transcribe.py: every word with its time. - Proofreads with
fix.py: a report of unsure words and near-misses of your names; the agent writes the corrections, and every unchanged word keeps its time. - Writes subtitle files with
captions.py: SRT, VTT and a plain transcript. - Shows the styles on a frame of your own video with
styles.py. - Shows a review sheet with
render.py --preview, with each app's buttons drawn on. - Renders every video in every shape and language.
- Plans the posts if you want, and schedules them only after one clear yes.
Install
Claude Code:
npx skills add social-media-skills/auto-captions-skill -g -a claude-code -y Codex, Cursor and other agents: npx skills add social-media-skills/auto-captions-skill, then pick your agent. OpenClaw: openclaw skills install @social-media-skills/auto-captions-skill. GitHub CLI: gh skill install social-media-skills/auto-captions-skill auto-captions-skill. Gemini CLI: gemini extensions install https://github.com/social-media-skills/auto-captions-skill.
It needs Python 3.9+ with Pillow, ffmpeg, and one way to transcribe: pip install faster-whisper is free. scripts/check_setup.py tells you what's missing and prints the install command for your system.
The example
The prompt:
Add captions to clips/intro.mp4 and clips/speed.mp4 for TikTok, Reels and Shorts, a 16:9 version for YouTube, a 4:5 version for LinkedIn, and a Spanish version. Her name is Nichole Ayers.
The agent writes a job file (videos, vocab, translations, outputs) and runs the scripts. Transcribing both clips took 19 seconds on a laptop after the one-time model download. The raw transcript of the first clip, as faster-whisper heard it:
L1 [00:00.0-00:06.8] Hey everyone, I'm NASA astronaut Nichole Ayers and welcome aboard the International Space Station We're orbiting the Earth 16 times every single day It dropped the word "where" and most commas. The agent's fixes.json puts them back and picks the words to colour:
{ "lines": {"1": "Hey everyone, I'm NASA astronaut Nichole Ayers, and welcome aboard the International Space Station, where we're orbiting the Earth 16 times every single day."}, "emphasis": ["16 times"] } One more detail from the example: NASA's own subtitle file for this video spells her name "Nicole". The captions use "Nichole", as on the name title in the video. That's the kind of thing only a proofreading step catches.
The second clip's subtitle file, as captions.py wrote it:
4 00:00:08,500 --> 00:00:09,597 So we'll actually only have 5 00:00:09,680 --> 00:00:11,557 about 9 or 10 minutes of good radio contact "9 or 10 minutes" stays on one line. Cues are at most 2 lines of 42 characters, last 5/6 of a second to 7 seconds, and break at punctuation.
The review sheet
Before anything is rendered, render.py --preview writes a sheet: three moments per version, and on the vertical ones the same frame with TikTok's, Reels' and Shorts' buttons drawn on. No app publishes a safe zone for normal posts, so the skill draws the buttons and you check that the captions miss them, the face and any name title. You move them with position and the crop with focus_x.
Styles are JSON
The 8 presets (pop, bold, highlight, reveal, lines, clean, minimal, one-word) are plain JSON files. pop, the default for vertical video:
{ "font": "Poppins-ExtraBold.ttf", "size": 84, "color": "#FFFFFF", "active": "#FFD43B", "keyword": "#4ADE80", "stroke": 9, "words": 3, "chars": 18, "lines": 1, "pause": 0.3, "position": 0.62 } active is the spoken word, keyword the emphasis words from fixes.json, pause the silence that starts a new caption. Change any of it per output with style_overrides, or copy a preset into your project as your brand style. Captions are drawn with Pillow, so any ffmpeg build works: it needs no subtitle library.
Translations keep the timing
For each language, captions.py writes a template with one entry per cue of the original: i, start, end, source and an empty text. The agent fills in text; the times never change, so the translation stays in sync. From the Spanish file:
{"i": 5, "start": 9.68, "end": 11.557, "source": "about 9 or 10 minutes of good radio contact", "text": "unos 9 o 10 minutos de contacto por radio"} The script warns when a translation reads faster than about 20 characters per second. The first English cue, "We won't have a lot of time to talk,", is on screen for 1.3 seconds; the agent shortened the Spanish to "No tendremos mucho tiempo,". Units are converted for the audience (17,500 miles an hour became 28 000 km/h). Translated versions show whole captions without the moving word highlight, because a translation has no spoken word to follow.
Subtitle files, and what posting can carry
Burned-in captions can't be resized or read aloud, so every video also gets an SRT, a VTT and a transcript. TikTok and Instagram take no subtitle file through their APIs, which is why the skill burns captions in. YouTube and Facebook let you add one; plan.md says where.
Posting is optional. post_plan.py checks every file against each platform, plans one post a day per account at most, and writes plan.md, which works by hand. To have the agent schedule it, the skill uses WoopSocial's social media MCP, made by the team that maintains the skill. It posts the video and the post text; it doesn't attach subtitle files or change the video. The free plan covers 2 social accounts, no card.
Try it
npx skills add social-media-skills/auto-captions-skill -g -a claude-code -y Then tell your agent "add captions to this video for TikTok and Reels" and give it the names that must be spelled right. Rendering takes one to three times the video's length per output, depending on the computer. The repo is social-media-skills/auto-captions-skill. Issues and pull requests are welcome.



