Originally published at ffmpeg-micro.com
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 48 -
fontColor(string) - hex color like#FFFFFFor named colors likewhite,red -
outlineThickness(number) - stroke width in pixels around the text -
margin(number) - padding from video edges in pixels -
textWidth(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.
Top comments (0)