Basic Commands
Display Text in the Top-Left Corner
ffmpeg -i input.mp4 -vf "drawtext=text='Hello World':x=10:y=10:fontsize=36:fontcolor=white" output.mp4
Center the Text
ffmpeg -i input.mp4 \
-vf "drawtext=text='CENTER':x=(w-text_w)/2:y=(h-text_h)/2:fontsize=48:fontcolor=white" \
output.mp4
w and h are the width and height of the video. text_w and text_h are the width and height of the drawn text. To combine drawtext with other filters, see how filtergraphs work.
Key Parameters
| Parameter | Description | Example |
|---|---|---|
text |
The text to display | text='Hello' |
fontfile |
Path to the font file | fontfile=/path/to/font.ttf |
fontsize |
Font size (pixels) | fontsize=36 |
fontcolor |
Text color (name or HEX) | fontcolor=white / fontcolor=0xFFFFFF |
x / y |
Position | x=10:y=10 |
shadowcolor |
Shadow color | [email protected] |
shadowx / shadowy |
Shadow offset | shadowx=2:shadowy=2 |
box |
Background box | box=1 |
boxcolor |
Background box color | [email protected] |
boxborderw |
Background box padding | boxborderw=5 |
Specifying a Font
ffmpeg -i input.mp4 \
-vf "drawtext=fontfile=/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf:text='FFmpeg':fontsize=40:fontcolor=yellow" \
output.mp4
For Japanese or other CJK (Chinese, Japanese, Korean) text, use a font that has those characters:
ffmpeg -i input.mp4 \
-vf "drawtext=fontfile=/path/to/NotoSansCJKjp-Regular.otf:text='日本語テキスト':fontsize=36:fontcolor=white" \
output.mp4
Text with a Shadow
ffmpeg -i input.mp4 \
-vf "drawtext=text='Shadow Text':x=50:y=50:fontsize=40:fontcolor=white:shadowcolor=black:shadowx=3:shadowy=3" \
output.mp4
Text with a Background Box
ffmpeg -i input.mp4 \
-vf "drawtext=text='BOX TEXT':x=20:y=20:fontsize=36:fontcolor=white:box=1:[email protected]:boxborderw=8" \
output.mp4
[email protected] is black at 60% opacity. If a solid box looks too heavy on a busy background, blur the area behind the text instead.
Displaying a Timecode
ffmpeg -i input.mp4 \
-vf "drawtext=text='%{pts\:hms}':x=w-text_w-10:y=h-text_h-10:fontsize=24:fontcolor=white:box=1:[email protected]" \
output.mp4
%{pts\:hms} shows the time as HH:MM:SS.mmm. Inside text='...', write a colon as \:. Otherwise FFmpeg reads it as the separator between options.
Displaying the Frame Number
ffmpeg -i input.mp4 \
-vf "drawtext=text='Frame %{n}':x=10:y=10:fontsize=24:fontcolor=yellow" \
output.mp4
Scrolling Ticker (Text Moving Right to Left)
ffmpeg -i input.mp4 \
-vf "drawtext=text='スクロールテキストのサンプルです':x=w-200*t:y=h-60:fontsize=32:fontcolor=white" \
output.mp4
For an English ticker, swap in your own text:
ffmpeg -i input.mp4 \
-vf "drawtext=text='This is a sample scrolling ticker':x=w-200*t:y=h-60:fontsize=32:fontcolor=white" \
output.mp4
With x=w-200*t, the text starts at the right edge and moves left as time t goes on. 200 is the speed in pixels per second; change it to scroll faster or slower.
Overlaying Multiple Text Layers
ffmpeg -i input.mp4 \
-vf "drawtext=text='Title':x=(w-text_w)/2:y=30:fontsize=48:fontcolor=white, \
drawtext=text='Subtitle':x=(w-text_w)/2:y=90:fontsize=28:fontcolor=yellow" \
output.mp4
Separate each drawtext with a comma to draw several texts.
Reading from a Text File
ffmpeg -i input.mp4 \
-vf "drawtext=textfile=caption.txt:x=10:y=10:fontsize=28:fontcolor=white" \
output.mp4
Use textfile= instead of text= to read the text from a file.
Handy Variables for Positioning
| Variable | Meaning |
|---|---|
w |
Width of the video |
h |
Height of the video |
text_w |
Width of the rendered text |
text_h |
Height of the rendered text |
t |
Current time (seconds) |
n |
Frame number |
Things to Watch Out For
drawtextneeds an FFmpeg build with libfreetype, and since FFmpeg 6.1 also libharfbuzz. To check, runffmpeg -h filter=drawtext.- The text in
textortextfilemust be UTF-8. - Text that runs past the edge of the frame is cut off. This is not an error.
Common Pitfalls
-
Symptom: nothing is drawn. Cause:
textis empty, or FFmpeg cannot find a font. Fix: test with a simple string such astext='Hello World'. If no font is set up, pointfontfile=at a real font file. On Windows, write the colon after the drive letter as\:, as infontfile='C\:/Windows/Fonts/arial.ttf'. The quotes alone do not protect that colon: FFmpeg still reads it as a separator and stops with an error. -
Symptom: a parse error or wrong text when the text contains
:or'. Cause:drawtextseparates options with colons, and the filter itself is wrapped in quotes, so these characters in your text are misread. Fix: insidetext='...', write a colon as\:. For text with a single quote, or long text with many symbols, put it in a file and load it withtextfile=caption.txt:expansion=none. Then nothing needs escaping. Withoutexpansion=none, FFmpeg still reads%and\in the file as special characters: a backslash disappears, and a plain%, as in50%, stops the text from being drawn. -
Symptom: Japanese or other CJK text shows as boxes (□) or blanks. Cause: the font (for example DejaVu Sans) has no characters for that language. Fix: set a CJK font such as Noto Sans CJK with
fontfile=. -
Symptom: the ticker stops partway or moves too fast. Cause: the speed in
x=w-200*tdoes not suit your clip’s length or width. Fix: try speeds from about100to300. The text needs about(w + text_w) / speedseconds to cross the screen completely.
FAQ
Q. Can I use it without specifying fontfile?
A. Only if FFmpeg was built with fontconfig; without it, fontfile is required. Even with fontconfig, if its configuration file cannot be found, FFmpeg prints Fontconfig error and can stop there. Passing a real font file with fontfile= is the most reliable. You can also pick a font by name with font=, but which fonts are available depends on the system.
Q. How do I put a semi-transparent bar behind the text?
A. Use the box options: box=1:[email protected]:boxborderw=8. @0.6 sets the opacity (60%), and boxborderw is the padding around the text.
Q. Can I show text only for a limited time?
A. Yes. Add enable='between(t,2,5)' to draw it only from 2 to 5 seconds. To show different text at different times, chain several drawtext filters with commas, each with its own enable.
Q. The timecode %{pts\\:hms} throws an error.
A. In PowerShell and Command Prompt, backslashes reach FFmpeg unchanged. FFmpeg reads \\ as one literal backslash, so the colon after it becomes an option separator and you get Error parsing filterchain. Use a single backslash: %{pts\:hms}. In bash or zsh, \\ inside double quotes becomes \, so both forms work there.
Q. Can I keep -c:v copy after drawing text?
A. No. drawtext changes the pixels, so the video is always re-encoded. You can still copy the audio unchanged with -c:a copy.