Skip to main content

vapoursynth-feel

GPU-accelerated filters in Vulkan for VapourSynth.

Primarily optimized for running on RDNA 3 with the RADV driver on Linux.

VapourSynth R80+ and a Vulkan 1.4 capable GPU are required.

pip install vapoursynth-feel

Performance

Filter vsfeel u16 vszipcl u16 vulkan u16 vsfeel fp32 vszipcl fp32 vulkan fp32 Speedup
Bilateral 2170 580 - 1142 387 - 3.43x
BM3Dv2 985 - - 966 119 280 3.48x
DFTTest 1431 833 - 1134 488 - 1.94x
EEDI3 (AA) 198 25 37 127 25 29 4.92x
GaussBlur 2325 1298 - 1145 797 - 1.66x
NLMeans 1043 452 603 735 462 593 1.49x
NNEDI3 2703 - 2004 1393 - 1008 1.36x

Measured on a RX 7900 XTX using tools/benchmark.py --filter <filter> --bits <16|32> with a 1080p clip.

vulkan column: bm3dvk, eedi3vk2, knlmvk, nnedi3vk

Filters

Bilateral

A Bilateral filter is a non-linear, edge-preserving and noise-reducing smoothing filter for images. The intensity value at each pixel in an image is replaced by a weighted average of intensity values from nearby pixels. This weight can be based on a Gaussian distribution.

core.vsfeel.Bilateral(clip clip[,
    float[] sigma_spatial=3.0,      # spatial blur reach; per-plane, chroma default = sigma[0]/sqrt((1<<ssw)*(1<<ssh))
    float[] sigma_color=0.02,       # edge sensitivity: how different pixels may be to blend; depth-normalized
    int[]   radius,                 # per-plane blur window radius; default max(1, round(sigma_spatial*3))
    int     use_shared_memory=1,    # faster on-chip kernel while the window fits; falls back otherwise
    int     block_x, int block_y,   # GPU thread-block dims; auto-tuned when unset (32 x 8, x16 when radius > 12)
    clip    ref])                   # guide clip: weights from ref, values from clip

BM3Dv2

BM3D is a block-matching and 3D collaborative filtering denoiser. Groups of similar blocks (across space and time) are stacked into 3D arrays, denoised together with a hard-thresholded 3D transform, and the overlapping estimates are aggregated into the output.

core.vsfeel.BM3Dv2(clip clip[,
    clip    ref,                    # basic-estimate clip for the Wiener (final) pass
    float[] sigma=3.0,              # denoising strength per-plane; below FLT_EPSILON skips the plane
    int[]   block_step=8,           # per-plane block grid spacing, 1..8; smaller = fewer artifacts, slower
    int[]   bm_range=9,             # per-plane spatial search radius in pixels, 1..8192
    int     radius=0,               # temporal search radius in frames, 0..16 (0 = spatial only)
    int[]   ps_num=2,               # motion-predicted candidates seeding each temporal search, 1..8
    int[]   ps_range=4,             # search radius around each predicted candidate, in pixels, 1..8192
    bool    chroma=False,           # True = one joint 4:4:4 entry, whose groups come from luma
    int     extractor_exp=0])       # aggregation weight bias, 0..127; 0 = off, >= 3 = reproducible output

chroma=True requires YUV444.

DFTTest

DFTTest is a 3D block-wise frequency-domain denoiser. Each 16x16 spatial block is stacked with temporally neighboring frames, transformed to the frequency domain, filtered, and transformed back with overlap-add. It reduces noise while preserving detail, with configurable spatial and temporal windowing and a choice of frequency-domain filter variants.

