fix(denoise): ship the DeepFilterNet 3 worklet as a file so it starts in the desktop app #477

Merged
jared merged 1 commits from fix/dfn-worklet-file into lotus 2026-10-28 20:42:25 -04:00
Owner

Reported by Jared: DeepFilterNet 3 noise suppression "didn't start" in a call in the desktop app.

Console:

Loading the script 'blob:http://127.0.0.1:44548/…' violates the following Content Security Policy directive: "script-src 'self' 'unsafe-eval' 'sha256-…'"
[lotus] denoise setProcessor failed AbortError: Failed to load worklet module script: blob:…

Cause: deepfilternet3-noise-filter inlines its AudioWorklet as a string and loads it from a blob: URL. Audio worklets fall under script-src, not worker-src, and the desktop CSP (tauri.conf.json) has no blob: in script-src.

  • Web: unaffected, since its call page sets no script-src.
  • Other models: RNNoise, Speex and DTLN load their worklets from files, so they were unaffected.

Fix (no CSP change): the lotusDenoise build step now writes the inline worklet to denoise/deepfilternet/dfn-worklet.js, and patches the copied index.esm.js to call addModule(new URL('./dfn-worklet.js', import.meta.url)). That's allowed by script-src 'self'. The build fails if the library changes shape, rather than shipping a model that can't start.

Verified in Chromium with the built assets, under the exact desktop CSP:

Model Before After
RNNoise / Speex worklet loads worklet loads
DTLN ready ready
DeepFilterNet 3 fails as reported node created, and cuts 4 s of white noise by 60 dB (its configured level)

Side finding while measuring (not a production problem): Vite's local preview server sends .tar.gz files with Content-Encoding: gzip. The browser then un-gzips the model, df_create panics inside the worklet (RuntimeError: unreachable), and DeepFilterNet silently passes audio through (0 dB).

  • The worklet catches that error and shows nothing, so it's worth remembering when testing locally.
  • Production is fine: nginx serves the model as plain application/octet-stream (checked), and the desktop's localhost plugin sets no Content-Encoding (checked in tauri-plugin-localhost 2.3.2).

🤖 Generated with Claude Code

https://claude.ai/code/session_017PCb59uY3UKqDqt7B6hzd5

**Reported by Jared:** DeepFilterNet 3 noise suppression "didn't start" in a call in the desktop app. **Console:** ``` Loading the script 'blob:http://127.0.0.1:44548/…' violates the following Content Security Policy directive: "script-src 'self' 'unsafe-eval' 'sha256-…'" [lotus] denoise setProcessor failed AbortError: Failed to load worklet module script: blob:… ``` **Cause:** `deepfilternet3-noise-filter` inlines its AudioWorklet as a string and loads it from a `blob:` URL. Audio worklets fall under `script-src`, not `worker-src`, and the desktop CSP (`tauri.conf.json`) has no `blob:` in `script-src`. - **Web:** unaffected, since its call page sets no `script-src`. - **Other models:** RNNoise, Speex and DTLN load their worklets from files, so they were unaffected. **Fix (no CSP change):** the `lotusDenoise` build step now writes the inline worklet to `denoise/deepfilternet/dfn-worklet.js`, and patches the copied `index.esm.js` to call `addModule(new URL('./dfn-worklet.js', import.meta.url))`. That's allowed by `script-src 'self'`. **The build fails** if the library changes shape, rather than shipping a model that can't start. **Verified** in Chromium with the built assets, under the **exact desktop CSP**: | Model | Before | After | |---|---|---| | RNNoise / Speex | worklet loads | worklet loads | | DTLN | ready | ready | | **DeepFilterNet 3** | **fails as reported** | node created, and **cuts 4 s of white noise by 60 dB** (its configured level) | **Side finding while measuring (not a production problem):** Vite's local preview server sends `.tar.gz` files with `Content-Encoding: gzip`. The browser then un-gzips the model, `df_create` panics inside the worklet (`RuntimeError: unreachable`), and DeepFilterNet silently passes audio through (0 dB). - The worklet catches that error and shows nothing, so it's worth remembering when testing locally. - **Production is fine:** nginx serves the model as plain `application/octet-stream` (checked), and the desktop's localhost plugin sets no `Content-Encoding` (checked in `tauri-plugin-localhost` 2.3.2). 🤖 Generated with [Claude Code](https://claude.com/claude-code) https://claude.ai/code/session_017PCb59uY3UKqDqt7B6hzd5
jared added 1 commit 2026-10-28 20:19:28 -04:00
fix(denoise): ship the DeepFilterNet 3 worklet as a file so it starts in the desktop app
CI / Build & Quality Checks (push) Skipped
CI / Secret scan (gitleaks) (push) Skipped
CI / Playwright smoke (e2e) (push) Skipped
CI / Secret scan (gitleaks) (pull_request) Successful in 32s
CI / Build & Quality Checks (pull_request) Successful in 3m17s
CI / Trigger Desktop Build (pull_request) Skipped
CI / Docker image build & smoke test (pull_request) Skipped
CI / Playwright smoke (e2e) (pull_request) Successful in 18m41s
e8a04fee20
Reported: DeepFilterNet 3 "did not start" in a desktop call. Console:
"Loading the script blob:http://127.0.0.1:44548/… violates … script-src",
then "[lotus] denoise setProcessor failed … Failed to load worklet module".
deepfilternet3-noise-filter inlines its AudioWorklet as a string and loads it
from a blob: URL; audio worklets fall under script-src, and the desktop CSP
has no blob: there (the web call page has no script-src, so web was fine).

Instead of loosening the CSP, the build now writes the inline worklet to
denoise/deepfilternet/dfn-worklet.js and patches the copied module to load
it by URL (script-src self). The build fails if the library changes shape.

Verified in Chromium under the exact desktop CSP with the built assets:
before, DeepFilterNet fails as reported; after, it creates its node and, fed
4 s of white noise, cuts it by 60 dB (its configured level). RNNoise, Speex
and DTLN load as before.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017PCb59uY3UKqDqt7B6hzd5
jared scheduled this pull request to auto merge when all checks succeed 2026-10-28 20:20:25 -04:00
jared merged commit 2264c79833 into lotus 2026-10-28 20:42:25 -04:00
Sign in to join this conversation.
No Reviewers
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: LotusGuild/cinny#477