Skip to main content

av-denoise VapourSynth plugin (vsavd)

This is the home of av-denoise exposed as a VapourSynth plugin to fit within existing filtering pipelines. With caveats.

We provide typed interfaces for all the supported algorithms:

  • vsavd.Nl4d(...) for our best in class NL4D denoiser offering higher quality and more effective denoising over V-BM3D.
  • vsavd.NlmHQ(...) for our NLMeans-HQ algorithm which provides a higher quality and smarter denoising experience over base NLMeans.
  • vsavd.Nlm(...) for quick and dirt NLMeans mirroring FFmpeg's strength scaling.

All algorithms are temporal aware and have inbuilt motion compensation kernels.

Here be dragons! 🐉

VapourSynth's API restricts how av-denoise can operate and as a result, can produce a worse denoising experience compared to the CLI or direct Rust library usage.

The plugin smooths the noise estimate over the stream's history, like the CLI. A render from the start is consistent. Frames after a seek, or after a burst of requests wider than twice the thread count, can differ slightly for a while. In tests the drift lasted 20 or more frames after a seek. Unlike the CLI, the plugin does not reset the estimate at scene cuts.

Table of contents

Installing

Pre-built wheels are available for Linux, macOS and Windows, published to PyPI.

Please note that the wheels for Linux and Windows are compiled for vulkan and cuda only. macOS is compiled for metal. ROCm is not recommended and requires manual compilation.

pip install vsavd

or, with uv:

uv add vsavd

Installing vsavd bundles the compiled plugin inside the wheel, so there is nothing else to build or load.

Choosing an algorithm

Please have a read of the linked page for info about what each algorithm does and its tradeoffs.

TL;DR: Use NL4D if you're unsure

Don't do this!

We recommend reading this before deciding how to integrate this into your existing filtering pipeline as some things differ quiet heavily to what you are likely used to.

Nl4d

Nl4d is the spatio-temporal denoiser, wrapping avd.NL4D. It gives the best noise removal and detail retention of the three, at the cost of time.

import vapoursynth as vs
import vsavd as avd

core = vs.core
clip = core.lsmas.LWLibavSource("noisy.mkv")
clean = avd.Nl4d(clip)
clean.set_output()
Parameter Type CLI equivalent Recommended
lambda_ht_scale float --lambda-ht-scale yes, the main dial
sigma_scale float --sigma-scale yes
preset string --preset yes
refine int --refine yes
spatial_radius int --spatial-radius yes, the speed dial
lambda_ht float --lambda-ht situational, see below
noise_map bool --no-noise-map situational, see below
channel_mode string channel-mode flags situational
device string --device situational
accelerators list of strings -A, --accelerators situational

lambda_ht_scale is the threshold multiplier a transform coefficient's estimated-noise standard deviations must clear to survive. Raising it removes more noise and takes more fine detail with it. Try it in steps of about 0.05 before reaching for lambda_ht, which pins luma and chroma's thresholds (4.158 and 3.234 by default, chosen by eye from rendered comparisons).

spatial_radius is the speed dial. preset already resolves it, so setting spatial_radius explicitly overrides whatever the preset would have picked. The centre-frame search covers (2 * radius + 1)^2 positions, so it dominates the work. Dropping it is the fastest way to speed a run up.

refine is the half-width of the window searched around each neighbour frame's motion-predicted position. Raise it when motion tracking lands close but not exact.

noise_map scales the luma threshold by how noisy each brightness level is, filtering noisy levels harder and clean ones more lightly. It is on by default, and noise_map=False turns it off.

sigma_scale keeps the per-scene noise measurement and nudges it, which is almost always what you actually want.

NlmHQ (NLMeans-HQ)

NlmHQ is the high-quality NLMeans variant, wrapping avd.NLMeans with variant="hq". It runs a per-scene noise estimator and reads its result into sigma_scale rather than leaving noise level to a hand-set strength. Use it over Nlm when you want the estimator to pick the noise level for you.

import vapoursynth as vs
import vsavd as avd

core = vs.core
clip = core.lsmas.LWLibavSource("noisy.mkv")
clean = avd.NlmHQ(clip)
clean.set_output()
Parameter Type CLI equivalent Recommended
preset string --preset yes
motion_compensation bool --motion-compensation yes
sigma_scale float --hq-sigma-scale yes, the main dial
chroma_strength float --chroma-strength yes
channel_mode string channel-mode flags situational
strength float --strength situational, see below
luma_strength float --luma-strength situational
device string --device situational
accelerators list of strings -A, --accelerators situational

Raising strength to fight leftover grain is the wrong move. Grain that survives means the noise level read low, and extra strength scrubs detail before it removes grain. Correcting sigma_scale instead is the right move.

Nlm (NLMeans)

