Skip to main content

Crate av_denoise

Crate av_denoise 

Source
Expand description

§av-denoise

Fast and efficient NLMEANS video denoising using CubeCL.

This project is heavily inspired by KNLmeansCL alongside FFmpeg’s nlmeans implementation but is built to be a more standalone tool and also make use of more modern tooling to better leverage modern hardware instead of relying on the now rather outdated OpenCL.

§Table of contents

§Features

  • One dial - the --preset ladder (veryfastveryslow) bundles algorithm, temporal radius, and search radius. base is the default.
  • Automatic noise handling - the hq variant measures the noise level, the grain’s spatial correlation, and per-plane strength for every scene. Film grain and encoder grain are seen at their true level, and --hq-sigma-scale nudges the measurement when your eye disagrees.
  • Temporal denoising with motion awareness - up to 17-frame windows, per-neighbour block-match confidence, and opt-in on-GPU motion compensation (--motion-compensation).
  • Luma, chroma, and YUV444 kernels - spatial or temporal, each plane individually tunable.
  • Prefilters - on-GPU bilateral and NLM-pilot reference clips, or supply your own guide via the library.
  • Library and binary - y4m over a pipe, or direct file ingestion via FFMS2 with scene-parallel workers.
  • Fast! - around 2x FFmpeg’s nlmeans_opencl at matched settings. Piped input can’t parallelize across scenes, so file input makes the best use of big GPUs.

§Tuning guide

The defaults are measured, not guessed. Start with them, judge the result by eye, and adjust one knob at a time using the situations below.

§Start here

av-denoise nlmeans --input noisy.mkv | ffmpeg -f yuv4mpegpipe -i - -c:v libsvtav1 clean.mkv

This runs the base preset: the hq variant with a 5-frame temporal window (radius of 2) and fully automatic noise handling. The noise level, the grain’s spatial correlation, and the per-plane strength are all measured per scene, so most sources need nothing else.

--input also takes - (or pipe:0) to read a y4m stream from standard input, and pipe:N for an inherited file descriptor:

ffmpeg -i noisy.mkv -pix_fmt yuv420p -f yuv4mpegpipe - \
  | av-denoise nlmeans --input - \
  | ffmpeg -f yuv4mpegpipe -i - -c:v libsvtav1 clean.mkv

Piped input has no scene detection, so the temporal window slides across the whole stream and --workers does not apply.

Your main dial is --preset. Go up the ladder (slow, veryslow) for noisier sources or when quality matters more than time. Go down (fast, veryfast) when speed is more important.

SymptomFirst thing to trySecond
Grain or noise still visibleone preset higher--hq-sigma-scale 1.1
Fine texture getting scrubbed--hq-sigma-scale 0.9lower --strength slightly
Smearing or ghosting on motion--motion-compensationone preset lower
Colour speckle survives--chroma-strength up-
Too slowcheck the GPU is actually selectedone preset lower

§Still too noisy

Work through these in order.

  1. Go up a preset. Noise and grain are independent frame to frame, so a deeper temporal window removes them more effectively than any strength increase. This is the strongest lever in the tool.
  2. Enable --motion-compensation on footage with real movement, so the deeper window keeps finding usable matches instead of falling back to the current frame.
    • For Anime sources, you may not want to enable this option. Anime sources typically cope with high motion much more effectively, and introducing motion compensation can work against you.
  3. Nudge --hq-sigma-scale up (try 1.1, then 1.2). This tells the denoiser the noise is a little stronger than it measured, and everything downstream (strength, patch matching, motion confidence) adapts together. Increase in small steps, judging by eye each time.

§Losing detail

The same dial works downward: --hq-sigma-scale 0.9 tells it the source is cleaner than measured. If texture is still being scrubbed after that, lower --strength a little.

The rule of thumb for choosing between the two:

  • --hq-sigma-scale says how noisy the source really is
  • --strength says how aggressively to clean at that noise level.

Prefer the sigma scale first. The noise level also steers patch matching and motion confidence, so correcting it fixes the cause rather than the symptom.

