Skip to content

Anime filters: BM3D/KNLMeans, AI upscaling (incl. AnimeJaNai add-on), Descale; Settings → Add-ons - #131

Merged
StuartCameronCode merged 15 commits into
mainfrom
feat-anime-filters
Oct 25, 2026
Merged

StuartCameronCode merged 15 commits into
mainfrom
feat-anime-filters

Conversation

@StuartCameronCode

@StuartCameronCode StuartCameronCode commented Oct 25, 2026 •

Copy link
Copy Markdown
Owner

Anime-focused filters, plus CI tests for every GPU feature on each platform that ships it.

What's new (app 1.5.0, deps 1.14.0-rc1)

  • Noise Reduction: BM3D and KNLMeans (advanced mode).
    • BM3D runs at 16-bit, one plane at a time. It now ships on every platform; before, only macOS arm64 had it.
    • KNLMeans has its own GPU device check, because its default device setting fails on Apple Silicon.
  • Crop & Resize: AI upscaling with Real-ESRGAN and Real-CUGAN, through vs-mlrt's VSNCNN (ncnn on Vulkan). HD frames are processed in 512 px tiles.
  • AnimeJaNai upscaling as an add-on.
    • The models are CC BY-NC-SA 4.0 (non-commercial), so they never go in the deps bundle. They're downloaded from upstream's release, with the zip and each model pinned by SHA-256.
    • The licence is shown at download time and while the method is selected.
    • Up to 576 lines the SD model is used; above that, the chosen HD model.
    • Flat colours shift by at most 0.5 levels, against Real-ESRGAN's 11.
  • Descale pass (runs after SpotLess).
    • It reverses the studio's upscale on luma, upscales again with NNEDI3, and leaves credits and text untouched.
    • A Detect button finds the native resolution and kernel (--detect-native).
  • Settings → Add-ons. One system for every third-party download (Whisper and AnimeJaNai): install and remove, with size, licence and source. Features use the same prompt when they need an add-on.

UI

  • NEW badges lead to what's new.
    • Individual dropdown options and methods can now carry their own stamp (optionSinceAppVersion, and sinceAppVersion on a method).
    • Every control on the way to something new is badged too: the dropdown that holds it, a switch that reveals it, its section and the pass row.
    • The new Add-ons tab and the Settings button are badged.
    • Stamps that sat on existing parameters (or on a hidden one, which badged nothing) were moved onto the new options and methods.
  • Parameter presets sit inside their own section. Before, in simple mode Crop & Resize showed Crop, Resize and Canvas presets in one block that read as all about cropping. Upscale now comes before Aspect Ratio.
  • Dropdown labels: ui.optionLabels, so "Real-ESRGAN" no longer shows as "Realesrgan". The upscale descriptions now cover every method rather than just NNEDI3.
  • Credits brought into sync.
    • Added: the Whisper models (MIT, OpenAI) and AnimeJaNai.
    • Fixed: the RemoveGrain About tile now names its MIT component, and the VSNCNN tile names LLVM OpenMP.
    • New tests: About and NOTICES must state the same licences; each add-on's credits must agree across NOTICES, About, README and Settings.

Testing

  • GPU tests in CI.
    • Linux and Windows runners get Mesa's lavapipe, a CPU Vulkan driver. With VAPOURBOX_EXPECT_VULKAN=1 set, a GPU test that reports "unavailable" fails instead of skipping.
    • macOS arm64 can't get a device: MoltenVK can't open the VM's Metal GPU, and lavapipe crashes because the bundled akarin exports its built-in LLVM's symbols, which lavapipe's own LLVM then binds to. Its GPU tests skip, but the probe must still give a real reason. MoltenVK is tested on real Macs. Details are in ENGINEERING_NOTES.
  • Every push: for each GPU feature, the probe, the refusal when it can't run, the generated script, and a real frame rendered on the GPU.
  • Nightly:
    • RIFE frame counts;
    • AI upscaling pixel checks (colour, position, preview = encode, 8-bit vs 10-bit);
    • Descale detection and credit protection;
    • high-bit-depth parity.
  • The macOS jobs print crash backtraces whenever tests fail.
  • Deps scripts. if ( set -e … ) blocks in the deps scripts ignored failures, because bash disables set -e inside an if condition. That hid a VSNCNN compile failure on macOS arm64. Fixed in both scripts.
  • Windows-only test bugs fixed. Several test helpers deleted temp files while still reading them. 4× CUGAN on lavapipe needed a longer stall limit.

Before merge

