What You Will Learn

  • Commands for drawing text onto video with the drawtext filter
  • How to specify font, size, color, and position
  • How to display timecodes and dynamic text
  • How to build a scrolling ticker

Tested with: FFmpeg 6.1 (verified against real FFmpeg)
Target OS: Windows / macOS / Linux

Tested with: FFmpeg 6.1 (verified against real FFmpeg)


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, while text_w and text_h are the width and height of the rendered text. When you start combining drawtext with other filters, understanding how filtergraphs work makes complex chains far easier to write.


Key Parameters

ParameterDescriptionExample
textThe text to displaytext='Hello'
fontfilePath to the font filefontfile=/path/to/font.ttf
fontsizeFont size (pixels)fontsize=36
fontcolorText color (name or HEX)fontcolor=white / fontcolor=0xFFFFFF
x / yPositionx=10:y=10
shadowcolorShadow color[email protected]
shadowx / shadowyShadow offsetshadowx=2:shadowy=2
boxBackground boxbox=1
boxcolorBackground box color[email protected]
boxborderwBackground box paddingboxborderw=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

To display Japanese (or other CJK) text, specify a font that supports 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 a black background at 60% opacity. When the background is busy and a flat box looks heavy, you can instead apply a box blur behind the text to keep it readable.


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} displays a timecode in HH:MM:SS.mmm format. Watch out for shell escaping (the \\: is required).


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 moves leftward as time t advances. Adjust the speed with the coefficient (200).


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

You can chain multiple drawtext filters with commas.


Reading from a Text File

ffmpeg -i input.mp4 \
  -vf "drawtext=textfile=caption.txt:x=10:y=10:fontsize=28:fontcolor=white" \
  output.mp4

Instead of text=, you can specify a text file with textfile=.


Handy Variables for Positioning

VariableMeaning
wWidth of the video
hHeight of the video
text_wWidth of the rendered text
text_hHeight of the rendered text
tCurrent time (seconds)
nFrame number

Things to Watch Out For

  • drawtext requires libfreetype. It is included in standard FFmpeg builds.
  • Multi-byte characters such as Japanese or Chinese require a font file with UTF-8 encoded glyphs.
  • If the text extends beyond the video frame, it is automatically clipped (this does not cause an error).
  • Be careful with escaping special characters in the shell (use \\: for :, '\'' for ', and so on).

Common Pitfalls

  • Symptom: nothing is drawn at all. Cause: an empty text, or the font cannot be found. Fix: first test with a known string such as text='Hello World', and if no font is configured, point fontfile= at a real font file. Quote any path that contains spaces or colons with '...'.

  • Symptom: a parse error when the text contains : or '. Cause: drawtext uses a colon to separate options and quotes to wrap the whole filter, so special characters in the body are misread. Fix: escape a colon as \\: and a single quote as '\''. For longer sentences, load them from an external file with textfile= to avoid escaping entirely.

  • Symptom: Japanese or other CJK text shows as boxes (□) or blanks. Cause: the chosen font (e.g. DejaVu Sans) has no glyphs for those characters. Fix: specify a CJK-capable font such as Noto Sans CJK via fontfile=. The font file itself must contain the glyphs you need.

  • Symptom: the scrolling ticker stops partway or moves too fast. Cause: the coefficient in x=w-200*t does not match your clip length or width. Fix: tune the speed coefficient between roughly 100 and 300, and estimate the time for the text to fully clear as about (w + text_w) / coefficient seconds.


FAQ

Q. Can I use it without specifying fontfile? A. On some builds and operating systems no default font is found and you get an error. The most reliable approach is to pass a real fontfile=. You can also select by name with font=, but the available fonts depend on the environment.

Q. How do I put a semi-transparent bar behind the text? A. Use the box options: box=1:[email protected]:boxborderw=8. The @0.6 is the opacity (60%) and boxborderw is the padding around the text.

Q. Can I show text only for a limited time? A. Add enable='between(t,2,5)' to draw it only between 2 and 5 seconds. Chain multiple drawtext filters with commas to show different text at different times.

Q. The timecode %{pts\\:hms} throws an error. A. The shell is consuming the backslash. Double it as \\: as shown in the examples, or pass the filter expression through a file or script so the escaping survives.

Q. Can I keep -c:v copy after drawing text? A. No. drawtext rewrites pixels, so the video stream is always re-encoded. You can still keep the audio untouched with -c:a copy.


  • drawbox — Draw a rectangle
  • subtitles — Burn in subtitles from an SRT file
  • ass — Burn in ASS-styled subtitles