§Common situations

  • Old live action, heavy film grain. Real grain is spatially correlated and hides from naive estimators. The estimator here measures it from frame-to-frame residuals, so start with plain --preset slow --motion-compensation before reaching for any manual value. If it still reads slightly weak to your eye, --hq-sigma-scale 1.1 is the intended fix.
  • Mostly clean sources. fast or veryfast is usually enough, and over-denoising a clean source only costs detail. If you only want the light grain layer gone, stay at a low preset and let the automatic strength do its thing.
  • Colour speckle. Chroma already gets its own measured strength, but stubborn colour noise can take --chroma-strength above the default without touching luma.
  • Fast motion looks smeary. Enable --motion-compensation first. If a scene still trails, drop one preset (a shallower window has less material to mis-blend).

§What not to do

These exist for debugging, calibration work, and unusual sources. Reaching for them first usually makes things worse.

  • --hq-sigma pins the noise level to a fixed value, which disables the per-scene measurement entirely. --hq-sigma-scale keeps the measurement and nudges it, which is almost always what you actually want.
  • Raising --strength to fight leftover grain. Grain that survives means the noise level read low, and extra strength scrubs detail before it removes grain. Fix the level (--hq-sigma-scale) instead.
  • --hq-no-noise-floor, --hq-no-auto-strength, --hq-no-temporal-confidence switch off measured machinery. They are comparison and debugging switches, not quality options.
  • --hq-thsad-scale, --mc-blksize, --mc-overlap, --mc-search, --mc-pyramid-levels tune the motion machinery’s internals. The defaults are calibrated together.
  • --prefilter (the NLM pilot and bilateral modes) changes what patch matching sees, and under the hq variant’s calibrated automatic handling both modes measured neutral at best on default settings. They exist for experimentation and for library users supplying their own reference clip, not as a default quality upgrade.
  • --search-radius and --patch-radius reshape the whole matching problem, and every other default is tuned around them. Cost grows quadratically with the search radius, and the presets already adjust these parameters based on exhaustive tuning.
  • The cpu accelerator is for testing the pipeline, not for real encodes.

§Benchmarks

Numbers below come from scripts/bench_runs.py (just compare-perf), which pipes each tool to ffmpeg -f null - so the encoder is not measured. Throughput is total frames divided by wall-clock elapsed.

  • Input is a 3,450-frame 1080p FFV1 clip.
  • av-denoise using the vulkan backend.
  • Running on a AMD AI Pro R9700 (AMD 9070XT equivalent) GPU.
  • These tables measure the nlmeans algorithm at veryfast-preset settings, not the base default.

§Apples-to-apples spatial NL-means (strength 1.0)

Matched patch and search sizes on both tools, av-denoise uses radii compared to ffmpeg which takes the absolute size.

patch / searchav-denoise (fps)ffmpeg nlmeans_opencl (fps)speedup
p=5, r=1172.5730.25~2.40x
p=7, r=1542.4116.33~2.60x
p=9, r=1541.8416.26~2.57x

§av-denoise feature cost (strength 1.0, default patch/search)

All luma+chroma. Spatial baseline is the reference. Lower fps = more work.

runfpsnotes
spatial baseline97.25--temporal-radius 0
spatial + bilateral prefilter93.50adds one on-GPU pass per frame
temporal r=172.733-frame window
temporal r=262.075-frame window
temporal r=1 + motion comp64.03hierarchical block matching enabled
temporal r=2 + motion comp54.29
temporal r=1 + prefilter69.58
full r=1 (temporal+MC+prefilter)60.97
full r=2 (temporal+MC+prefilter)52.18

Reproduce with just compare-perf (config: scripts/bench_runs.toml).

§Hardware support

The project supports the following accelerators/gpus:

  • AMD GPUs (via the rocm or vulkan features)
  • Intel GPUs (via the vulkan feature)
  • Nvidia GPUs (via the cuda or vulkan features)
  • Apple Silicon (via the metal feature)
  • CPU (via the cpu feature)
    • WARNING! The CPU backend within CubeCL is still very new, and is not as optimised as a manually written kernel.
      As such, I do not recommend using this backend outside of testing.

§Notes about the JIT

It is important to note that av-denoise internally uses a JIT (Just In Time) compiler for its kernels; this means that the kernels are compiled and optimised for your specific hardware at runtime. As such, the first a couple of calls will have significant overhead as the system compiles, optimises and caches the kernels.