Nlm is the fast NLMeans variant, wrapping avd.NLMeans with variant="fast". It has no noise estimator, so it runs quickly and expects you to set strength yourself. Reach for it when speed matters more than squeezing out the last bit of noise.

import vapoursynth as vs
import vsavd as avd

core = vs.core
clip = core.lsmas.LWLibavSource("noisy.mkv")
clean = avd.Nlm(clip, strength=1.2)
clean.set_output()
Parameter Type CLI equivalent Recommended
preset string --preset yes
motion_compensation bool --motion-compensation yes
chroma_strength float --chroma-strength yes
channel_mode string channel-mode flags situational
strength float --strength yes
luma_strength float --luma-strength situational
device string --device situational
accelerators list of strings -A, --accelerators situational

Nlm has no noise estimator, so strength is the dial that sets the noise level. Use NlmHQ if you would rather have it measured for you.

Presets

preset is the main quality-versus-speed dial. It takes one of five values, from fastest to slowest and best-quality: veryfast, fast, base, slow, veryslow. Each preset resolves every unset numeric and string parameter to a value tuned for that speed tier.

Any parameter you set explicitly overrides what the preset would have chosen for it, other fields still fall back to the preset's values. This lets you take a preset as a starting point and adjust just the dial you care about, as the examples above do.

Channel modes

channel_mode selects which planes get denoised, and takes one of four values:

  • luma denoises the luma plane only, leaving chroma untouched.
  • chroma denoises the chroma planes only, leaving luma untouched.
  • lumachroma denoises both, luma and chroma independently.
  • yuv denoises luma and chroma together as a single pass. It needs a 4:4:4 source, since it requires the chroma planes to be full resolution.

Devices and accelerators

device is typed on all three functions and selects which GPU device runs the filter. device="cpu" selects a software device where the platform offers one, such as lavapipe under Vulkan. It is for testing the pipeline, not for real encodes.

accelerators selects which GPU backend to use, for example ["vulkan"] or ["cuda"]. Multiple accelerators can be provided and the system will try each accelerator in the order provided, choosing the first accelerator which can work on the host hardware.

clean = avd.Nl4d(clip, preset="slow", accelerators=["cuda", "vulkan"])

Shared conventions

  • Every numeric script argument is optional, an unset one falls back to the algorithm's own default, or to whatever preset resolves for that field.
  • device and accelerators are unset by default rather than pinned to a literal string.

Tuning guide

For more information about how to adjust the algorithms to best fit your needs.

Metadata

Release files for vsavd 0.5.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Built distributions (wheels)

Table of built distributions (wheels) for vsavd 0.5.0
File Interpreter ABI Platform
vsavd-0.5.0-py3-none-win_amd64.whl Python 3 none Windows x86-64 Details
vsavd-0.5.0-py3-none-manylinux_2_28_x86_64.whl Python 3 none Linux glibc 2.28+ x86-64 Details
vsavd-0.5.0-py3-none-macosx_11_0_arm64.whl Python 3 none macOS 11.0+ ARM64 Details

Total release size: 18.9 MB

Release files / vsavd-0.5.0-py3-none-win_amd64.whl

Download URL vsavd-0.5.0-py3-none-win_amd64.whl
Size 6.8 MB
Tags Python 3 Windows x86-64
SHA-256 checksum
How to use checksums
4264bd5915094d5e7e067645c1edd2713219f3170e73638be23fe7de28f6a0f8
BLAKE2b-256 checksum
How to use checksums
081c8bcc1e38034dcd6d965729db333c037f9db9302511e002de9e6706f7ba4e
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 9, 2026.

Transparency log

Release files / vsavd-0.5.0-py3-none-manylinux_2_28_x86_64.whl

Download URL vsavd-0.5.0-py3-none-manylinux_2_28_x86_64.whl
Size 7.2 MB
Tags Linux glibc 2.28+ x86-64 Python 3
SHA-256 checksum
How to use checksums
a4a848c457ba34e31de2a422d357db04773e199a86af44d5d725f493aa08eb84
BLAKE2b-256 checksum
How to use checksums
f81f682245db3af9c6b2489a36c53460d6cbf249951ca07b979f8bf45ebb5dd3
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 9, 2026.

Transparency log

Release files / vsavd-0.5.0-py3-none-macosx_11_0_arm64.whl

Download URL vsavd-0.5.0-py3-none-macosx_11_0_arm64.whl
Size 5.0 MB
Tags Python 3 macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
2083359097945be4ba096155be93944aa3088448981d100b8077b77c1ae3ca49
BLAKE2b-256 checksum
How to use checksums
6ba1f8d41d1efb39aac2059eb79edc935cb384371fd2a30cf6054a9cb1654f5b
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 9, 2026.

Transparency log
Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page