Read VITC Timecode from Analog Video with FFmpeg

Digitizing analog videotapes often requires preserving the original timecode embedded in the Vertical Blanking Interval (VBI). This guide explains how to use FFmpeg’s readvitc filter to detect, read, and extract Vertical Interval Timecode (VITC) from interlaced analog video captures. You will learn the basic filter syntax, how to adjust scanning parameters for poor-quality tapes, and how to burn the recovered timecode directly into your video or export it as metadata.

Understanding the readvitc Filter

The readvitc filter analyzes the non-visible lines at the top of an analog video frame (the vertical blanking interval) where VITC is stored. When it detects a valid timecode, it attaches this data to the video frame as metadata under the key lavfi.readvitc.tc.

Because analog captures can suffer from signal degradation, the filter allows you to configure line limits and brightness thresholds to improve recognition accuracy.

Basic Syntax and Parameters

The basic syntax for the filter is:

-vf readvitc=scan_max_line=N:thr_b=X:thr_w=Y

Practical Examples

1. Extract VITC Metadata to a Text File

To extract the timecode from every frame without re-encoding the video, combine ffprobe with the readvitc filter. This outputs a list of frame numbers alongside their corresponding VITC timecode.

ffprobe -f lavfi -i "movie=input.mov,readvitc" -show_entries frame=pkt_pts_time:frame_tags=lavfi.readvitc.tc -of csv=p=0 > timecodes.txt

2. Burn VITC Timecode into the Video (Overscan Visual Confirmation)

To verify that the timecode is being read correctly, you can burn the extracted metadata onto the active video area using the drawtext filter.

ffmpeg -i input.mov -vf "readvitc,drawtext=fontfile=Arial.ttf:text='%{metadata\:lavfi.readvitc.tc}':x=10:y=10:fontsize=24:fontcolor=white:box=1:boxcolor=black@0.8" -c:a copy output.mp4

Note: Ensure your FFmpeg build has libfreetype enabled to use the drawtext filter.

3. Tuning for Noisy or Low-Signal Analog Captures

If your analog capture has generation loss or low contrast, the default thresholds might miss frames. You can adjust the black and white thresholds to make the filter more sensitive to weak VITC pulses:

ffmpeg -i input.mov -vf "readvitc=scan_max_line=30:thr_b=0.3:thr_w=0.5" -f null -

In this setup: * Scanning is limited to the first 30 lines. * thr_b=0.3 raises the black ceiling, allowing gray-ish low signals to register as black. * thr_w=0.5 lowers the white floor, allowing weaker white pulses to be recognized.