Additionally, because the kernels are compiled at runtime, whatever environment you run the tool in, must also provide access to the hardware specific headers and compilers.

This primarily has the following impacts:

  • The rocm backend requires the AMD HIP compiler and headers, typically vendored via the ROCm dev SDK.
  • The cuda backend requires the NVIDIA CUDA headers and nvcc, typically vendored via the CUDA devel toolkit.
  • The cpu backend should not require any special dependencies directly, as it should already be vendored.
  • The vulkan and metal backends should “just work” on non-containerised hosts. If you are building for docker, then the vulkan backend requires vulkan-icd-loader and then the relevant GPU specific driver, i.e. vulkan-radeon or vulkan-intel.

Since both the CUDA and ROCm backends are very heavy in terms of dependencies, I recommend just using the vulkan backend for those devices. It should be more or less the same performance, without all the library headache.

§Configure compilation cache directory

Set AV_DENOISE_COMPILATION_CACHE=/some/dir to redirect the compiled-kernel and autotune caches to a specific directory (overrides whatever is in cubecl.toml). Library users can call av_denoise::apply_compilation_cache_env() before Denoiser::create to honor the same env var from their own binary.

§Installing

av-denoise is available both in library and binary format, by default only the vulkan feature is enabled, since that is typically the default accelerators you will want to use.

When compiling the binary, enable the binary feature. It pulls in both ingestion paths (FFMS2 for file input, y4m for piped input), so there’s nothing else to pick between.

The following (non-accelerator) features are available:

  • binary - Enables the dependencies and code required to compile av-denoise as a binary.
    • This pulls in ffms2 as hard dependencies. This means you must install ffms2 before you can compile and link the binary.

§Cargo install

cargo install --locked av-denoise --features binary

§From source

git clone https://github.com/ChillFish8/av-denoise.git
cargo build --release --features binary
cp ./target/release/av-denoise ./av-denoise

§As a library

cargo add av-denoise

§Example commands

Almost everything is handled by two dials: --preset for how hard to work, and --hq-sigma-scale to nudge the measured noise level when your eye disagrees with it. Each example below changes one thing from the defaults.

Clean up a noisy file. The defaults measure the noise per scene and pick their own strength.

av-denoise nlmeans --input noisy.mkv | ffmpeg -f yuv4mpegpipe -i - -c:v libsvtav1 clean.mkv

A noisier source. Go up the preset ladder. A deeper temporal window is the strongest lever in the tool.

av-denoise nlmeans --preset slow --input noisy.mkv \
  | ffmpeg -f yuv4mpegpipe -i - -c:v libsvtav1 clean.mkv

Still grainy after raising the preset. Tell it the noise is a little stronger than it measured. Move in steps of 0.1 and judge by eye.

av-denoise nlmeans --preset slow --hq-sigma-scale 1.1 --input noisy.mkv \
  | ffmpeg -f yuv4mpegpipe -i - -c:v libsvtav1 clean.mkv

Fine texture getting scrubbed. The same dial works downward.

av-denoise nlmeans --hq-sigma-scale 0.9 --input noisy.mkv \
  | ffmpeg -f yuv4mpegpipe -i - -c:v libsvtav1 clean.mkv

Live action with real movement. Motion compensation keeps the deeper window finding usable matches instead of smearing. Anime is often better off without it.

av-denoise nlmeans --preset slow --motion-compensation --input noisy.mkv \
  | ffmpeg -f yuv4mpegpipe -i - -c:v libsvtav1 clean.mkv

Brightness only, for speed. Both planes are cleaned by default. Narrow to luma when the colour is already clean and you want the time back.

av-denoise nlmeans --channel-mode luma --input noisy.mkv \
  | ffmpeg -f yuv4mpegpipe -i - -c:v libsvtav1 clean.mkv

Pick a specific GPU. Both flags are global, so they work either side of the subcommand.

av-denoise --accelerators vulkan --device discrete:1 nlmeans --input noisy.mkv \
  | ffmpeg -f yuv4mpegpipe -i - -c:v libsvtav1 clean.mkv
Advanced examples — fixed variant, manual per-plane strength, explicit backends