deps-version.json points at the deps-v1.14.0-rc1 prerelease, rebuilt from this branch; no deps script has changed since. A real deps-v1.14.0 tag must be published, and deps-version.json pointed at it, before an app release. Scripts/release.sh refuses an rc tag. Main already points at rc1, from #130.

🤖 Generated with Claude Code

StuartCameronCode and others added 13 commits October 25, 2026 11:54
- Noise Reduction: BM3D (16-bit, per-plane GRAY) and KNLMeans (own
  device probe: "gpu" then "auto"), advanced-only. BM3D r12 now ships on
  every platform (was macOS arm64 only).
- Crop & Resize: Real-ESRGAN animevideo 2x/4x and Real-CUGAN 2x via
  vs-mlrt's VSNCNN (ncnn/Vulkan), tiled above SD. rife.rs generalised to
  gpu_plugin.rs; --probe-upscale.
- Descale pass (after SpotLess): descale r12 on luma, NNEDI3 re-upscale,
  credit protection mask; --detect-native finds the native resolution
  and kernel.
- CI: lavapipe on Linux/Windows (provision-vulkan.sh); with
  VAPOURBOX_EXPECT_VULKAN=1 the GPU tests fail instead of skipping.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ngs → Add-ons

- Crop & Resize: AnimeJaNai (the-database's Real-ESRGAN Compact models, CC
  BY-NC-SA 4.0) on VSNCNN. Its SD model is used up to 576 lines and the
  chosen HD model (Compact / UltraCompact / SuperUltraCompact, optionally
  Sharp) above, decided in the script per doubling. Flat colour stays within
  0.5 levels.
- The models are never in the deps bundle. They're downloaded from
  upstream's 3.0.0 release, with the zip and each model pinned by SHA-256,
  and the non-commercial terms are shown at download time and while the
  method is chosen. The worker refuses the job if the models are missing.
- AddonService replaces the Whisper-only manager and dialogs: one catalogue,
  requirements installed first, dependants removed together. Settings →
  Add-ons lists every add-on with its size, licence and source, to install
  or remove, and AddonPrompt is the shared on-demand prompt.
- Schema: ui.optionLabels, so dropdowns show "Real-ESRGAN" instead of
  "Realesrgan".
- Credits: the Whisper models (MIT, OpenAI) and AnimeJaNai are now in
  NOTICES, About and README. The RemoveGrain About tile now names its MIT
  component, and the VSNCNN tile names LLVM OpenMP.
- Tests: About and NOTICES licences must match; each add-on's credits must
  agree across NOTICES, About, README and Settings; the GPU tests install
  the real AnimeJaNai download.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… blocks

- macOS arm64 pins no deployment target, so VSNCNN's direct clang++ call got
  an empty -mmacosx-version-min= and failed. It now targets 15.0, the arm64
  bundle's floor.
- The failure went unnoticed because bash ignores set -e in a subshell used
  as an `if` condition: `if ( set -e ... ); then` reported success because
  the last command succeeded. The four macOS blocks and two Linux blocks
  that used that form now run the subshell on its own and check its status.
- The vapoursynth shim is now written by a function, and restored near the
  end if missing. A rerun that reinstalled Python but skipped VapourSynth
  had left no shim, so VSScript could not configure itself.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…NEDI3

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…eouts

The first CI run with VAPOURBOX_EXPECT_VULKAN=1 showed MoltenVK can't open
the hosted arm64 runner's Metal device (it segfaults creating the instance;
the runners are VMs). macOS now gets Homebrew's mesa lavapipe through the
Khronos loader, which ncnn tries before the preloaded MoltenVK. Only the
loader is exposed, on the fallback path, so no other Homebrew library can
stand in for a bundled one.

On lavapipe the first probe took 30.4 s on Windows, past the default test
timeout, so the probe tests now allow 3 minutes and the script test 5
(it may also download AnimeJaNai).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- SIP strips DYLD_* at the bundle's /bin/bash vspipe wrapper, so the
  loader is now copied into ~/lib, which is on dyld's default fallback
  path.
- On Windows lavapipe one 720x576 Real-CUGAN frame took over 5 minutes, so
  the push-gate upscale jobs crop to 240x192 first. Full-size checks stay
  in the heavy suite.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… switches

- A new enum option (optionSinceAppVersion) is badged in its dropdown, and
  a new method (sinceAppVersion on the method) in the method list.
- Every control on the way to something new is badged too: a parameter
  whose option is new or that reveals a new control (through every
  visibleWhen level, so "Enable Upscale" badges), the Method label, a
  section heading, and the pass row. The panels pass the schema to the
  labels through ParameterBadgeScope.
