Color grade with the curves filter
The curves filter is the most precise color tool in libavfilter. It applies a piecewise-linear function to a channel (red, green, blue, luma, or all), letting you lift the shadows, roll off the highlights, or change the contrast at a specific luminance range.
The command
ffmpeg -i in.mp4 -vf "curves=preset=darker" -c:v libx264 -crf 20 out.mp4What it does
The filter can take a named preset (`darker`, `brighter`, `increase_contrast`, `linear`) or a custom expression mapping input to output for a specific channel. For a custom look, the syntax is `curves=red='0/0 0.5/0.4 1/1'`, which sets red 0 to stay 0, red 0.5 to 0.4, and red 1 to 1 — a midtone darkening that leaves the pure black and pure white anchors untouched.
Requirements
Any video input. The filter is in libavfilter. CPU-only. The mapping expression is straightforward enough to write by hand, but the `curves` UI in ffmpeg-ui or any external color tool is more visual.
Things to avoid
- Modifying the endpoints. If you change `0/0` to `0/0.1`, you have just lifted the black floor and added a permanent blue cast on the dark side of the image.
- Using a very long curve list. Each pair adds a breakpoint; too many breakpoints give the same result as a single straight line, so keep the list minimal.
- Combining curves with a global color space filter. The curves filter operates in YUV; if you converted to RGB for grading, the conversion back to YUV may clip the highlights.
- Forgetting to verify on a calibrated monitor. What looks 'darker' on a bright display may look 'crushed' on a dim one. Always check the output on the same hardware the audience will use.