#[non_exhaustive]pub enum EffectKind {
Show 17 variants
ColorCorrect {
brightness: Param,
contrast: Param,
saturation: Param,
temperature: Param,
tint: Param,
},
Blur {
radius: Param,
},
Sharpen {
amount: Param,
},
Vignette {
amount: Param,
},
FilmGrain {
luma_strength: Param,
chroma_strength: Param,
},
Glow {
threshold: Param,
radius: Param,
intensity: Param,
},
ColorWheels {
shadows_lift: [Param; 3],
midtones_gamma: [Param; 3],
highlights_gain: [Param; 3],
},
Curves {
master: Vec<[f32; 2]>,
red: Vec<[f32; 2]>,
green: Vec<[f32; 2]>,
blue: Vec<[f32; 2]>,
},
Hsl {
hue_shift: Param,
saturation: Param,
lightness: Param,
},
Lut {
path: String,
},
ChromaKey {
key_color: [f32; 3],
similarity: Param,
softness: Param,
},
LumaMask {
invert: bool,
},
ShapeMask {
x: Param,
y: Param,
width: Param,
height: Param,
invert: bool,
},
MotionBlur {
shutter_angle: Param,
sub_frames: u8,
},
Raw {
step: FilterStep,
},
Volume {
gain_db: Param,
},
AudioRaw {
step: FilterStep,
},
}Expand description
A typed effect that a clip can carry. #[non_exhaustive]: more kinds are added
over time, so external matchers must include a _ arm.
The set grows as effect nodes are wired into the GPU bridge; each kind documents
the ff-filter step / ff-render node it maps to.
§Serialization compatibility (#1709)
Every parameter field carries its neutral as a serde default, so a document
serialized before that field existed still loads — the missing field simply takes
its neutral and the effect renders as it did then. A new field added to an existing
variant must follow this, and its neutral must equal the default the field
reports from descriptor; the
deserializing_omitted_effect_fields_should_yield_descriptor_defaults test fails if
they drift apart.
The exception is a field with no meaningful neutral — Raw::step and
AudioRaw::step carry a whole FilterStep, which has no neutral
value, so they stay required.
The trade-off is deliberate: because parameters are optional on the wire, a truncated or hand-edited document also loads, with the missing parameters at their neutral, rather than being rejected.
Variants (Non-exhaustive)§
This enum is marked as non-exhaustive
ColorCorrect
Brightness / contrast / saturation / temperature / tint adjustment (the eq
filter on the CPU path, ff_render::ColorGradeNode on the GPU).
Neutral parameters (brightness = 0.0, contrast = 1.0, saturation = 1.0,
temperature = 0.0, tint = 0.0, all constant) compile to no filter at all,
preserving bit-identical output.
temperature/tint are a GPU-only enrichment: the CPU eq fallback applies
brightness/contrast/saturation only and does not reproduce them (FFmpeg eq
has no such parameter), while the GPU-default path applies the full grade.
Fields
Blur
Gaussian blur (the gblur filter).
Sharpen
Unsharp-mask sharpen (the unsharp filter on the CPU path,
ff_render::SharpenNode on the GPU).
A single luma sharpening amount in [−1.5, 1.5] (negative blurs). Because
FFmpeg’s unsharp has no runtime-settable parameter, an animated amount
animates on the GPU-default path but renders its t = 0 value on the CPU
fallback.
Vignette
Vignette (the vignette filter on the CPU path, ff_render::VignetteNode
on the GPU).
A single normalised darkening amount in [0, 1] (0.0 = no vignette),
centred on the frame. The vignette filter re-evaluates its angle per frame,
so an animated amount animates on both paths.
FilmGrain
Temporal film grain (the noise filter on the CPU path,
ff_render::FilmGrainNode on the GPU).
Luma and chroma grain strengths in the noise filter’s [0, 100] scale
(0.0 = none). The grain pattern varies per frame on both paths; because
noise has no runtime-settable parameter, an animated strength animates on
the GPU-default path but renders its t = 0 value on the CPU fallback.
Fields
Glow
Glow / bloom (the compound split/curves/gblur/blend chain on the CPU
path, ff_render::GlowNode on the GPU).
Extracts highlights above threshold, blurs them by radius, and adds them
back weighted by intensity. An animated parameter animates on the GPU-default
path; the CPU renders its t = 0 value (the glow sub-filters have no runtime
parameter).
Fields
ColorWheels
Three-way (lift/gamma/gain) colour corrector (the curves filter on the CPU
path, ff_render::ColorWheelsNode on the GPU).
Each wheel is a per-channel [R, G, B] array. Neutral parameters
(shadows_lift = 0.0, midtones_gamma = 1.0, highlights_gain = 1.0, all
constant) compile to no filter at all. Because curves takes string options,
an animated parameter animates on the GPU-default path but renders its t = 0
value on the CPU fallback.
Fields
Curves
Per-channel tone curves (the curves filter on the CPU path,
ff_render::CurvesNode on the GPU).
Each curve is a list of [input, output] control points in [0, 1]. Unlike
the other kinds, a curve is a structural parameter, not a scalar, so it carries
no keyframeable Param; an empty set of curves is a no-op. The master curve
applies to every channel, then the per-channel curve.
Fields
Hsl
HSL adjustment (the hue filter on the CPU path, ff_render::HslNode on
the GPU).
A hue rotation in degrees, a saturation multiplier, and a lightness offset.
The CPU hue filter works in YUV (chroma rotation plus a luma-add
brightness), so it approximates the GPU node’s HSL-space adjustment within a
documented tolerance. Neutral parameters (hue_shift = 0.0,
saturation = 1.0, lightness = 0.0, all constant) compile to no filter.
Because hue’s options are string expressions, an animated parameter
animates on the GPU-default path but renders its t = 0 value on the CPU
fallback.
Fields
Lut
3D colour LUT (the lut3d filter on the CPU path, ff_render::LutNode on
the GPU), loaded from an Adobe .cube or Resolve .3dl file.
Like Curves, a LUT is a structural parameter (a file
path), not a scalar, so it carries no keyframeable Param; an empty path
is a no-op. On the GPU a file that cannot be loaded (missing, malformed, or
an unsupported extension) falls back to the CPU path.
ChromaKey
Chroma-key (green-screen removal): makes pixels near key_color
transparent (the chromakey filter on the CPU path, ff_render::ChromaKeyNode
on the GPU).
key_color is a structural RGB triple (each channel 0.0..=1.0), not a
keyframeable Param — the key colour is picked once, like a
Lut path. similarity (match radius) and softness (edge
feather) are keyframeable. A constant similarity = 0.0 removes nothing, so
it compiles to no filter. Because chromakey’s options are static, an
animated parameter animates on the GPU-default path but renders its t = 0
value on the CPU fallback (like Hsl).
Fields
LumaMask
Luma mask: multiplies the clip’s alpha by its own BT.709 luma (the geq
filter on the CPU path, ff_render::LumaMaskNode on the GPU). Bright pixels
stay opaque, dark pixels become transparent; invert uses 1 - luma.
This is a structural effect with no scalar Param — like Lut
and Curves, its “keyframeable per parameter” requirement is
satisfied vacuously (there is nothing to animate; invert is a one-time
toggle). The mask is the clip’s own frame, so no external mask source is
needed.
ShapeMask
Rectangular shape mask: keeps the clip opaque inside the rectangle and clears
the alpha outside (the geq filter on the CPU path, ff_render::ShapeMaskNode
on the GPU). invert swaps inside and outside.
x / y / width / height are keyframeable per-pixel Params (a moving
or resizing mask), so a constant rectangle compiles to the RectMask filter
and any animated bound uses RectMaskAnimated (the GPU animates per frame; the
CPU renders its t = 0 bounds, like ChromaKey). A constant
zero width or height masks nothing, so it compiles to no filter.
Fields
MotionBlur
Motion blur (the tblend filter on the CPU path, ff_render::MotionBlurNode
on the GPU): a per-clip exposure trail that blends each frame with the
accumulated previous output.
shutter_angle is keyframeable per the typed-effect model, but motion blur is
stateful — the trail accumulates across successive frames on one node
instance — so a stable shutter is required and the value at t = 0 is used on
both paths (the CPU tblend likewise has no runtime shutter parameter). A
constant shutter_angle = 0.0 is no blur, so it compiles to no filter.
sub_frames is a structural trail-length count (clamped 2..=8 by the GPU
node); the CPU tblend ignores it (it blends only the two most recent frames),
a documented GPU/CPU divergence.
Fields
Raw
Escape hatch: a raw FilterStep the typed model has no variant for yet
(Hue, HFlip, Crop, Denoise, …).
This is the only way to attach an untyped step, so every effect a clip
carries still lives in one ordered, id-addressed list: a raw step can be
enabled/disabled, reordered and removed through the *Effect commands like any
other effect. Its interior is opaque, though — the step’s own arguments are not
individually keyframeable Params and descriptor
reports no parameters for it. Prefer a typed kind whenever one exists.
Fields
step: FilterStepThe step rendered verbatim, in this effect’s position in the chain.
Volume
Audio gain in decibels (the volume filter) — an EffectDomain::Audio effect.
A neutral constant (0.0 dB) compiles to no filter at all, preserving
bit-identical audio. gain_db is keyframeable per the typed model, but
FFmpeg’s volume step carries no runtime-settable parameter here, so an
animated gain renders its t = 0 value (the same documented limitation as
Sharpen and MotionBlur).
AudioRaw
Escape hatch for a raw audio FilterStep the typed model has no variant for
(ACompressor, NoiseReduce, ParametricEq, …) — the audio counterpart of
Raw, and an EffectDomain::Audio effect.
Like Raw it is opaque: the step’s arguments are not individually keyframeable
Params and descriptor reports no parameters for it.
Fields
step: FilterStepThe step rendered verbatim, in this effect’s position in the audio chain.
Implementations§
Source§impl EffectKind
impl EffectKind
Sourcepub fn domain(&self) -> EffectDomain
pub fn domain(&self) -> EffectDomain
Which media stream this kind applies to (#1712).
A clip keeps one effect list for both domains; each derive path selects its own
domain, so the value here decides whether a kind reaches
Clip::video_effect_chain or
Clip::audio_effect_chain.
The match is exhaustive with no _ arm: a new EffectKind variant
fails to compile until its domain is declared, so a kind can never silently
default to the wrong pipeline (RK-003).
Sourcepub fn descriptor(&self) -> EffectDescriptor
pub fn descriptor(&self) -> EffectDescriptor
Host-facing introspection: the kind’s stable snake_case name and a
ParamDescriptor for every parameter (name, type, range, default, current
value), so a UI can render an editable parameter panel without hard-coding each
variant.
The match is exhaustive with no _ arm (per #1640): adding an
EffectKind variant without a descriptor here fails to compile, which
guarantees the descriptor stays complete for every variant. This is in-crate, so
#[non_exhaustive] does not force a wildcard arm (RK-003). Ranges and defaults
come from each parameter’s documented range on the variant; an open-ended range
uses f64::INFINITY as the upper bound.
Sourcepub fn to_filter_step(&self) -> Option<FilterStep>
pub fn to_filter_step(&self) -> Option<FilterStep>
Compiles this kind to the FilterStep that renders it, or None when the
kind is a no-op (a neutral, all-constant ColorCorrect,
matching the historical “skip eq when neutral” behaviour so output stays
bit-identical).
An all-constant kind compiles to the static FilterStep variant (Eq,
GBlur); any animated parameter compiles to the animated variant
(EqAnimated, GBlurAnimated).
Trait Implementations§
Source§impl Clone for EffectKind
impl Clone for EffectKind
Source§fn clone(&self) -> EffectKind
fn clone(&self) -> EffectKind
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read more