Extract per-frame colour and luminosity metrics from video using
ffprobe's signalstats filter.
Output goes to Parquet, CSV, IPC/Feather, or NDJSON.
Designed for research pipelines that need a fast, dependency-light way to turn a video into a tabular time series — for example, non-contact cardiac monitoring in animals via colour/motion video analysis.
pixi (recommended — pulls in ffmpeg automatically):
pixi global install vidstatsuv (global install):
uv tool install vidstatsconda:
conda install -c conda-forge vidstatspip (requires ffmpeg on PATH separately):
pip install vidstats# Extract all metrics → Parquet
vidstats input.mp4 output.parquet
# Extract only luminance and saturation averages → CSV
vidstats input.mp4 output.csv --metrics YAVG,SATAVG
# Include both frame number and timestamp in seconds
vidstats input.mp4 output.parquet --timestamps both
# Override FPS when stream metadata is missing or wrong
vidstats input.mp4 output.parquet --timestamps both --fps 30
# Apply a crop region (X Y W H) before extraction
vidstats input.mp4 output.parquet --crop "10 20 180 180"
# Force format regardless of extension
vidstats input.mp4 output.dat --format csv
# Disable hardware acceleration
vidstats input.mp4 output.parquet --no-hwaccel
# List all available metric names and their output column names
vidstats --list-metricsvidstats can also be used directly from Python. The simplest path is the
extract() convenience function:
import vidstats
df = vidstats.extract("input.mp4")df is a Polars DataFrame with the same schema as the CLI output. Optional
arguments mirror the CLI:
df = vidstats.extract(
"input.mp4",
metrics=["YAVG", "SATAVG", "HUEMED"], # default: all metrics
crop=(10, 20, 180, 180), # (x, y, w, h) in pixels
include_time=True, # adds time_s column
fps=25.0, # override FPS for time_s
hwaccel="cuda", # hardware decode acceleration
)Write the result with any Polars method:
df.write_parquet("output.parquet")
df.write_csv("output.csv")| Extension(s) | Format |
|---|---|
.parquet |
Parquet |
.csv |
CSV |
.tsv |
TSV |
.ipc, .arrow, .feather |
Arrow IPC |
.ndjson, .jsonl |
NDJSON |
All 25 signalstats metrics are extracted by default. Run
vidstats --list-metrics for the full table of ffprobe names, output column
names, and descriptions. They cover:
- Luminance:
YMIN,YLOW,YAVG,YHIGH,YMAX - Cb chrominance (U): same set of five
- Cr chrominance (V): same set of five
- Saturation:
SATMIN,SATLOW,SATAVG,SATHIGH,SATMAX - Hue:
HUEMED,HUEAVG - Quality flags:
TOUT,VREP,BRNG
The --metrics flag accepts ffprobe names (e.g. YAVG,SATAVG).
Output columns use descriptive snake_case names (e.g. luminance_mean,
saturation_mean) — see --list-metrics for the full mapping.
| Column | Type | Condition |
|---|---|---|
frame |
UInt32 | always |
time_s |
Float64 | --timestamps seconds or both |
| metrics… | Float32 | selected metrics |
time_s is computed as frame / fps. FPS is read from stream metadata
automatically; use --fps to override it or supply it when metadata is absent.
vidstats auto-detects CUDA and passes -hwaccel cuda to ffprobe if available.
This accelerates the decode stage only — signalstats itself always runs
on CPU. For small (e.g. 200×200) videos the gain is negligible, but the
detection is there for larger inputs. Suppress with --no-hwaccel.
No special CUDA packages or drivers are required beyond what you already have.
vidstats uses ffprobe's built-in NVDEC hardware decoding, which talks directly
to the NVIDIA driver on your system — there is no cudatoolkit, no
pytorch-cuda, and no GPU-specific installation step.
MIT