FFmpeg drawtext Drop-Frame Timecode Configuration

This article explains how to configure the drawtext filter in FFmpeg to accurately generate and display drop-frame timecodes. You will learn the exact syntax required to prevent drift on NTSC frame rates (like 29.97 fps), how to properly escape special characters in the command line, and how to define the starting timecode frame rate.

To render a drop-frame timecode, you must use the timecode parameter within the drawtext filter. Drop-frame timecode is essential for broadcast formats running at nominal frame rates like 29.97 fps or 59.94 fps to ensure the timecode matches real-world clock time. FFmpeg triggers drop-frame behavior when you specify a drop-frame frame rate (such as 29.97 or 30000/1001) and use a semicolon (;) or dot (.) as the frame separator in the initial timecode string.

The Basic Command Syntax

Here is the standard command structure to overlay a drop-frame timecode starting at 01:00:00;00 on a 29.97 fps video:

ffmpeg -i input.mp4 -vf "drawtext=fontfile=Arial.ttf:timecode='01\:00\:00\;00':rate=30000/1001:fontsize=24:fontcolor=white:x=10:y=10" -c:a copy output.mp4

Key Parameter Breakdown

Escaping Rules for Command Lines

Proper escaping is critical to avoid syntax errors. The escaping method changes depending on your operating system’s terminal:

On Linux and macOS (Bash/Zsh)

Wrap the entire filter chain in double quotes, and wrap the timecode value in single quotes with backslashes:

-vf "drawtext=fontfile=Arial.ttf:timecode='01\:00\:00\;00':rate=30000/1001"

On Windows (Command Prompt)

Windows Command Prompt handles quotes differently. You must escape the colons and semicolons with backslashes, but you may need to omit the internal single quotes:

-vf "drawtext=fontfile=C\\:/Windows/Fonts/arial.ttf:timecode=01\:00\:00\;00:rate=30000/1001"

(Note: If the font path contains a drive letter with a colon, like C:, that colon must also be escaped as C\\:).

Verifying Drop-Frame Behavior

When configured correctly, the timecode will automatically drop frame numbers 00 and 01 at the start of every minute, except for minutes ending in zero (00, 10, 20, 30, 40, and 50). This behavior keeps the burned-in timecode in perfect sync with real-world time.