These pin --preset veryfast to select the fast variant, which makes --strength an absolute value rather than the noise multiplier the hq variant applies. That trades away the per-scene measurement, so treat them as calibration and debugging recipes rather than a starting point. If your goal is a better-looking result, the dials above are the ones to reach for first — see What not to do.

Y/UV Denoise - ROCm/Vulkan - On GPU 1 - Light Denoise - Spatial - strength=luma:1.2,choma:1.2

av-denoise nlmeans \
  --preset veryfast \
  --accelerators rocm,vulkan \
  --device discrete:1 \
  --channel-mode luma,chroma \
  --strength 1.2 \
  --input ./sample.mkv \
    | ffmpeg -hide_banner -loglevel info -y -f yuv4mpegpipe -i - -c:v ffv1 ./output.mkv

Y/UV Denoise - Vulkan - On iGPU 0 - Split Denoise - Temporal (radius=1) - strength=luma:2.0,choma:1.5

av-denoise nlmeans \
  --preset veryfast \
  --accelerators vulkan \
  --device integrated:0 \
  --channel-mode luma,chroma \
  --temporal-radius 1 \
  --luma-strength 2.0 \
  --chroma-strength 1.5 \
  --input ./sample.mkv \
    | ffmpeg -hide_banner -loglevel info -y -f yuv4mpegpipe -i - -c:v ffv1 ./output.mkv

Y-Only Denoise - Metal - On GPU 0 - Heavy Denoise - Spatial - strength=luma:3.0

av-denoise nlmeans \
  --preset veryfast \
  --accelerators metal \
  --device discrete:0 \
  --channel-mode luma \
  --strength 3.0 \
  --input ./sample.mkv \
    | ffmpeg -hide_banner -loglevel info -y -f yuv4mpegpipe -i - -c:v ffv1 ./output.mkv

YUV Fused Denoise - Vulkan - On Default GPU - Medium Denoise - Spatial - strength=yuv:2.0

av-denoise nlmeans \
  --preset veryfast \
  --accelerators vulkan \
  --channel-mode yuv \
  --strength 2.0 \
  --input ./sample.mkv \
    | ffmpeg -hide_banner -loglevel info -y -f yuv4mpegpipe -i - -c:v ffv1 ./output.mkv

Y/UV Denoise - Vulkan - On GPU 0 - Temporal (radius=2) + Motion Compensation - Anime / Heavy Motion

av-denoise nlmeans \
  --preset veryfast \
  --accelerators vulkan \
  --device discrete:0 \
  --channel-mode luma,chroma \
  --temporal-radius 2 \
  --motion-compensation \
  --strength 1.5 \
  --input ./anime.mkv \
    | ffmpeg -hide_banner -loglevel info -y -f yuv4mpegpipe -i - -c:v ffv1 ./output.mkv

§Binary usage

§Global options

Fast and efficient video denoising

Usage: av-denoise [OPTIONS] <COMMAND>

Commands:
  nlmeans  Denoise with the non-local means family
  help     Print this message or the help of the given subcommand(s)

Options:
      --preset <PRESET>
          Speed vs quality dial.

          `veryfast` is the fastest and lowest-quality end of the dial. For `nlmeans` it runs the `fast` variant with no temporal window and matches this tool's original default behavior.

          `fast`, `base`, `slow`, and `veryslow` all run the `hq` variant and widen the temporal window going up the list, from a 1-frame radius at `fast` to an 8-frame radius at `veryslow`. `slow` and `veryslow` also widen the search radius.

          `base` is the default.

          [default: base]

  -A, --accelerators <ACCELERATORS>
          Which hardware backends to try, in order of preference.

          The first backend that initialises is used. If none work the program exits with an error.

          The list is comma-separated, for example `vulkan,cpu`.

          [default: vulkan]

  -d, --device <DEVICE>
          Which device to use on the chosen backend.

          Accepted values:

          `default` lets the backend pick.

          `discrete[:N]` picks the Nth discrete GPU (default 0). Works on CUDA, ROCm, and Vulkan.

          `integrated[:N]` picks the Nth integrated GPU. Vulkan only.

          `virtual[:N]` picks the Nth virtual GPU. Vulkan only.

          `cpu` uses the software backend.

          [default: default]

      --channel-mode <CHANNEL_MODE>
          Which planes of the video to clean (comma-separated).

          `luma` cleans only the brightness plane. Colour passes through untouched, which is cheaper when only luma carries grain.

          `chroma` cleans only the colour planes at their native size.

          `luma,chroma` cleans both as two independent passes. This is the default and is usually what you want for noisy footage.

          `yuv` cleans all three planes in one fused pass.

          `yuv` needs a YUV444 source and cannot be combined with the other modes.

          Possible values:
          - luma:   Clean only the brightness plane (Y). Colour passes through
          - chroma: Clean only the colour planes (U, V). Brightness passes through
          - yuv:    Clean all three planes together in one pass. Needs a YUV444 source and cannot be combined with the other modes

          [default: luma,chroma]

      --progress
          Shows a progress bar for the denoising pass when `--input` names a file.

          Off by default because that bar runs for the whole encode, and anything else writing to the terminal, such as the ffmpeg the output is usually piped into, scrambles it. Scene detection shows its bar without this flag, since it finishes before any output is written.

          Neither bar is drawn unless stderr is a terminal, and there is nothing to show a bar for on piped input.

  -h, --help
          Print help (see a summary with '-h')

