β„‚π• π•Ÿπ•₯π•šπ•Ÿπ•¦π•¦π•ž

Cinematic Grading

Last update: 2026-08-03

Tags: music

Apply a refined cinematic / Fuji-inspired color grade to video files using presets or custom parameters.

Requirements

Features

Install

cd cinematic-grade
uv sync

Optional short alias (add to ~/.zshrc or ~/.bashrc):

alias cg='cinematic-grade'
# or if you prefer staying with uv run:
# alias cg='uv run cinematic-grade'

Quick Start

List Available Presets

cg --list-presets
# or
uv run cinematic-grade --list-presets

Use a Preset

# Default preset is "subtle" (soft lifestyle look)
cg input.mp4 output.mp4

# Explicit presets
cg input.mp4 output.mp4 --preset subtle
cg input.mp4 output.mp4 --preset warm
cg input.mp4 output.mp4 --preset chris
cg input.mp4 output.mp4 --preset strong
cg input.mp4 output.mp4 --preset movie

Override Preset Parameters

# Use warm preset but boost saturation
cg input.mp4 output.mp4 --preset warm --saturation 1.20

# Use strong preset but reduce LUT strength
cg input.mp4 output.mp4 --preset strong --lut-strength 0.50

Presets

Presets are defined in presets.toml.
Main LUT: classic_chrome_sRGB.cube (Fujifilm Classic Chrome)
Default preset: subtle

Preset Description LUT Strength Best for
subtle Soft lifestyle look (default) 0.40 Everyday / vlog / travel
warm Warm cinematic 0.50 Balanced cinematic look
chris Warm intimate guitar / cozy room 0.40 Intimate music / soft daylight
strong Stronger film look 0.70 More stylized shots
punchy Higher contrast + saturation 0.55 Vibrant / energetic clips
soft Very soft and low contrast 0.35 Dreamy / gentle look
movie Heavy cinematic (Movie Film LUT) 0.80 Dramatic / heavy grade
pure Warm grade only (no LUT) β€” Clean warmth, no film LUT
neutral No grading β€” Comparison / baseline
# Soft lifestyle / travel footage (default)
cg input.mp4 output.mp4

# Warm intimate (guitar, cozy rooms, soft light)
cg input.mp4 output.mp4 --preset chris

# General cinematic
cg input.mp4 output.mp4 --preset warm

# Heavier film look
cg input.mp4 output.mp4 --preset strong

Usage Without / Beyond Presets

# Full custom grade
cg input.mp4 output.mp4 \
  --lut classic_chrome_sRGB.cube \
  --lut-strength 0.45 \
  --warmth 1.13 \
  --saturation 1.12 \
  --contrast 1.06 \
  --black-lift 0.07 \
  --vignette 0.09 \
  --cool-desat 0.08

Parameter Reference

Parameter Range Default Purpose
--preset name subtle Load a preset from presets.toml
--lut file path (none) Path to .cube 3D LUT
--lut-strength 0.0–1.0 0.75 How strongly to apply the LUT
--warmth 0.8–1.3 1.12 Shift toward warm (orange/red) tones
--saturation 0.8–1.5 1.15 Color intensity multiplier
--contrast 0.9–1.2 1.08 Overall punch and separation
--black-lift 0.0–0.15 0.06 Shadow lift (softer blacks)
--vignette 0.0–0.3 0.12 Edge darkening strength
--cool-desat 0.0–0.3 0.18 Desaturate cool tones (blues/cyans)
--no-normalize flag off Skip loudness normalization entirely
--loudness-target LUFS -12.0 Target integrated loudness
--true-peak dBTP -1.5 Max true peak (clipping ceiling)
--loudness-range LU 11.0 Allowed loudness range (dynamics)
--audio-bitrate e.g.Β 256k 256k AAC bitrate for the final export

Processing Order

  1. LUT (base look)
  2. Black lift
  3. Contrast (S-curve)
  4. Warmth
  5. Saturation + cool desaturation
  6. Vignette

The numeric controls (warmth, contrast, etc.) fine-tune the result after the LUT is applied.

Audio Normalization

Every export runs a two-pass loudnorm by default:

  1. Measure β€” ffmpeg analyzes the source audio’s integrated loudness, true peak, and loudness range (EBU R128).
  2. Apply β€” those measured values are fed back in with linear=true, producing a single flat gain adjustment rather than a dynamic, sample-by-sample one.

This brings clips to a consistent, comparable loudness across a project without pumping/ducking during quiet vs.Β loud passages β€” the recorded dynamics and tonal character are preserved, just leveled.

# Default: normalize to -12 LUFS, 256k AAC
cg guitar_take.mp4 output.mp4 --preset chris

# Louder target, tighter true-peak ceiling
cg guitar_take.mp4 output.mp4 --preset chris --loudness-target -14 --true-peak -1.0

# Skip normalization entirely, keep original levels
cg guitar_take.mp4 output.mp4 --preset chris --no-normalize

Note: two-pass loudnorm only stays purely linear if the correction needed is modest. If a source clip is unusually quiet or has very large dynamic swings, ffmpeg may fall back to its dynamic algorithm for that clip even with linear=true on. There’s no clean way to detect this from the exit code β€” if a specific clip’s audio sounds off after normalization, this is the first thing to check.

LUTs

File Character Recommended use
classic_chrome_sRGB.cube Muted, clean, documentary Main / default LUT
eterna_sRGB.cube Soft, low-contrast film Soft cinematic
provia_sRGB.cube More vivid + contrasty Punchier looks
movie_film.cube Heavy cinematic / stylized Dramatic grades

Additional Fuji LUTs:
https://github.com/abpy/FujifilmCameraProfiles/tree/master/cube%20lut
(use the *_sRGB.cube versions)

Creating Custom Presets

Edit presets.toml and add a new section:

[presets.my_look]
description = "Custom grade"
lut = "classic_chrome_sRGB.cube"
lut_strength = 0.55
warmth = 1.13
saturation = 1.15
contrast = 1.09
black_lift = 0.05
vignette = 0.10
cool_desat = 0.10

Then use it:

cg input.mp4 output.mp4 --preset my_look

Batch Processing

#!/bin/bash
PRESET=${1:-subtle}
OUTPUT_DIR=${2:-./graded}

mkdir -p "$OUTPUT_DIR"

for video in *.mp4; do
  echo "Grading: $video"
  cg "$video" "$OUTPUT_DIR/${video%.mp4}_graded.mp4" --preset "$PRESET"
done
chmod +x batch_grade.sh
./batch_grade.sh              # uses default (subtle)
./batch_grade.sh chris        # warm intimate
./batch_grade.sh warm         # warmer cinematic
./batch_grade.sh strong       # stronger film look

Technical Notes

Troubleshooting

Presets not loading

Audio missing / unplayable file

LUT not found

File Structure

cinematic-grade/
β”œβ”€β”€ pyproject.toml
β”œβ”€β”€ presets.toml
β”œβ”€β”€ classic_chrome_sRGB.cube   # Main LUT
β”œβ”€β”€ eterna_sRGB.cube
β”œβ”€β”€ provia_sRGB.cube
β”œβ”€β”€ movie_film.cube
β”œβ”€β”€ README.md
└── cinematic_grade/
    β”œβ”€β”€ __init__.py
    β”œβ”€β”€ cli.py
    └── grade.py

Also see 2026-07-26: Recording and 2026-07-26: Guitar