core.vsfeel.DFTTest(clip clip[,
    int     ftype=0,                # 0 = Wiener: mult by max((psd-sigma)/psd, 0) ** f0beta
                                    # 1 = hard threshold: zero the bin when psd < sigma
                                    # 2 = mult every bin by sigma
                                    # 3 = mult by sigma inside [pmin,pmax], else by sigma2
                                    # 4 = mult by sigma*sqrt(psd*pmax / ((psd+pmin)*(psd+pmax)))
    float   sigma=8.0,              # base denoising strength
    float   sigma2=8.0,             # ftype=3 only: strength outside [pmin,pmax]
    float   pmin=0.0,               # ftype=3/4 only: lower PSD bound
    float   pmax=500.0,             # ftype=3/4 only: upper PSD bound
    int     sbsize=16,              # spatial block size; must be 16 in this backend
    int     sosize=12,              # spatial overlap, 0..15; >50% needs (sbsize-sosize) | sbsize
    int     tbsize=3,               # temporal block size; ODD, 1..7 (1 = spatial only)
    int     swin=0,                 # spatial window, 0..11: 0=hanning 1=hamming 2=blackman
                                    #   3=4-term b-harris 4=kaiser-bessel 5=7-term b-harris
                                    #   6=flat top 7=rectangular 8=bartlett 9=bartlett-hann
                                    #   10=nuttall 11=blackman-nuttall
    int     twin=7,                 # temporal window, the same 0..11 set; default 7=rectangular
    float   sbeta=2.5,              # kaiser-bessel beta (swin=4 only)
    float   tbeta=2.5,              # kaiser-bessel beta (twin=4 only)
    int     zmean=1,                # subtract the windowed mean before filtering
    float   f0beta=1.0,             # ftype=0 exponent (1.0 = plain Wiener, 0.5 = sqrt)
    int     ssystem=0,              # slocation scale: 0 = relative to block size, 1 = absolute
    float[] slocation,              # frequency-dependent sigma: [freq, sigma, freq, sigma, ...]
    float[] ssx,                    # slocation along the X axis only
    float[] ssy,                    # slocation along the Y axis only
    float[] sst,                    # slocation along time only
    int[]   planes])                # planes to process; default: all

EEDI3

EEDI3 is an edge-directed interpolator for deinterlacing and upscaling. For each missing pixel it searches candidate connection angles between the neighboring lines, picks the one minimizing a cost functional over local neighborhoods, and interpolates along that direction so edges stay sharp instead of stair-stepping.

core.vsfeel.EEDI3(clip clip, int field[,   # and EEDI3H, same args, horizontal
    int     dh=False,               # double-height output keeping every source line (no field extracted)
    int[]   planes,                 # planes to process; default: all
    float   alpha=0.2,              # 0..1 (alpha+beta <= 1): weight given to connecting similar
                                    #   neighborhoods. Larger = more lines/edges connected
    float   beta=0.25,              # 0..1: weight given to the vertical difference created by
                                    #   the interpolation. Larger = fewer edges connected
                                    #   (1.0 = no edge directedness at all)
    float   gamma=20.0,             # >= 0: penalizes changes in interpolation direction.
                                    #   Larger = smoother interpolation field
    int     nrad=2,                 # radius used for neighborhood similarity, 0..3
    int     mdis=20,                # max connection radius, 1..40; larger connects shallower
                                    #   lines, but costs speed and risks artifacts
    int     vcheck=2,               # 0..3: strength of the vertical-consistency check
    float   vthresh0=32.0,          # vcheck thresholds; all must be > 0 when vcheck > 0
    float   vthresh1=64.0,
    float   vthresh2=4.0,
    clip    sclip,                  # source for the vcheck comparison
    clip    mclip])                 # edge mask; fully-masked spans are skipped

field 2/3 are the double-rate variants (not allowed with dh=True).

GaussBlur

Gaussian blur is a smoothing filter that blends each pixel with its neighbors, weighting nearby pixels more heavily than distant ones according to a bell-shaped (Gaussian) curve. It is commonly used to soften an image or reduce noise.

core.vsfeel.GaussBlur(clip clip[,
    float[] sigma=0.5])             # blur strength; per-plane, chroma default = sigma[0]/sqrt((1<<ssw)*(1<<ssh))

NLMeans

Non-local means is a denoising filter that replaces every pixel with a weighted average of pixels across a search window, weighting them by the similarity of their surrounding patches. Searching across space and time suppresses noise while preserving detail.

core.vsfeel.NLMeans(clip clip[,
    int     d=1,                    # temporal radius; 0 = spatial only
    int     a=2,                    # search-window radius, 1..64
    int     s=4,                    # patch radius, 0..8
    float   h=1.2,                  # > 0: filtering strength
    int     wmode=0,                # weighting function of the patch distance x, 0..3:
                                    #   0 = exp(-x) | 1 = max(1-x, 0)
                                    #   2 = max(1-x, 0)**2 | 3 = max(1-x, 0)**8
    float   wref=1.0,               # >= 0: weight of the pixel itself
    string  channels="auto",        # planes to process, jointly for YUV/RGB; auto picks by format
    clip    rclip])                 # weights computed from rclip, values from clip