§nlmeans

Denoise with the non-local means family.

`nlmeans` compares small patches of pixels and averages the ones that look alike, either inside a single frame or across a temporal window.

Usage: av-denoise nlmeans [OPTIONS] --input <INPUT>

Options:
  -i, --input <INPUT>
          Where to read frames from.

          A path opens the file with ffms2 and splits the work by scene. Any container or codec supported by ffmpeg works.

          `-` or `pipe:0` reads a y4m stream from standard input.

          `pipe:N` for `N` of 3 or above reads a y4m stream from an inherited file descriptor.

          Piped input has no scene detection, so the temporal window slides across the whole stream.

          A file whose name would otherwise be read as a pipe is reachable by prefixing it, for example `./-`.

          The source must be 8-bit. 10 or 12-bit inputs are rejected with a clear error message.

      --preset <PRESET>
          Speed vs quality dial.

          `veryfast` is the fastest and lowest-quality end of the dial. For `nlmeans` it runs the `fast` variant with no temporal window and matches this tool's original default behavior.

          `fast`, `base`, `slow`, and `veryslow` all run the `hq` variant and widen the temporal window going up the list, from a 1-frame radius at `fast` to an 8-frame radius at `veryslow`. `slow` and `veryslow` also widen the search radius.

          `base` is the default.

          [default: base]

  -A, --accelerators <ACCELERATORS>
          Which hardware backends to try, in order of preference.

          The first backend that initialises is used. If none work the program exits with an error.

          The list is comma-separated, for example `vulkan,cpu`.

          [default: vulkan]

  -W, --workers <WORKERS>
          How many scenes to clean in parallel.

          Each worker uses its own GPU memory for the frame ring buffer, so higher values trade GPU memory for throughput.

          `1` is valid and useful for debugging. Defaults to 2 when unset.

          Ignored for piped input, which cannot be split by scene.

  -d, --device <DEVICE>
          Which device to use on the chosen backend.

          Accepted values:

          `default` lets the backend pick.

          `discrete[:N]` picks the Nth discrete GPU (default 0). Works on CUDA, ROCm, and Vulkan.

          `integrated[:N]` picks the Nth integrated GPU. Vulkan only.

          `virtual[:N]` picks the Nth virtual GPU. Vulkan only.

          `cpu` uses the software backend.

          [default: default]

      --variant <VARIANT>
          Which variant to run.

          `fast` uses fixed weighting and is the cheapest option. `hq` calibrates its weighting to the noise level, measured automatically per frame (see `--hq-sigma` to override).

          Defaults to whatever `--preset` selects.

      --channel-mode <CHANNEL_MODE>
          Which planes of the video to clean (comma-separated).

          `luma` cleans only the brightness plane. Colour passes through untouched, which is cheaper when only luma carries grain.

          `chroma` cleans only the colour planes at their native size.

          `luma,chroma` cleans both as two independent passes. This is the default and is usually what you want for noisy footage.

          `yuv` cleans all three planes in one fused pass.

          `yuv` needs a YUV444 source and cannot be combined with the other modes.

          Possible values:
          - luma:   Clean only the brightness plane (Y). Colour passes through
          - chroma: Clean only the colour planes (U, V). Brightness passes through
          - yuv:    Clean all three planes together in one pass. Needs a YUV444 source and cannot be combined with the other modes

          [default: luma,chroma]

      --prefilter <PREFILTER>
          Reference image used when comparing patches.

          Omitted (the default) means no prefilter, for both variants.

          `none` forces the noisy input directly (the cheapest option). This is the same as leaving the flag unset.

          `nlm` or `nlm:<strength_scale>` runs a windowed spatial NLM pass first and compares patches against that cleaner image. `strength_scale` multiplies the main pass strength for the pilot pass. Bare `nlm` uses the calibrated default.

          `bilateral:<sigma_s>,<sigma_r>` runs a quick on-GPU bilateral blur first, then compares patches against that cleaner image.

          `sigma_s` is the spatial blur radius in pixels, greater than 0 and at most 11.0 (anything beyond this is insane.)

          `sigma_r` is the colour-similarity threshold, greater than 0. `(0, 1]` is the typical range for normalised pixel data. There is no enforced upper bound.

          A good starting point is `bilateral:3.0,0.02`.

          Prefiltering keeps more detail at the cost of one extra GPU pass per frame.

      --progress
          Shows a progress bar for the denoising pass when `--input` names a file.

          Off by default because that bar runs for the whole encode, and anything else writing to the terminal, such as the ffmpeg the output is usually piped into, scrambles it. Scene detection shows its bar without this flag, since it finishes before any output is written.

          Neither bar is drawn unless stderr is a terminal, and there is nothing to show a bar for on piped input.

      --temporal-radius <TEMPORAL_RADIUS>
          How many neighbouring frames to look at on each side when cleaning a frame.

          `0` means no temporal blending. Each frame is cleaned on its own.

          Values above `0` look at that many frames before and after the current one.

          Larger values give stronger cleanup but use more memory and add latency.

          When `--input` names a file this is reset at every scene change, so raising it never causes blending across cuts.

          Defaults to whatever `--preset` selects.

      --search-radius <SEARCH_RADIUS>
          How far away to look for similar patches inside a frame.

          Larger values find more matches but cost quadratically more work.

          Defaults to whatever `--preset` selects.

      --patch-radius <PATCH_RADIUS>
          Size of each patch being compared. The patch is `(2*patch_radius + 1)` pixels square.

          Larger patches preserve fine structure better but cost more GPU memory. Library default is 4.

      --strength <STRENGTH>
          Cleaning strength. Higher numbers smooth more.

          Must be a finite number greater than 0.

          The default depends on the variant. `fast` defaults to 1.2. `hq` interprets strength as a multiplier on the measured noise level. Its default is calibrated automatically, adapting to the temporal radius and to which plane (luma or chroma) is being denoised, so lower and higher radii each get their own measured value.

          This value applies to both planes unless `--luma-strength` or `--chroma-strength` is set.

      --luma-strength <LUMA_STRENGTH>
          Strength override for the brightness plane only.

          Falls back to `--strength` (or the library default) when not set.

          Ignored when luma is not being denoised, or when `--channel-mode yuv` is used.

      --chroma-strength <CHROMA_STRENGTH>
          Strength override for the colour planes only.

          Falls back to `--strength` (or the library default) when not set.

          Ignored when chroma is not being denoised, or when `--channel-mode yuv` is used.

      --self-weight <SELF_WEIGHT>
          How much weight to give the centre pixel itself when averaging.

          Library default is 1.0. Must be a finite number `>= 0`.

          Setting to 0 gives pure NLM (centre pixel only counts if a similar patch was found nearby).

      --hq-sigma <HQ_SIGMA>
          How noisy the source is. Leave it unset for almost all uses.

          The noise level is measured automatically per scene when this is not set. Set it only when the automatic estimate misjudges a source and you want to pin the value.

          Small values mean light grain and larger values mean heavier noise. `3` is subtle grain, `6` is clearly visible grain, `12` and up is heavy noise.

      --hq-no-auto-strength
          Treat `--strength` as an absolute value instead of a multiplier on `--hq-sigma`

      --hq-no-noise-floor
          Keep the expected-noise floor inside patch distances instead of subtracting it

      --hq-no-temporal-confidence
          Disable per-block temporal confidence weighting for the `hq` variant.

          By default HQ block-matches each temporal neighbour against the centre frame and lets a poor match suppress that neighbour's contribution, instead of blurring in occluded or changed content. Setting this applies temporal weights uniformly no matter how well a neighbour matches.

          Only takes effect when `--temporal-radius` is above 0.

      --hq-thsad-scale <HQ_THSAD_SCALE>
          Multiplier on the per-block mismatch threshold temporal confidence weighting tolerates before a neighbour's contribution starts dropping.

          Higher values tolerate larger mismatches. Library default is 1.0. Ignored when `--hq-no-temporal-confidence` is set.

      --hq-sigma-scale <HQ_SIGMA_SCALE>
          Nudges the automatically measured noise level up or down.

          `1.0` (the library default) keeps the measurement as-is. Raise it a little when the cleaned result still looks noisy. Lower it when detail is getting scrubbed.

          This differs from `--strength` because the noise level also sets the patch-distance noise floor and the motion-confidence floor, not just the weighting.

          Has no effect when `--hq-sigma` pins the noise level.

      --motion-compensation
          Turn on motion compensation for temporal denoising.

          When the camera or content moves between frames, the brightness at the same `(x, y)` is different content in each frame.

          Without help, temporal cleanup will blur moving edges.

          Motion compensation looks at where each block of pixels moved between frames, then shifts neighbour frames to line up with the current frame before cleaning.

          This keeps detail sharp on anime, fast pans, and action footage.

          The tracking strategy adapts automatically to `--temporal-radius`.

          Has no effect when `--temporal-radius 0`.

      --mc-blksize <MC_BLKSIZE>
          Size of each motion-search block, in pixels. Must be even.

          Larger blocks are more stable but track motion less accurately on small details.

          Only takes effect with `--motion-compensation`. Defaults to 16 when unset.

      --mc-overlap <MC_OVERLAP>
          How many pixels neighbouring motion blocks may overlap.

          Must be less than `--mc-blksize`. Higher overlap smooths the transitions between blocks but does more work.

          Only takes effect with `--motion-compensation`. Defaults to 8 when unset.

      --mc-search <MC_SEARCH>
          How many pixels of motion to search for at the finest level.

          The coarse pyramid pass reaches further (search radius times 2 for a 2-level pyramid), so for typical content the default is fine.

          Raise it for very fast motion.

          Only takes effect with `--motion-compensation`. Defaults to 4 when unset.

      --mc-pyramid-levels <MC_PYRAMID_LEVELS>
          How many levels the motion-search pyramid uses.

          `1` does a single full-resolution search (cheaper, weaker on large motion).

          `2` (default) does a coarse pass on a half-size image first, then refines at full resolution.

          This handles much larger motion at modest extra cost.

          Only takes effect with `--motion-compensation`. Defaults to 2 when unset.

  -h, --help
          Print help (see a summary with '-h')

