How to Add Subtitles to Video with FFmpeg

You need captions on your video. Maybe it's for accessibility, maybe TikTok and Instagram penalize uncaptioned content in their algorithms, or maybe you just want your audience to watch with the sound off. Whatever the reason, you're going to reach for FFmpeg.
And then you'll spend an hour fighting with filter syntax.
Adding Subtitles with FFmpeg CLI
FFmpeg supports two main approaches for burning subtitles into video: the subtitles filter (for SRT/ASS files) and the drawtext filter (for simple text overlays). The subtitles filter is what you want for actual captions.
Assuming you have an SRT file ready, the basic command looks like this:
ffmpeg -i input.mp4 -vf "subtitles=captions.srt" -c:v libx264 -crf 23 -c:a aac output.mp4
That works. But the moment you need to customize font size, color, or positioning, you're writing ASS override tags inside your SRT file or converting to ASS format entirely:
ffmpeg -i input.mp4 -vf "subtitles=captions.srt:force_style='FontSize=24,PrimaryColour=&H00FFFFFF,OutlineColour=&H00000000,Outline=2'" -c:v libx264 -crf 23 -c:a aac output.mp4
That single line is already hard to read. Add font paths (which differ between Linux, macOS, and Windows), character encoding issues, and the fact that FFmpeg silently fails on malformed SRT files, and you've got a debugging session ahead of you.
If you only need to process a handful of videos on your own machine, the CLI approach is fine. But if you're building a product that captions videos at scale, you don't want this running on your server.
Burning Subtitles via the FFmpeg Micro API
FFmpeg Micro wraps FFmpeg's subtitle capabilities into a REST API. You send your video and subtitle file, specify the filter, and get back a captioned video. No server, no font path issues, no dependency management.
The approach uses the filters field on the /v1/transcodes endpoint. You provide your video and SRT file as inputs, then apply the subtitles filter:
curl -X POST https://api.ffmpeg-micro.com/v1/transcodes \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"inputs": [
{"url": "https://storage.example.com/video.mp4"},
{"url": "https://storage.example.com/captions.srt"}
],
"outputFormat": "mp4",
"filters": [
{"filter": "subtitles=captions.srt"}
]
}'
Both files get downloaded and processed together. The subtitles filter references the SRT file by name, and FFmpeg burns the captions directly into the video frames.
You can style the subtitles the same way you would with CLI, using the force_style parameter:
curl -X POST https://api.ffmpeg-micro.com/v1/transcodes \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"inputs": [
{"url": "https://storage.example.com/video.mp4"},
{"url": "https://storage.example.com/captions.srt"}
],
"outputFormat": "mp4",
"filters": [
{"filter": "subtitles=captions.srt:force_style=FontSize=28,PrimaryColour=&H00FFFFFF"}
]
}'
The response gives you a job ID. Poll GET /v1/transcodes/{id} until the status is completed, then grab the output with GET /v1/transcodes/{id}/download.
Simple Text Overlays Without an SRT File
Sometimes you don't need timed captions. You just need a line of text burned into the video, like a watermark, a title card, or a call-to-action. FFmpeg Micro has a virtual option for that.
The @text-overlay option lets you add styled text without writing any FFmpeg filter syntax:
{
"inputs": [
{"url": "https://storage.example.com/video.mp4"}
],
"outputFormat": "mp4",
"options": [
{
"option": "@text-overlay",
"argument": {
"text": "Subscribe for more tips",
"style": {
"position": "bottom-center",
"fontSize": 48,
"fontColor": "#FFFFFF",
"outlineThickness": 2
}
}
}
]
}
Behind the scenes, this generates an ASS subtitle file with your text and styling, then applies the subtitles filter. You get clean, anti-aliased text without touching any FFmpeg syntax.
SRT File Format Quick Reference
If you're generating SRT files programmatically (which you probably are if you're reading this), the format is simple:
1
00:00:01,000 --> 00:00:04,000
Welcome to this tutorial.
2
00:00:04,500 --> 00:00:08,000
Today we're covering video captions.
3
00:00:08,500 --> 00:00:12,000
Burned-in subtitles work everywhere.
Each block has a sequence number, a timestamp range with comma-separated milliseconds (not periods), and the text. Blank line between blocks. UTF-8 encoding. That's it.
If you're using a speech-to-text service like Whisper, Deepgram, or AssemblyAI, they can output SRT directly. Pipe that into the FFmpeg Micro API and you've got an automated captioning pipeline.
Automating Captions at Scale
The real value of an API-based approach shows up when you're processing more than a few videos. A typical automation flow:
- Video gets uploaded to your app
- Speech-to-text service generates an SRT file
- Your backend sends both files to FFmpeg Micro's
/v1/transcodesendpoint - Poll for completion or use a webhook
- Download the captioned video and serve it to your users
You can wire this up with n8n, Make.com, or just a simple script. The point is that you're not managing FFmpeg installations, font dependencies, or scaling infrastructure.
FFmpeg Micro has a free tier, so you can test this entire flow without paying anything. Sign up and grab an API key to try it with your own videos.
You might also like

How to Add Text to Video with FFmpeg (CLI and API)
Learn two ways to add text overlays to video: FFmpeg drawtext filter for CLI and FFmpeg Micro @text-overlay API for automation.

How to Use FFmpeg with n8n for Video Editing Workflows
Step-by-step tutorial for building automated video editing workflows in n8n using FFmpeg Micro API. Covers transcoding, resizing, watermarks, and batch processing.

How to Transcode Video with an API (Skip the FFmpeg Server Setup)
Learn how to add video transcoding to your app with a simple API instead of managing FFmpeg servers, job queues, and scaling infrastructure.
Ready to process videos at scale?
Start using FFmpeg Micro's simple API today. No infrastructure required.
Get Started Free