channels="YUV" requires 4:4:4 so on subsampled clips run a "Y" pass and a "UV" pass instead.

Accuracy caveat. The weight accumulator is fp16. At small h with wref=0 the exp() weights fall into fp16 subnormals and the whole ring can flush to zero; the kernel then falls back to the centre sample rather than evaluating 0/0, so the output can differ from the reference by thousands of codes (measured ~4600 LSB at h=1.2, wref=0 on the 16-bit test clip; back to 1 LSB at h=3.0). Raise h or wref if that matters.

NNEDI3

NNEDI3 is a neural-network edge-directed interpolator for deinterlacing and upscaling. A small neural network predicts each missing pixel from its local neighborhood, while a prescreener network skips pixels that simple cubic interpolation already handles.

core.vsfeel.NNEDI3(clip clip, int field[,
    int     dh=False,               # double-height output keeping every source line (no field extracted)
    int[]   planes,                 # planes to process; default: all
    int     nsize=6,                # predictor neighborhood, 0..6: 0=8x6 1=16x6 2=32x6
                                    #   3=48x6 4=8x4 5=16x4 6=32x4
    int     nns=1,                  # predictor neurons, 0..4: 0=16 1=32 2=64 3=128 4=256
    int     qual=1,                 # 1 or 2: number of predictor passes averaged
    int     etype=0,                # 0 = weights trained on absolute error, 1 = squared error
    int     pscrn=2])               # prescreener, 0..4: 0=off (predict every pixel)
                                    #   1=original, 2..4=new levels 0..2 (higher = fewer pixels
                                    #   left to cubic interpolation: slower, slightly better)

field 2/3 are the double-rate variants (not allowed with dh=True).

vs-jetpack integration

The wheel ships a small Python module alongside the plugin that adds vsfeel as a backend for the vs-jetpack wrappers.

vsjetpack is an optional dependency, only needed at runtime when you use these backends.

from vsrgtools import bilateral, gauss_blur
from vsdenoise import bm3d, DFTTest, nl_means

import vsfeel

# Bilateral
blurred = bilateral(clip, ref, 3.0, 0.02, backend=vsfeel.Backend)

# BM3D
denoised = bm3d(clip, 0.7, tr=2, profile=bm3d.Profile.NORMAL, ref=ref, planes=0, backend=vsfeel.Backend)

# DFTTest
dft = DFTTest(clip, backend=vsfeel.Backend).denoise({0.0: 16.0, 0.5: 8.0, 1.0: 0.0}, tr=1)

# GaussBlur
smooth = gauss_blur(clip, 1.5, backend=vsfeel.Backend)

# NLMeans
denoised = nl_means(clip, h=0.2, tr=2, a=2, s=4, ref=ref, planes=[1, 2], backend=vsfeel.Backend)

To also route the internal filters vs-jetpack calls on its own (e.g. the bilateral postfilter inside vsaa.based_aa), use the backend as a context manager:

from vsaa import based_aa

with vsfeel.Backend():
    based = based_aa(clip, antialiaser=vsfeel.EEDI3())

Manual Compilation

Full Python Package

pip install .

Plugin-Only

cmake -S . -B build -D CMAKE_BUILD_TYPE=Release
cmake --build build --config Release
cmake --install build

Metadata

Release files for vapoursynth-feel 1.1.0

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

Source distribution (sdist)

Source distribution for vapoursynth-feel 1.1.0
File Size Uploaded
vapoursynth_feel-1.1.0.tar.gz 23.1 MB Details

Built distributions (wheels)

Table of built distributions (wheels) for vapoursynth-feel 1.1.0
File
vapoursynth_feel-1.1.0-py3-none-win_amd64.whl Python 3 none Windows x86-64 Details
vapoursynth_feel-1.1.0-py3-none-manylinux_2_34_x86_64.whl Python 3 none Linux glibc 2.34+ x86-64 Details
vapoursynth_feel-1.1.0-py3-none-manylinux_2_34_aarch64.whl Python 3 none Linux glibc 2.34+ ARM64 Details
vapoursynth_feel-1.1.0-py3-none-macosx_13_0_x86_64.whl Python 3 none macOS 13.0+ x86-64 Details
vapoursynth_feel-1.1.0-py3-none-macosx_13_0_arm64.whl Python 3 none macOS 13.0+ ARM64 Details

