How to Add Text to Video with FFmpeg (CLI and API)

You want to burn text into a video. Maybe it's a caption, a title card, or a watermark. FFmpeg can do it, but the drawtext filter syntax is notoriously painful to get right.
This post covers two approaches: raw FFmpeg CLI for when you need full control, and the FFmpeg Micro API for when you want to skip the hassle.
The drawtext Filter (CLI Approach)
FFmpeg's drawtext filter is the standard way to add text to video from the command line. A basic example:
ffmpeg -i input.mp4 \
-vf "drawtext=text='Hello World':fontsize=48:fontcolor=white:x=(w-text_w)/2:y=(h-text_h)/2" \
-c:a copy output.mp4
This centers "Hello World" on every frame of the video. The x and y parameters use FFmpeg expressions where w is video width, h is video height, and text_w/text_h are the rendered text dimensions.
Positioning Text
Common positions you'll use:
# Bottom center (good for captions)
drawtext=text='Caption text':x=(w-text_w)/2:y=h-th-40:fontsize=36:fontcolor=white
# Top left (good for watermarks)
drawtext=text='My Brand':x=20:y=20:fontsize=24:fontcolor=white@0.7
# Bottom right with padding
drawtext=text='@handle':x=w-tw-20:y=h-th-20:fontsize=28:fontcolor=white
The @0.7 after the color sets opacity. Useful for watermarks you don't want to dominate the frame.
Adding a Background Box
Raw white text on video is hard to read. Add a semi-transparent box behind it:
ffmpeg -i input.mp4 \
-vf "drawtext=text='Subscribe':fontsize=40:fontcolor=white:x=(w-text_w)/2:y=h-th-60:box=1:boxcolor=black@0.6:boxborderw=10" \
-c:a copy output.mp4
boxborderw=10 adds 10 pixels of padding around the text inside the box.
The Pain Points
If you've worked with drawtext before, you know the frustrations:
- Special characters break everything. Colons, quotes, and backslashes need careful escaping. A colon in your text will silently break the filter chain.
- Long text doesn't wrap. You have to manually split lines and position each one separately.
- Font management is a mess. You need fonts installed on the server, and the path varies by OS. What works on your Mac won't work on your Linux server.
- No easy way to style. Want an outline around your text? That's a separate
drawtextcall composited under the first one. Want word wrapping? You're doing math.
For a one-off video, these are minor annoyances. For an automated pipeline processing hundreds of videos, they become real problems.
The API Approach (FFmpeg Micro)
FFmpeg Micro's @text-overlay virtual option handles all of this with a single API call. No FFmpeg installation, no font management, no escaping issues.
curl -X POST https://www.ffmpeg-micro.com/v1/transcodes \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"inputs": [{"url": "https://your-bucket.s3.amazonaws.com/input.mp4"}],
"outputFormat": "mp4",
"options": [
{
"option": "@text-overlay",
"argument": {
"text": "Your caption text goes here. It can be as long as you want and it will wrap automatically.",
"style": {
"position": "bottom-center",
"fontSize": 48,
"fontColor": "#FFFFFF",
"outlineThickness": 3,
"textWidth": 800
}
}
}
]
}'
That's it. The API handles text wrapping, font rendering, outline generation, and proper positioning. No filter string escaping. No font path issues.
Available Positions
The position parameter accepts nine presets: center, top-left, top-center, top-right, middle-left, middle-right, bottom-left, bottom-center, bottom-right.
Need pixel-perfect placement? Use x and y instead:
{
"option": "@text-overlay",
"argument": {
"text": "Custom positioned text",
"style": {
"x": "0.15*w",
"y": "(h-text_h)/2",
"fontSize": 60,
"fontColor": "#FFFFFF"
}
}
}
The x and y fields accept FFmpeg expressions, so you can use the same positioning logic you already know from the CLI.
Styling Options
The full set of style parameters:
fontSize(number) - font size in points, defaults to 48fontColor(string) - hex color like#FFFFFFor named colors likewhite,redoutlineThickness(number) - stroke width in pixels around the textmargin(number) - padding from video edges in pixelstextWidth(number) - maximum width before text wraps
Combining Text with Other Transformations
In practice, you rarely just add text. You're also resizing, re-encoding, or adjusting quality. With the CLI, that means chaining filters:
ffmpeg -i input.mp4 \
-vf "scale=1280:720,drawtext=text='My Caption':fontsize=36:fontcolor=white:x=(w-text_w)/2:y=h-th-40" \
-c:v libx264 -crf 23 -c:a aac output.mp4
With the API, you just add both options to the same request:
{
"inputs": [{"url": "https://your-bucket.s3.amazonaws.com/input.mp4"}],
"outputFormat": "mp4",
"preset": {"quality": "medium", "resolution": "720p"},
"options": [
{
"option": "@text-overlay",
"argument": {
"text": "Episode 12: Building in Public",
"style": {
"position": "bottom-center",
"fontSize": 36,
"fontColor": "#FFFFFF",
"outlineThickness": 2
}
}
}
]
}
The preset handles resizing and encoding. The virtual option handles text. They compose without you having to think about filter chain ordering.
When to Use Which
Use the CLI when you're doing a quick one-off edit on your local machine and you already have FFmpeg installed.
Use the API when you're building automation. If you're processing user uploads, generating social media clips, or adding captions to a batch of videos, you don't want to manage FFmpeg servers. The API handles scaling, font rendering, and text wrapping so you can focus on your application logic.
You can sign up for a free FFmpeg Micro account at ffmpeg-micro.com and start making API calls in a few minutes. The free tier includes enough processing time to test your text overlay workflow before committing to a paid plan.
About Javid Jamae
Founder & CEO at FFmpeg Micro
Javid is a software engineer, author, and entrepreneur with over 25 years of professional software development experience across enterprise, startup, and consulting environments. He founded FFmpeg Micro to make video processing accessible to developers through a simple, automation-first REST API.
You might also like

How to Use the FFmpeg MCP Server with Claude, Cursor, and Windsurf
Set up the FFmpeg Micro MCP server and process videos with natural language from Claude Code, Claude Desktop, Cursor, or Windsurf. No FFmpeg install needed.

How to Use FFmpeg with Go (Golang)
Learn 3 ways to use FFmpeg with Go: os/exec, ffmpeg-go wrapper, and a cloud API. Working code for each approach, common pitfalls, and when to use which.

How to Use FFmpeg with Java (No Installation Required)
Learn three ways to process video in Java: ProcessBuilder, Jaffree, and a cloud API that needs no FFmpeg install. Working code for each approach.
Ready to process videos at scale?
Start using FFmpeg Micro's simple API today. No infrastructure required.
Get Started Free