# How to Implement Custom Color Grading Filters with grade.py in video-use

> Learn to implement custom color grading filters with grade.py in video-use. Extend presets or use custom ffmpeg expressions for powerful video enhancement.

- Repository: [Browser Use/video-use](https://github.com/browser-use/video-use)
- Tags: how-to-guide
- Published: 2026-06-29

---

**The [`grade.py`](https://github.com/browser-use/video-use/blob/main/grade.py) module in browser-use/video-use generates ffmpeg filter strings through built-in presets, automatic per-clip analysis, or raw filter inputs that you can extend by modifying the `PRESETS` dictionary or passing custom ffmpeg expressions.**

The `browser-use/video-use` toolkit provides a flexible color grading system centered in [`helpers/grade.py`](https://github.com/browser-use/video-use/blob/main/helpers/grade.py). Whether you need subtle corrections or dramatic cinematic looks, this module allows you to implement custom color grading filters using three distinct approaches that integrate seamlessly with the rendering pipeline.

## Understanding the Color Grading Architecture

The [`grade.py`](https://github.com/browser-use/video-use/blob/main/grade.py) module serves as the central authority for generating ffmpeg-compatible filter strings. It offers three primary input methods: **built-in presets** defined in the `PRESETS` dictionary ([lines 38-63](https://github.com/browser-use/video-use/blob/main/helpers/grade.py#L38-L63)), **automatic per-clip analysis** via `auto_grade_for_clip` ([lines 78-154](https://github.com/browser-use/video-use/blob/main/helpers/grade.py#L78-L154)), and **raw ffmpeg filter strings** passed directly through CLI or EDL configurations.

When processing video segments, [`helpers/render.py`](https://github.com/browser-use/video-use/blob/main/helpers/render.py) calls `resolve_grade_filter` ([lines 66-84](https://github.com/browser-use/video-use/blob/main/helpers/render.py#L66-L84)) to determine which grading strategy to apply. This function distinguishes between preset names, the literal `"auto"` string for automatic grading, and verbatim ffmpeg expressions before passing the resolved filter to `extract_segment` ([lines 79-86](https://github.com/browser-use/video-use/blob/main/helpers/render.py#L79-L86)) for final application.

## Method 1: Extending Built-In Presets

The simplest way to implement custom color grading filters is by extending the `PRESETS` dictionary in [`helpers/grade.py`](https://github.com/browser-use/video-use/blob/main/helpers/grade.py). This dictionary maps user-friendly names to valid ffmpeg filter expressions, making them accessible via CLI `--preset` flags or EDL `grade` fields.

To add a custom preset, locate the `PRESETS` definition around line 38 and append your filter chain:

```python

# helpers/grade.py – add after the existing PRESETS block

PRESETS["my_cinematic"] = (
    "eq=contrast=1.15:brightness=-0.03:saturation=0.90,"
    "curves=master='0/0 0.25/0.22 0.75/0.78 1/1'"
)

```

The `get_preset` function ([lines 66-73](https://github.com/browser-use/video-use/blob/main/helpers/grade.py#L66-L73)) retrieves these values by key, allowing immediate usage:

```bash
python helpers/grade.py input.mp4 -o out.mp4 --preset my_cinematic

```

## Method 2: Automatic Per-Clip Analysis

For dynamic color correction that adapts to individual clip characteristics, use the **automatic grading** mode. When `resolve_grade_filter` encounters the string `"auto"`, it returns the sentinel `__AUTO__`, triggering `auto_grade_for_clip` ([lines 78-154](https://github.com/browser-use/video-use/blob/main/helpers/grade.py#L78-L154)) during segment processing.

This function samples frames using `_sample_frame_stats` ([lines 84-124](https://github.com/browser-use/video-use/blob/main/helpers/grade.py#L84-L124)) to compute brightness, contrast, and saturation statistics, then generates a subtle "clean-up" filter tailored to each specific clip. Enable this mode in an EDL by setting `"grade": "auto"`:

```json
{
  "grade": "auto",
  "ranges": [
    {"source": "clip1", "start": 0.0, "end": 5.0}
  ],
  "sources": {"clip1": "videos/clip1.mp4"}
}

```

## Method 3: Passing Raw FFmpeg Filter Strings

When presets lack the specificity you need, pass **raw ffmpeg filter strings** directly via the `--filter` CLI flag or the EDL `grade` field. This bypasses `resolve_grade_filter` entirely, applying your expression unchanged to the video filter chain.

```bash
python helpers/grade.py input.mp4 -o out.mp4 --filter 'eq=contrast=1.12:gamma=0.95:saturation=1.02'

```

In EDL configurations, any grade value that isn't `"auto"` and doesn't match a preset key is treated as a literal filter string.

## Integrating Custom Filters into the Render Pipeline

Understanding how [`grade.py`](https://github.com/browser-use/video-use/blob/main/grade.py) interfaces with [`helpers/render.py`](https://github.com/browser-use/video-use/blob/main/helpers/render.py) ensures your custom filters apply correctly during final output. The `extract_all_segments` function ([lines 23-31](https://github.com/browser-use/video-use/blob/main/helpers/render.py#L23-L31)) orchestrates the rendering process, calling `extract_segment` for each EDL range.

During extraction, `resolve_grade_filter` ([lines 66-84](https://github.com/browser-use/video-use/blob/main/helpers/render.py#L66-L84)) determines the appropriate filter string for each segment. If you've added a custom preset to [`grade.py`](https://github.com/browser-use/video-use/blob/main/grade.py), this function automatically recognizes it through `get_preset`. The resolved filter string then gets appended to the video-filter chain in `extract_segment` ([lines 79-86](https://github.com/browser-use/video-use/blob/main/helpers/render.py#L79-L86)), ensuring every clip receives its specified color grade.

## Programmatic Implementation Examples

For Python-based workflows, import the grading functions directly to apply filters programmatically:

```python
from pathlib import Path
from helpers.grade import get_preset, apply_grade

inp = Path("raw.mov")
out = Path("final.mov")
filter_str = get_preset("high_contrast")          # ← retrieve preset

apply_grade(inp, out, filter_str)                # ← runs ffmpeg with the filter

```

To implement a high-contrast preset in the source code:

```python

# helpers/grade.py – add after the existing PRESETS block

PRESETS["high_contrast"] = "eq=contrast=1.20:saturation=1.05"

```

Apply it via CLI:

```bash
python helpers/grade.py source.mov -o graded.mov --preset high_contrast

```

## Summary

- **Built-in presets** offer reusable ffmpeg filter chains stored in the `PRESETS` dictionary ([lines 38-63](https://github.com/browser-use/video-use/blob/main/helpers/grade.py#L38-L63)) of [`helpers/grade.py`](https://github.com/browser-use/video-use/blob/main/helpers/grade.py).
- **Automatic grading** analyzes per-clip statistics via `_sample_frame_stats` ([lines 84-124](https://github.com/browser-use/video-use/blob/main/helpers/grade.py#L84-L124)) and `auto_grade_for_clip` ([lines 78-154](https://github.com/browser-use/video-use/blob/main/helpers/grade.py#L78-L154)) when EDL specifies `"grade": "auto"`.
- **Raw filter strings** bypass preset resolution entirely, allowing direct ffmpeg expressions through CLI `--filter` or EDL grade fields.
- The render pipeline in [`helpers/render.py`](https://github.com/browser-use/video-use/blob/main/helpers/render.py) automatically resolves and applies grades through `resolve_grade_filter` ([lines 66-84](https://github.com/browser-use/video-use/blob/main/helpers/render.py#L66-L84)) during `extract_segment` ([lines 79-86](https://github.com/browser-use/video-use/blob/main/helpers/render.py#L79-L86)).

## Frequently Asked Questions

### How do I add a new color grading preset to grade.py?

Open [`helpers/grade.py`](https://github.com/browser-use/video-use/blob/main/helpers/grade.py) and locate the `PRESETS` dictionary around line 38. Add a new key-value pair where the key is your preset name and the value is a valid ffmpeg filter string. For example: `PRESETS["vintage"] = "eq=contrast=1.1:saturation=0.8,curves=r='0/0 0.5/0.4 1/0.9'"`. The preset becomes immediately available via `--preset vintage` or `"grade": "vintage"` in EDL files.

### What is the difference between preset and auto grading modes?

**Preset mode** applies static ffmpeg filter strings defined in the `PRESETS` dictionary consistently across all clips. **Auto grading** dynamically analyzes each clip's brightness, contrast, and saturation statistics through `auto_grade_for_clip` and generates a unique filter chain per segment. Use presets for uniform stylistic looks and auto mode for technical correction that adapts to varying source footage.

### Can I use multiple filters in a single custom preset?

Yes. The `PRESETS` dictionary values accept full ffmpeg filtergraph expressions. Chain multiple filters using commas: `"eq=contrast=1.15,curves=master='0/0 0.25/0.22 0.75/0.78 1/1',hue=s=0.9"`. Ensure proper quoting when filters contain spaces or special characters.

### Where does the render pipeline apply the grade filter during video processing?

The `resolve_grade_filter` function in [`helpers/render.py`](https://github.com/browser-use/video-use/blob/main/helpers/render.py) ([lines 66-84](https://github.com/browser-use/video-use/blob/main/helpers/render.py#L66-L84)) determines the appropriate filter string, which then gets appended to the ffmpeg command in `extract_segment` ([lines 79-86](https://github.com/browser-use/video-use/blob/main/helpers/render.py#L79-L86)) during the segment extraction phase. This occurs within the `extract_all_segments` loop ([lines 23-31](https://github.com/browser-use/video-use/blob/main/helpers/render.py#L23-L31)), ensuring each EDL range receives its specified color grade before final composition.