Total release size: 98.2 MB

Release files / vapoursynth_feel-1.1.0.tar.gz

Download URL vapoursynth_feel-1.1.0.tar.gz
Size 23.1 MB
Tags Source
SHA-256 checksum
How to use checksums
2264130dde6026398a8d8922b304bde36228c02cb6d38038b827d31e76869562
BLAKE2b-256 checksum
How to use checksums
b48e5175a3af84c72da22f5696c5fd7c27c60a8c0c79ffc308999546cbfd38cf
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 5, 2026.

Transparency log

Release files / vapoursynth_feel-1.1.0-py3-none-win_amd64.whl

Download URL vapoursynth_feel-1.1.0-py3-none-win_amd64.whl
Size 15.4 MB
Tags Python 3 Windows x86-64
SHA-256 checksum
How to use checksums
188b5909a07044ebcef023bee669243a5914eb2a4d7d02a9b624e8e7edc33506
BLAKE2b-256 checksum
How to use checksums
7c6fc591054841e702bf8e0dda2914da5b38f0440472e20c0c7cc506e1326f99
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 5, 2026.

Transparency log

Release files / vapoursynth_feel-1.1.0-py3-none-manylinux_2_34_x86_64.whl

Download URL vapoursynth_feel-1.1.0-py3-none-manylinux_2_34_x86_64.whl
Size 14.9 MB
Tags Linux glibc 2.34+ x86-64 Python 3
SHA-256 checksum
How to use checksums
bdb31d155a92eb5a1f351fd7e97b06a29e5315d6e3fb532431c6f020f8835af8
BLAKE2b-256 checksum
How to use checksums
cb69e592702b17c13e958f9c6ab8efb0b517986696d7f6f957eec0d6d98351d3
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 5, 2026.

Transparency log

Release files / vapoursynth_feel-1.1.0-py3-none-manylinux_2_34_aarch64.whl

Download URL vapoursynth_feel-1.1.0-py3-none-manylinux_2_34_aarch64.whl
Size 14.9 MB
Tags Linux glibc 2.34+ ARM64 Python 3
SHA-256 checksum
How to use checksums
96707ad314f9372f26c06ce5a2efc963ccd21f8882629278b60008d4bcbe022e
BLAKE2b-256 checksum
How to use checksums
50cf57ab4ecc14e57374546e30375b0364fa1ffc19a0846e9d6d593c054ef8e0
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 5, 2026.

Transparency log

Release files / vapoursynth_feel-1.1.0-py3-none-macosx_13_0_x86_64.whl

Download URL vapoursynth_feel-1.1.0-py3-none-macosx_13_0_x86_64.whl
Size 14.9 MB
Tags Python 3 macOS 13.0+ x86-64
SHA-256 checksum
How to use checksums
c66406f1f467240f217584c59255f2d497a0e17797e31c6e40c8c8aea4e92164
BLAKE2b-256 checksum
How to use checksums
aba0d752ed02b46f057415d99f1973ccd56fe809851420efa9ce9f944128885f
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 5, 2026.

Transparency log

Release files / vapoursynth_feel-1.1.0-py3-none-macosx_13_0_arm64.whl

Download URL vapoursynth_feel-1.1.0-py3-none-macosx_13_0_arm64.whl
Size 15.0 MB
Tags Python 3 macOS 13.0+ ARM64
SHA-256 checksum
How to use checksums
e9b068898ed2103fd30394dc15893f61cfb2fddcc3e41c9241cc93fc7789ace6
BLAKE2b-256 checksum
How to use checksums
1723934d56b012b58d10f48aee1a21675f659c33c2d22ef1993e76097117ec46
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 5, 2026.

Transparency log

Release history Release notifications | RSS feed

1.1.1

6 release files

This release

1.1.0 This release

6 release files

1.0.0

6 release files

0.2.2

3 release files

0.2.1

3 release files

0.2.0

3 release files

0.1.0

3 release files

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