2026-10-26 · 5 min read

An ffmpeg drawtext Alternative for Styled Captions: One API Call Instead of a Filter Graph

Every developer who needs captions on video eventually lands on ffmpeg's drawtext filter. It works, in the sense that text appears on the video. Everything else is on you: transcription, word-level timing, line breaking, positioning, fonts that render the same on every machine, and the animated word-by-word styles that perform on short-form platforms. By the time the filter graph does what a modern caption tool does, you have written a caption product inside a shell script.

caption.sh is the alternative for the common case: you want word-timed, styled captions burned into the video, and you do not want to own the pipeline. POST the video URL and a style, poll the job, download the finished MP4. One call replaces transcription, timing, layout, and rendering.

What drawtext makes you build yourself

  • Transcription. drawtext renders text you give it. It does not listen to the audio, so you need a speech-to-text step before ffmpeg even enters the picture.
  • Word timing. Karaoke-style captions need a timestamp per word. Getting that out of a transcriber, aligned, and into drawtext's enable expressions is a project on its own.
  • Styling that matches. Fonts, outlines, shadows, and per-word highlight colors in drawtext depend on what is installed on the machine running the encode. caption.sh renders the same style every time, with fonts like inter, roboto, or luckiest-guy built in.

The same job as an API call

curl https://api.caption.sh/v1/jobs \
  -H "Authorization: Bearer $CAPTION_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "video_url": "https://cdn.example.com/clip.mp4",
    "style": {
      "font": "inter",
      "animation": "word-highlight",
      "position": "bottom"
    }
  }'

# poll until done, then follow the signed URL
# GET /v1/jobs/{id} -> { "status": "done", "result_url": "..." }
# the result is a 302 redirect to the finished MP4

The output is a new MP4 with the captions burned into the pixels. That is a deliberate choice: burned-in captions render identically on TikTok, YouTube, Instagram, and every player, with no subtitle track support required. The trade-off is that there is no separate SRT or VTT export; if you need an editable sidecar file, drawtext or a subtitle editor is still the right tool.

ffmpeg is the right answer when you need full control over the encode and you are prepared to build the caption layer yourself. When the goal is simply captioned video out the other end, an API that does transcription, timing, styling, and burn-in for $0.10 per minute is a lot less pipeline to maintain. Get a key at caption.sh and run one clip through to compare.

Back to all articles