Preset Grading vs Auto-Grade vs Raw ffmpeg Filters in video-use

video-use provides three colour-grading modes—preset grading, auto-grade, and raw ffmpeg filters—that determine how the -vf filter chain is constructed during per-segment extraction.

The browser-use/video-use repository ships a compact colour-grading subsystem that exposes preset grading, auto-grade, and raw ffmpeg filters to shape the look of extracted segments. Whether you want a deterministic cinematic look, a data-driven cleanup, or complete manual control, the chosen mode dictates how the ffmpeg filter string is generated and injected into the pipeline.

Preset Grading: Reusable, Author-Defined Looks

Preset grading relies on the PRESETS dictionary defined in helpers/grade.py. Each named entry—such as warm_cinematic or neutral_punch—maps to a static ffmpeg filter string assembled from eq, colorbalance, curves, and other filters. When a user requests a preset, get_preset() returns the corresponding expression, and extract_segment() in helpers/render.py inserts it directly into the -vf chain of the per-segment extraction step.

This mode is ideal when you need a deterministic, artistic look that applies the same fixed corrections across every segment.

Example: Applying a Preset from the CLI

python helpers/grade.py input.mp4 -o out.mp4 --preset warm_cinematic

Auto-Grade: Conservative, Statistics-Based Correction

Auto-grade is the default behaviour when no preset or raw filter is supplied. The implementation lives in helpers/grade.py, where auto_grade_for_clip() drives the process. It first invokes _sample_frame_stats() to run ffmpeg with the signalstats filter and metadata=print, sampling frames to collect Y-luma and saturation values. These metrics are normalised by bit-depth to produce y_mean, y_std, and sat_mean.

A deterministic rule set maps those statistics to subtle contrast, gamma, and saturation adjustments that are deliberately clamped to ±8% and never introduce a colour shift. If the source clip is already well-balanced, the function falls back to the subtle preset (eq=contrast=1.03:saturation=0.98).

Example: Using Default Auto-Grade

python helpers/grade.py input.mp4 -o out.mp4

The resulting filter string—something like eq=contrast=1.045:gamma=1.017:saturation=1.012—is injected into the same -vf chain used for preset grading.

Raw ffmpeg Filters: Unrestricted Manual Control

Raw ffmpeg filters give callers full manual control by accepting any valid ffmpeg filter string via the --filter CLI flag or the grade field of an EDL. No validation is performed beyond treating the input as a literal filter expression.

Inside helpers/render.py, resolve_grade_filter() detects a raw string by checking for characters like = or ,. When found, it bypasses the PRESETS lookup and returns the expression verbatim. extract_segment() then appends that literal string to the -vf chain immediately after HDR tone-mapping and scaling.

Example: Supplying a Custom Filter String

python helpers/grade.py input.mp4 -o out.mp4 \
    --filter "eq=contrast=1.12:saturation=0.95,curves=master='0/0 0.5/0.6 1/1'"

Architectural Flow and Filter Injection

The three grading modes converge in the same rendering pipeline. Understanding the resolution flow clarifies how each mode is selected and where it is applied.

CLI Argument Resolution

In helpers/grade.py, the --preset and --filter arguments are mutually exclusive. If both are omitted, the code automatically falls back to auto_grade_for_clip().

EDL Grade Resolution

resolve_grade_filter() in helpers/render.py interprets the grade field of each EDL entry. It returns exactly one of the following:

  • A preset filter via get_preset(name)
  • The literal raw filter string
  • The sentinel "__AUTO__", which is expanded per-segment by calling auto_grade_for_clip() with the source video and segment timestamps

Raw strings are detected heuristically and passed straight through without preset lookup.

EDL Examples for Each Mode

{
  "source": "clip1.mp4",
  "grade": "auto"
}
{
  "source": "clip2.mp4",
  "grade": "neutral_punch"
}
{
  "source": "clip3.mp4",
  "grade": "eq=gamma=1.08"
}

Per-Segment ffmpeg Assembly

extract_segment() builds the final -vf argument by concatenating, in order, tone-mapping, scaling, and the resolved grade filter. This ensures every extracted segment receives a consistent colour-correction step regardless of how the filter was derived.

Summary

  • Preset grading uses static, author-defined filter strings stored in helpers/grade.py for deterministic looks.
  • Auto-grade derives conservative corrections from frame-level signalstats analysis via _sample_frame_stats() and auto_grade_for_clip().
  • Raw ffmpeg filters allow unrestricted manual control by passing literal strings through --filter or EDL grade fields.
  • All three modes are injected by extract_segment() in helpers/render.py into the same per-segment -vf chain after tone-mapping and scaling.

Frequently Asked Questions

What happens if I supply both --preset and --filter?

The CLI parser in helpers/grade.py treats these arguments as mutually exclusive. You cannot supply both simultaneously; the tool enforces a single grading path and will reject or override the conflicting input.

How does auto-grade decide when to apply corrections?

auto_grade_for_clip() analyses sampled frames using ffmpeg's signalstats filter. It computes y_mean, y_std, and sat_mean, then maps those values to contrast, gamma, and saturation adjustments clamped to ±8%. If the metrics indicate the clip is already well-balanced, the system falls back to the subtle preset instead of applying a custom correction.

Can I use raw ffmpeg filters inside an EDL?

Yes. If an EDL entry's grade field contains characters like = or ,, resolve_grade_filter() in helpers/render.py treats the value as a raw ffmpeg filter string and appends it verbatim to the -vf chain. No preset lookup occurs.

Where is the grade filter positioned in the final ffmpeg command?

The resolved filter is appended inside extract_segment() in helpers/render.py after HDR tone-mapping and scaling steps. This ordering ensures colour corrections apply to the correctly transformed image.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →