How to Use FFmpeg Signature Filter for Video Fingerprinting
This guide explains how to use the FFmpeg signature
filter to generate and compare unique perceptual fingerprints of video
files. You will learn the command-line syntax for creating signature
files in both binary and XML formats, as well as how to compare two
videos directly to detect duplicate content, even if the files have
different resolutions, bitrates, or compression levels.
What is a Perceptual Video Fingerprint?
Unlike cryptographic hash functions (such as MD5 or SHA-256), which change completely if a single pixel or byte is altered, a perceptual video fingerprint represents the actual visual content of the video.
FFmpeg’s signature filter analyzes the luminance and
spatial characteristics of video frames to generate a robust
fingerprint. This fingerprint remains virtually identical even if the
video is resized, transcoded to a different format, or slightly
compressed.
Step 1: Generating a Video Signature File
To generate and save a perceptual fingerprint of a video to a file,
use the signature filter. You can export the fingerprint in
either binary (more compact) or xml
(human-readable) format.
Run the following command to generate a binary signature:
ffmpeg -i input.mp4 -vf "signature=format=binary:filename=video_signature.bin" -f null -Command Breakdown:
-i input.mp4: Specifies the input video file.-vf "signature=...": Applies the signature video filter.format=binary: Sets the output format of the signature file.filename=video_signature.bin: Defines the output path for the fingerprint file.
-f null -: Tells FFmpeg not to output a new video file, avoiding unnecessary disk space usage and speeding up the process.
To generate an XML version instead, change the format and file extension:
ffmpeg -i input.mp4 -vf "signature=format=xml:filename=video_signature.xml" -f null -Step 2: Comparing Two Videos Directly
You can compare two video streams in real-time to check if they
contain the same content by feeding both files into FFmpeg and using the
signature filter with multiple inputs.
Run this command to compare two videos:
ffmpeg -i video1.mp4 -i video2.mp4 -filter_complex "[0:v][1:v]signature=nb_inputs=2:detect=on" -f null -Command Breakdown:
-i video1.mp4 -i video2.mp4: Inputs both videos you want to compare.-filter_complex: Uses a complex filtergraph to handle multiple video inputs.[0:v][1:v]: Selects the video streams from the first and second input files.signature=nb_inputs=2: Instructs the filter to accept two input streams.detect=on: Enables the detection engine to analyze and report matches in the terminal output.
Step 3: Understanding the Matching Output
When you run the comparison command, FFmpeg will output the detection results directly to your console. Look for lines resembling the following:
[Parsed_signature_0 @ 0x7fa8bb40c100] matching of input 0 and input 1 at 0.000000s and 0.000000s, duration 10.4s
If the videos are different, FFmpeg will not output any matching lines. If they are identical or highly similar, the console output will specify the exact timestamps where the match begins and how long the matching sequence lasts.
Advanced Configuration Options
You can fine-tune the matching sensitivity and behavior of the
signature filter using additional parameters:
Adjusting Similarity Threshold
The threshold parameter controls how strict the matching
algorithm is. The default value is 90. * Lower
values (e.g., 70) make the detection more strict,
reducing false positives but potentially missing highly compressed
duplicates. * Higher values (e.g., 120)
make the detection more tolerant of changes like noise, watermarks, or
severe compression.
ffmpeg -i video1.mp4 -i video2.mp4 -filter_complex "[0:v][1:v]signature=nb_inputs=2:detect=on:threshold=100" -f null -Setting Minimum Matching Duration
By default, the filter requires a minimum sequence of frames to match
before declaring a fit. You can change this using the
min_duration parameter (expressed in frames, default is 90
frames).
ffmpeg -i video1.mp4 -i video2.mp4 -filter_complex "[0:v][1:v]signature=nb_inputs=2:detect=on:min_duration=150" -f null -