Re-exports§

pub use cache::COMPILATION_CACHE_ENV;
pub use cache::CacheAlreadyInitialisedError;
pub use cache::apply_compilation_cache_env;
pub use device::Device;

Modules§

accelerate
cache
device
sniff

Structs§

Denoiser
DenoiserOptions
User-facing denoiser configuration. Build with DenoiserOptions::builder().
HqParams
Parameters for the quality-focused nlmeans-hq variant. The noise level drives both the effective strength and the distance floor, so weighting adapts to how noisy the source actually is.
NlmTuning
NLM tuning knobs. All optional; missing fields fall back to library defaults.

Enums§

Algorithm
Which denoising algorithm variant to run.
ChannelMode
How to apply denoising to the input frame channels.
DenoiserError
Errors surfaced from the high-level Denoiser.
DenoisingMode
Standard spatial or temporal-aware denoising.
MotionCompensationMode
How motion compensation is configured for a denoise pass.
MotionEstimation
Strategy for estimating a temporal neighbour’s motion vector.
PrefilterMode
How the per-frame reference clip is produced.

Constants§

DEFAULT_PILOT_STRENGTH_SCALE
Measured default for the pilot pass’s relative strength, a multiplier on the main pass strength. A calibration sweep across noise levels found the XPSNR plateau optimum for PrefilterMode::NlmSpatial at this value.