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

  • drawtext needs an FFmpeg build with libfreetype, and since FFmpeg 6.1 also libharfbuzz. To check, run ffmpeg -h filter=drawtext.
  • The text in text or textfile must 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: text is empty, or FFmpeg cannot find a font. Fix: test with a simple string such as text='Hello World'. If no font is set up, point fontfile= at a real font file. On Windows, write the colon after the drive letter as \:, as in fontfile='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: drawtext separates options with colons, and the filter itself is wrapped in quotes, so these characters in your text are misread. Fix: inside text='...', write a colon as \:. For text with a single quote, or long text with many symbols, put it in a file and load it with textfile=caption.txt:expansion=none. Then nothing needs escaping. Without expansion=none, FFmpeg still reads % and \ in the file as special characters: a backslash disappears, and a plain %, as in 50%, 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*t does not suit your clip’s length or width. Fix: try speeds from about 100 to 300. The text needs about (w + text_w) / speed seconds 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.

  • drawbox: draws a rectangle
  • subtitles: burns in subtitles from an SRT file
  • ass: burns in ASS-styled subtitles