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.1

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.1
File Size Uploaded
vapoursynth_feel-1.1.1.tar.gz 23.1 MB Details

Built distributions (wheels)

Table of built distributions (wheels) for vapoursynth-feel 1.1.1
File
vapoursynth_feel-1.1.1-py3-none-win_amd64.whl Python 3 none Windows x86-64 Details
vapoursynth_feel-1.1.1-py3-none-manylinux_2_34_x86_64.whl Python 3 none Linux glibc 2.34+ x86-64 Details
vapoursynth_feel-1.1.1-py3-none-manylinux_2_34_aarch64.whl Python 3 none Linux glibc 2.34+ ARM64 Details
vapoursynth_feel-1.1.1-py3-none-macosx_13_0_x86_64.whl Python 3 none macOS 13.0+ x86-64 Details
vapoursynth_feel-1.1.1-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.1.tar.gz

Download URL vapoursynth_feel-1.1.1.tar.gz
Size 23.1 MB
Tags Source
SHA-256 checksum
How to use checksums
e269b01ed883f868a24655e0d2ca74d75305c4f6d056fa1d4fcab33a0057db30
BLAKE2b-256 checksum
How to use checksums
4f13c964d1eb8260343db4ff4e695517985d6274d7dd8fe34642f595a5da3f73
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.1-py3-none-win_amd64.whl

Download URL vapoursynth_feel-1.1.1-py3-none-win_amd64.whl
Size 15.4 MB
Tags Python 3 Windows x86-64
SHA-256 checksum
How to use checksums
0708c3c241d8d3dbf2dd67378530c2c58b11f38f964087f3143d3fac7a499d6a
BLAKE2b-256 checksum
How to use checksums
f41cd11836c6e1f60d7a3e2860b4f153d6da8174a2b4859f319662de23e5b333
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.1-py3-none-manylinux_2_34_x86_64.whl

Download URL vapoursynth_feel-1.1.1-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
ce1087d9d288f64a2b5696d8c7ed5bd7680b4249686ae2f880b4e8c7d5688091
BLAKE2b-256 checksum
How to use checksums
e7e4f88717432da0cef7b2d09688a42c8831a68701dd8c72ea60ea2727439fcb
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.1-py3-none-manylinux_2_34_aarch64.whl

Download URL vapoursynth_feel-1.1.1-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
46ed886d675cc3ac8c42a3db4c761621c7cd2c0eab8d219e5b8e8cf296dcf470
BLAKE2b-256 checksum
How to use checksums
2d5590a86ac1fe4b3ac7ba958f33fc55f2885166d6f50aff6b538dada85808ee
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.1-py3-none-macosx_13_0_x86_64.whl

Download URL vapoursynth_feel-1.1.1-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
612864d053ca4bde740568eb5fb5d32d4b5b408789f2a9ec2c5e18f659aabbd0
BLAKE2b-256 checksum
How to use checksums
9cd9e0ff9adff71cda61415a806a4e2007839c24f3b86d070054efb5b0cf9a11
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.1-py3-none-macosx_13_0_arm64.whl

Download URL vapoursynth_feel-1.1.1-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
f8245226794ccc137eaee99c9802910d8c4c8ef08f3f3adbb9e6d374b108a1b3
BLAKE2b-256 checksum
How to use checksums
c9030aead32d3f5b391efc96decc31fadbf8d28cf8a44932bfbde911e3ba10ac
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

This release

1.1.1 This release

6 release files

1.1.0

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