How to Use FFmpeg lutyuv Filter for Pixel Math
This article provides a practical guide on using the
lutyuv filter in FFmpeg to manipulate video frames at the
pixel level using mathematical equations. You will learn the syntax of
the filter, the key variables available for your expressions, and see
step-by-step examples of how to modify luminance, chrominance, and apply
coordinate-based visual effects directly to your video streams.
Understanding the lutyuv Filter
The lutyuv filter (Look-Up Table YUV) allows you to
alter the Y (Luminance), U (Blue-difference chroma), and V
(Red-difference chroma) channels of a video. FFmpeg evaluates your
mathematical equations for every pixel in the frame, generates a
256-element look-up table for 8-bit video, and maps the input pixel
values to the output values. This makes it highly efficient compared to
per-pixel real-time scripting.
Basic Syntax
The basic syntax for the filter is:
ffmpeg -i input.mp4 -vf "lutyuv=y='expression':u='expression':v='expression'" output.mp4You do not need to define all three channels. If you omit a channel, it remains unchanged.
Key Variables and Constants
You can use the following variables inside your mathematical expressions:
val: The input value of the current pixel (0–255 for 8-bit depth).w/h: The width and height of the video frame.x/y: The horizontal and vertical coordinates of the current pixel.pi: The mathematical constant \(\pi\).
FFmpeg supports standard arithmetic operators (+,
-, *, /) alongside functions like
sin(), cos(), pow(),
exp(), clip(val, min, max), and bitwise
operators.
Practical Examples
1. Adjusting Brightness and Contrast
To increase the brightness of a video, you can add a constant value to the Y (luminance) channel. To adjust contrast, multiply the luminance value relative to the midpoint (128).
Increase Brightness:
ffmpeg -i input.mp4 -vf "lutyuv=y='clip(val+30, 0, 255)'" output.mp4Increase Contrast:
ffmpeg -i input.mp4 -vf "lutyuv=y='clip((val-128)*1.4+128, 0, 255)'" output.mp4Note: The
clip()function prevents the pixel values from exceeding the standard 8-bit range of 0 to 255.
2. Inverting Color Channels
To invert the brightness (creating a negative-like effect) while keeping colors intact, subtract the input luminance value from the maximum value of 255.
ffmpeg -i input.mp4 -vf "lutyuv=y='255-val'" output.mp4To completely invert the colors as well, invert the U and V channels. In YUV color space, chroma channels range from 0 to 255 with 128 representing neutral gray, so the formula offsets around the midpoint:
ffmpeg -i input.mp4 -vf "lutyuv=y='255-val':u='256-val':v='256-val'" output.mp43. Creating a Horizontal Gradient (Coordinate-Based Math)
Because lutyuv gives you access to the x
(horizontal pixel position) and w (total width) variables,
you can create gradients that change across the screen.
The following command gradually darkens the video from left to right by multiplying the luminance channel by a factor that scales from 1 at the left edge to 0 at the right edge:
ffmpeg -i input.mp4 -vf "lutyuv=y='val*(1-(x/w))'" output.mp44. Color Tinting (Manipulating Chrominance)
You can apply custom color tints by forcing static mathematical values onto the chroma channels (U and V) while leaving the luminance (Y) untouched.
Apply a Warm/Red Tint:
ffmpeg -i input.mp4 -vf "lutyuv=v='160'" output.mp4Apply a Cool/Blue Tint:
ffmpeg -i input.mp4 -vf "lutyuv=u='160'" output.mp4
Tips for Writing Expressions
- Always Clip Output: When performing addition or
multiplication, values can easily exceed 255 or fall below 0. Wrap your
math in
clip(expression, 0, 255)to prevent rendering artifacts. - Use Floating Point Numbers: To ensure precise
division and scaling, write numbers with decimals (e.g.,
1.5instead of3/2). - Mind the Color Space: Remember that YUV is not RGB. Y controls light, while U and V control color differences. Modifying Y preserves color relationships, whereas modifying U and V shifts the overall color spectrum.