Burn 29.97 FPS Drop-Frame Timecode in FFmpeg

This article explains how to burn a dynamic SMPTE drop-frame timecode overlay into a 29.97 frames-per-second video using FFmpeg's drawtext video filter. It covers the precise command-line syntax required to ensure proper drop-frame synchronization, explains the essential parameters, and shows how to customize the visual appearance and placement of the overlay on your output file.

The Basic Command

To burn a drop-frame timecode starting at 01:00:00;00, run the following command:

ffmpeg -i input.mp4 -vf "drawtext=fontfile=/path/to/font.ttf:timecode='01\:00\:00\;00':rate=30000/1001:x=(w-text_w)/2:y=h-th-50:fontsize=48:fontcolor=white:box=1:boxcolor=black@0.6:boxborderw=5" -c:a copy output.mp4

Key Parameters Explained

  1. Drop-Frame Semicolon Syntax (timecode='01\:00\:00\;00') In SMPTE standard notation, a semicolon (;) or period (.) preceding the frame number denotes drop-frame timecode. FFmpeg detects the semicolon delimiter to trigger drop-frame counting logic, where frame numbers 00 and 01 are skipped at the start of every minute, except every tenth minute. Colons and semicolons inside the filter must be escaped with a backslash (\) to avoid parsing errors.

  2. Accurate Frame Rate (rate=30000/1001) Always define the exact fractional rate 30000/1001 instead of using the rounded value 29.97. Using 29.97 can introduce drift over long runtimes because true NTSC frame rates are mathematically fractional.

  3. Font Specification (fontfile=/path/to/font.ttf) FFmpeg requires a valid TrueType or OpenType font to generate the text. Replace /path/to/font.ttf with an actual path on your system (e.g., /Windows/Fonts/arial.ttf on Windows or /System/Library/Fonts/Helvetica.ttc on macOS). For timecodes, monospaced fonts such as Courier or Roboto Mono are recommended to prevent horizontal jitter as numbers change.

  4. Positioning (x and y)

    • x=(w-text_w)/2: Horizontally centers the overlay.
    • y=h-th-50: Positions the timecode 50 pixels from the bottom of the video frame.
  5. Background Box (box, boxcolor, boxborderw)

    • box=1: Enables a rectangular background behind the timecode to ensure legibility against bright backgrounds.
    • boxcolor=black@0.6: Sets the background to black with 60% opacity.
    • boxborderw=5: Adds 5 pixels of padding around the text.

Reading Timecode from Source Metadata

If your source file already contains an embedded SMPTE timecode track and you want to display that original value rather than a manually typed starting point, use the timecode_rate parameter combined with the internal metadata reader:

ffmpeg -i input.mov -vf "drawtext=fontfile=/path/to/font.ttf:text='%{pts\:hms}':rate=30000/1001:x=(w-text_w)/2:y=h-th-50:fontsize=48:fontcolor=white:box=1:boxcolor=black@0.6" -c:a copy output.mov

Alternatively, if you want to pull the native metadata timecode tag into the drawtext filter directly:

ffmpeg -i input.mov -vf "drawtext=fontfile=/path/to/font.ttf:timecode='00\:00\:00\;00':rate=30000/1001:x=50:y=50:fontsize=36:fontcolor=yellow" -c:v libx264 -crf 18 -c:a copy output.mp4

Encoding Considerations

  • Re-encoding: Burning visual text onto video frames requires re-encoding the video stream (-c:v libx264 or another supported encoder). It cannot be done using -c:v copy.
  • Audio Preservation: Use -c:a copy to pass through the existing audio stream without re-encoding or introducing audio-sync offsets.