Caption Generator: Add Captions to Any Video (2026)
Upload → auto-generate → export as .srt or burn-in. With honest accuracy figures by video source and the FFmpeg styling reference nobody publishes.
force_stylereference for styling, honest accuracy figures by video source, and how to route the handful of “caption generator” searchers looking for Instagram post captions (a different tool) elsewhere.- 60 minutes free
- No credit card
- 99 languages
- Speaker labels
Last verified July 9, 2026
TL;DR — pick your path
| Your situation | Best path |
|---|---|
| Have a video, want captions on it | Upload to DeluxeScribe (free 60 min) |
| Need soft captions (viewer toggles on/off) | Export .srt → attach to video (FFmpeg one-liner) |
| Need burned-in captions (Instagram, TikTok) | Export .srt → burn-in with FFmpeg subtitles filter |
| Video over 5 GB | Strip audio first, transcribe audio-only, then attach captions |
| Want captions in translated language | Transcribe → translate .srt (watch length differential) |
| Looking for Instagram/LinkedIn post captions | Different tool category — see bottom of page |
How to add captions to a video (3 steps)
- Upload — drop your video (MP4, MOV, WebM, MKV, and more) into DeluxeScribe. Files up to 5 GB.
- Auto-generate — captions are generated automatically with timestamps synced to the video clock. Language auto-detects on the first ~30 seconds; you can override.
- Export or burn-in — download as SRT or WebVTT (soft captions, viewer toggle) or use the FFmpeg commands below to burn captions into the video permanently.
Caption vs subtitle vs SRT — quick disambiguation
These three words are used interchangeably in casual speech but mean different things in production and accessibility contexts.
| Term | What it is | When to use |
|---|---|---|
| Caption | On-screen text that includes dialogue plus non-speech audio (music cues, sound effects). Intended for accessibility. | Accessibility compliance, deaf/HoH audiences |
| Subtitle | On-screen text for dialogue only, historically for translation to another language. | Foreign-language films, translated content |
| SRT (.srt) | A file format — SubRip subtitle text — that carries either captions or subtitles as timed text. | Universal caption/subtitle file format |
| Closed captions (CC) | Captions the viewer can toggle on/off. | YouTube, streaming platforms, broadcast |
| Open captions (OC) | Captions permanently burned into the video, cannot be toggled off. | Instagram, TikTok, silent-scroll social |
Full explainer on the accessibility distinctions: What Is Closed Captioning?
Soft captions vs burned-in — pick the right one
Soft captions (recommended for accessibility)
The caption file is embedded as a separate track inside the video container. The viewer toggles them on or off. Works for YouTube, Vimeo, Premiere delivery, streaming platforms.
ffmpeg -i video.mp4 -i captions.srt -c copy -c:s mov_text output.mp4
-c copy keeps the video and audio streams untouched (no re-encode). -c:s mov_text converts the SRT to the MOV Text format required inside an MP4 container. Instant, no quality loss.
Burned-in captions (required for social)
Captions are permanently rendered into the picture. Required for Instagram, TikTok, Facebook, and any platform that doesn’t support subtitle tracks.
ffmpeg -i video.mp4 -vf subtitles=captions.srt output_burned.mp4
This re-encodes the video (takes longer). For control over font, size, color, position, add force_style — see the styling section below.
Decision table
| Use case | Recommended approach |
|---|---|
| YouTube upload | Soft — upload .srt in Studio, YouTube renders |
| Vimeo | Soft — upload .srt in video settings |
| Instagram Reel / TikTok | Burned-in — platform doesn’t read soft subs |
| LinkedIn video | Burned-in recommended (native auto-captions unreliable) |
| Presentation / conference talk export | Burned-in — no way to know playback environment |
| Streaming platform delivery (Netflix, Prime) | Soft — separate .srt or .vtt required by spec |
Styling captions — full force_style reference
FFmpeg’s subtitles filter accepts a force_style parameter that overrides the default caption appearance. Nobody publishes this cheat sheet cleanly, so here it is.
Basic syntax
ffmpeg -i video.mp4 -vf "subtitles=captions.srt:force_style='FontName=Inter,FontSize=24,PrimaryColour=&H00FFFFFF,OutlineColour=&H80000000,BorderStyle=3,Outline=1,Shadow=0,MarginV=40'" output.mp4
force_style parameters
| Parameter | Purpose | Example |
|---|---|---|
FontName | Font family (must be installed on the system) | Inter, Arial, Roboto |
FontSize | Caption font size in points | 24, 36 for 1080p |
PrimaryColour | Text color as &HAABBGGRR (BGR, not RGB, with alpha first) | &H00FFFFFF = white, &H0000FFFF = yellow |
OutlineColour | Outline/background color, same format as above | &H80000000 = 50% black |
BorderStyle | 1 = outline+shadow, 3 = opaque box behind text | 3 for social media legibility |
Outline | Outline thickness in pixels | 1–3 |
Shadow | Shadow depth in pixels | 0 disables shadow |
MarginV | Vertical margin from bottom of frame | 40, 60 for safe area |
Alignment | 1=bottom-left, 2=bottom-center, 8=top-center | 2 is default |
Bold | 1 = bold, 0 = normal | 1 for social |
Preset styles for common platforms
Instagram Reel / TikTok (bold, centered, large)
force_style='FontName=Inter,FontSize=32,Bold=1,PrimaryColour=&H00FFFFFF,OutlineColour=&H80000000,BorderStyle=3,MarginV=100,Alignment=2'
YouTube (subtle, standard subtitle style)
force_style='FontName=Roboto,FontSize=22,PrimaryColour=&H00FFFFFF,OutlineColour=&H80000000,BorderStyle=1,Outline=1,MarginV=40'
Cinematic (yellow classic subtitles)
force_style='FontName=Arial,FontSize=24,PrimaryColour=&H0000FFFF,OutlineColour=&H00000000,BorderStyle=1,Outline=2,MarginV=30'
Colour format gotcha: FFmpeg uses &HAABBGGRR where AA is alpha (00 = opaque), BB is blue, GG is green, RR is red — backward from typical web hex codes. Yellow is &H0000FFFF, not &H00FFFF00.
Accuracy by video source
The video container has no effect on caption accuracy — it’s entirely the audio inside it. Common video sources with typical Word Error Rate (WER):
| Source | Typical WER | Notes |
|---|---|---|
| Screen recording, close mic | 2–5% | Cleanest signal; light proofreading |
| Zoom / Teams export | 5–12% | Compression + mixed mics |
| Webcam, USB mic | 5–12% | Room reverb adds error |
| Smartphone video (indoor) | 8–18% | Omnidirectional mic picks up room |
| Phone video (outdoor/wind) | 20–40% | Wind noise dominates |
| Music-heavy video | Often fails | Model may hallucinate lyrics or skip |
For the full WER breakdown by language and Whisper model size, see How Accurate Is Whisper.
Language support — the honest picture
DeluxeScribe supports 99 languages, but performance varies across them. Same story on every AI captioning tool — nobody achieves equal accuracy in Bengali as in English.
| Tier | Languages | Typical accuracy |
|---|---|---|
| Excellent | English, Spanish, French, German, Portuguese, Italian, Dutch | 95–98% on clean audio |
| Very good | Japanese, Korean, Chinese (Mandarin), Russian, Polish | 90–95% on clean audio |
| Good | Arabic, Hindi, Turkish, Vietnamese, Thai, Ukrainian | 85–92% on clean audio |
| Variable | Less-resourced languages (Bengali, Swahili, Punjabi, etc.) | 60–85%, depends heavily on speaker + condition |
For translated captions (audio in one language, captions in another), transcribe first in the source language, then translate the .srt with DeepL, Google Translate, or an LLM. Watch the length differential — German is ~30% longer than English, French ~15% longer, which breaks caption timing unless you adjust.
Common failures
Caption timing drifts on long videos
Variable frame rate (VFR) videos — common from smartphones — cause timestamps to drift. Convert to constant frame rate before captioning:
ffmpeg -i input.mp4 -vf fps=30 -c:a copy output_cfr.mp4
Wrong language auto-detected
Auto-detection reads the first ~30 seconds. If the video opens with a different language than the main content, set the target language manually.
Missing captions during background music
Heavy music drowns out speech. Source clean audio before mixing, or use vocal isolation (Ultimate Vocal Remover, Krisp) before uploading.
Emoji and special characters break force_style
FFmpeg’s subtitle filter can’t render most emoji or unusual Unicode without a font that includes them. Use an emoji-capable font (Twemoji Mozilla, Noto Color Emoji) or strip emoji from the .srt before burn-in.
Captions too small on vertical video
Default FontSize is calibrated for landscape. For 1080×1920 vertical video, use FontSize=36 or larger and MarginV=100 to keep captions above the platform UI overlay.
Not what you’re looking for?
“Caption generator” also means writing Instagram/LinkedIn post captions— text that goes in the post body, not on the video. That’s a different tool category (LLM writers, hook generators). We don’t do that here.
If you need social-media post copy: try Hootsuite’s AI caption generator, Ahrefs’ Instagram caption generator, or an LLM (ChatGPT, Claude) with a template prompt.
What we do here: generate captions on the video itself — from the audio track — for YouTube, streaming, silent-scroll social, and accessibility compliance.
How this page was verified
Related guides
- Automatic CaptionsYouTube vs Zoom vs Teams built-in auto-captions compared to dedicated tools.
- What Is Closed Captioning?Closed vs open captions vs subtitles, legal requirements, and file formats.
- SRT GeneratorSRT file specifics — subtitle timing rules, format spec, and edge cases.
- Video to SRTFull video → .srt workflow — extract, attach, burn-in for Premiere/DaVinci/CapCut.
- Audio to SRTAudio-first subtitle workflow — Podcasting 2.0 publishing included.