2026-09-27 · 8 min read
Karaoke captions API: word-by-word highlight captions, rendered for you
Open any short-form feed and the dominant caption style is karaoke: a few words on screen at a time, with the word being spoken right now lit up in a different color. It reads effortlessly, it keeps eyes on the video, and it has quietly become the default look for talking-head clips, podcast cuts, and UGC ads.
This post is about what makes that style tick, why it is fundamentally a timing problem, and how to produce it at volume through an API instead of an editor.
Karaoke captions are a timing problem, not a styling problem
Regular subtitles are timed per cue: a sentence or two appears, hangs on screen, and disappears. Karaoke captions need something much finer - the exact start and end of every single word. The whole effect rests on the highlight landing on the syllable as it is spoken. When the timing drifts by even a couple hundred milliseconds, the effect flips from satisfying to broken.
That requirement is why the karaoke look cannot ride along in a subtitle file. WebVTT and TTML (both W3C specs) time cues, not words, and the player owns the styling. There is no standard way to say "color this one word differently at this moment", and even if there were, every social platform would ignore it. Burning the captions into the pixels is the only way the effect survives a repost, a re-encode, or a download.
How an API produces the karaoke look
caption.sh starts from a speech-to-text pass that returns word-level timestamps, groups the words into caption blocks, and renders the styled result straight into the video. The karaoke behavior is a handful of fields in the options object:
{
"max_words": 2,
"max_lines": 1,
"highlight": true,
"highlight_color": "#00E676",
"decoration": "backdrop",
"backdrop_radius": "rounded",
"position": "center"
}max_words is the heart of it: one to three words per group is what makes captions feel like karaoke instead of a transcript. highlight (on by default) recolors the active word as it is spoken, and highlight_color picks that color (default #00E676). decoration decides how the text stays legible on any footage - an outline stroke, a filled backdrop box, or nothing - and position can be top, center, bottom, or an exact fraction of frame height.
Tuning the feel
- max_words: 1 is the aggressive word-at-a-time punch; 2 to 3 reads calmer. "auto" packs as many words as fit the wrap budget and stops feeling like karaoke.
- max_lines: 1 keeps the block on a single line, which suits the karaoke rhythm.
- font: luckiest-guy gives the loud creator look; inter or roboto read more product-demo. 18 fonts are bundled, so there is nothing to install or license.
- max_tilt: a small random rotation per caption for the hand-placed look; 0 keeps everything straight.
- position: center is the classic karaoke placement; bottom with a backdrop box reads more traditional.
One sizing detail worth knowing: font size is a fraction of the video height, not pixels. The same options produce proportionally identical captions on a vertical Short, a square feed post, and a landscape clip, which removes a whole class of per-aspect-ratio bugs.
Running it at volume
The API is async: one POST creates a job, you poll or take a webhook, and you download a finished MP4. That shape means a pipeline can caption every clip it produces with no human in the loop. Billing is prepaid at $0.10 per minute of video, debited only for successful renders, so a failed job never costs anything.
If your pipeline is an agent rather than a script, caption.sh also runs a hosted MCP server at https://mcp.caption.sh/mcp. Clients like Claude and Cursor get caption_video as a native tool, and the nine built-in style recipes cover the karaoke look, so the agent can pick a style by name instead of tuning JSON.
See it before you build
The playground on caption.sh is the fastest way to judge the effect: drop a clip, set max_words to 2, watch the preview. When it looks right, the same options JSON goes straight into your API calls. The full field reference lives at caption.sh/docs.