FFmpeg lutyuv: Modify Individual Y, U, and V Channels

The lutyuv filter in FFmpeg allows you to manipulate the individual luminance (Y) and chrominance (U and V) channels of a video stream using mathematical expressions compiled into lookup tables. By targeting these color components independently, you can alter brightness, adjust color balance, modify saturation, or apply custom color grading. This guide explains the filter's syntax, built-in variables, and practical examples for precise per-channel manipulation.

Basic Syntax and Variables

The lutyuv filter accepts expressions for the y, u, and v planes. If an expression is omitted for a channel, that channel remains unchanged.

ffmpeg -i input.mp4 -vf "lutyuv=y='expression':u='expression':v='expression'" output.mp4

Common variables available within expressions include:

  • val: The input value of the current pixel in the plane.
  • clipval: The input value clipped to the valid pixel range.
  • minval: The minimum allowed value for the channel (typically 0 or 16 for limited-range Y).
  • maxval: The maximum allowed value for the channel (typically 255 or 235 for limited-range Y).
  • w and h: The width and height of the video frame.

In standard 8-bit YUV (such as yuv420p), the Y channel represents brightness (0–255 in full range), while U and V represent color differences centered around 128 (chroma neutral).


Practical Examples

1. Adjusting Luminance (Y Channel)

To increase brightness, add a fixed value to the Y channel:

ffmpeg -i input.mp4 -vf "lutyuv=y=val+30" -c:a copy output.mp4

To increase contrast, expand values around the mid-luma level (128):

ffmpeg -i input.mp4 -vf "lutyuv=y='(val-128)*1.3+128'" -c:a copy output.mp4

2. Removing Color (Grayscale)

To remove all color data without re-encoding into a single-plane pixel format, set both the u and v channels to their neutral center value (128):

ffmpeg -i input.mp4 -vf "lutyuv=u=128:v=128" -c:a copy output.mp4

3. Adjusting Color Saturation (U and V Channels)

Saturation is modified by scaling the difference between the current chrominance value and 128.

To increase saturation by 50%:

ffmpeg -i input.mp4 -vf "lutyuv=u='(val-128)*1.5+128':v='(val-128)*1.5+128'" -c:a copy output.mp4

To decrease saturation by 50%:

ffmpeg -i input.mp4 -vf "lutyuv=u='(val-128)*0.5+128':v='(val-128)*0.5+128'" -c:a copy output.mp4

4. Inverting Specific Channels

To invert brightness while keeping colors intact:

ffmpeg -i input.mp4 -vf "lutyuv=y=maxval-val" -c:a copy output.mp4

To invert the chroma channels to create inverted color tones:

ffmpeg -i input.mp4 -vf "lutyuv=u=maxval-val:v=maxval-val" -c:a copy output.mp4

5. Tinting Video (Color Shifting)

You can introduce color casts by shifting the neutral chroma values. Adding value to the v channel shifts the image toward magenta/red, while subtracting shifts it toward green:

ffmpeg -i input.mp4 -vf "lutyuv=v=val+25" -c:a copy output.mp4

Adding value to the u channel shifts the image toward blue, while subtracting shifts it toward yellow:

ffmpeg -i input.mp4 -vf "lutyuv=u=val+30" -c:a copy output.mp4

High Bit-Depth Considerations

If you work with 10-bit or 12-bit video formats (e.g., yuv420p10le), the neutral chroma point and maximum values change. For 10-bit video:

  • maxval becomes 1023.
  • Neutral chroma shifts from 128 to 512 ((maxval+1)/2).

To write bit-depth agnostic expressions for chroma operations, calculate the neutral point dynamically:

ffmpeg -i input.mp4 -vf "lutyuv=u='(val-(maxval+1)/2)*1.2+(maxval+1)/2'" -c:a copy output.mp4