- The new Settings → Add-ons tab is badged, and the Settings button gets a
  dot while it is new.
- Restamped: Real-ESRGAN, Real-CUGAN and AnimeJaNai are now stamped as
  options rather than on upscaleMethod; RIFE, BM3D and KNLMeans as methods
  rather than on the method parameter. Noise Reduction's stamp had been on
  a hidden parameter, so it badged nothing.
- Tests: the derived rules; lints for option and method stamps, and against
  stamping a hidden parameter; the real 1.5.0 badges on the shipped
  schemas; and a widget test of the Crop & Resize panel.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… overflow

The tabs share the dialog's width equally, and a NEW pill beside "Add-ons"
overflowed its tab by 14 px. It's now a Badge on the label's corner, which
takes no layout width. A test checks the label at 600 and 480 px.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
~/lib didn't work either: dyld no longer searches it, or /usr/local/lib,
for ncnn's dlopen("libvulkan.1.dylib"), and SIP strips DYLD_* at the
bundle's /bin/bash vspipe wrapper. The scripts already preload a Vulkan
library on macOS (MoltenVK), so VAPOURBOX_VULKAN_LIBRARY now names a
different one; CI sets it to the Khronos loader, which opens lavapipe
through VK_DRIVER_FILES.

Checked locally with Homebrew's loader driving the bundled MoltenVK:
VSNCNN upscales, and both probes report available. A missing path is
reported as a missing file.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A plugin that segfaults in vspipe shows only "signal 11" in the test log,
and the hosted runners can't be logged into. print-crash-reports.py prints
the faulting thread of the newest vspipe/python crash reports, with the
library and function names. It's needed now to find why lavapipe still
crashes on the macOS arm64 runner.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The crash report shows lavapipe dying in Homebrew's libLLVM.23 (PassBuilder)
while compiling its first shader. The bundle's macOS akarin statically
links LLVM and exports ~47,000 of its symbols, 2,293 of them weak, and dyld
coalesces weak definitions across images, so lavapipe's LLVM 23 ran
against akarin's LLVM 22. MoltenVK can't open the VM's Metal device either.
So the macOS arm64 runner gets no device and its GPU tests skip, while the
probe must still give a real reason. MoltenVK is tested on real Macs.

Removes VAPOURBOX_VULKAN_LIBRARY, which only existed for this. The akarin
finding is in ENGINEERING_NOTES: any LLVM-based component loaded into
vspipe on macOS would hit the same problem.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
In simple mode every parameter preset used to be drawn in one block at the
top of the pass, and the controls it sets are hidden there. Crop & Resize
therefore showed "Crop Preset", "Resize Preset" and "Canvas Preset"
together, reading as all about cropping. Each preset is now drawn inside
the section whose controls it sets (FilterSchema.sectionForPreset), so the
section heading says what it's about, and a section whose only control is
its preset still shows. Crop & Resize's Upscale sections now come before
Aspect Ratio.

A lint requires every preset's parameters to sit in one section, and a
widget test pins the panel's reading order.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@sanchandhana-commits

Copy link
Copy Markdown

Congratulations 🤩

StuartCameronCode and others added 2 commits October 25, 2026 16:22
…e upscales

Two Windows-only nightly failures:
- Four test helpers did `return future;` inside a try whose finally deletes
  the temp file being read. The analyzer warned about each
  (unawaited_return_in_try_block). macOS and Linux allow deleting an open
  file and Windows doesn't, so the Descale encode test failed there with
  "being used by another process" even though Descale itself passed (diff
  0.670, tolerance 2.0).
- 4x Real-CUGAN's first frame on Windows lavapipe took longer than the
  worker's 600 s stall watchdog, so the AI-upscale jobs now pass
  VAPOURBOX_STALL_TIMEOUT_SECS=1200, matching their own 20-minute limit
  (runJob gains extraEnv).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Windows x64's nightly passed the 4x Real-CUGAN encode, then failed its
one-frame preview at the harness's default 5 minutes. On a CPU Vulkan
driver one 4x CUGAN frame takes longer than that. The AI-upscale previews
now get the same 20 minutes and stall limit as the encodes (runPreview
gains extraEnv), and those tests allow 60 minutes in total. A preview
killed at its timeout now reports that, instead of an empty reason.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@StuartCameronCode
StuartCameronCode merged commit 90f76c7 into main Oct 25, 2026
17 of 18 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants