Merge pull request 'fix(denoise): ship the DeepFilterNet 3 worklet as a file so it starts in the desktop app' (#477) from fix/dfn-worklet-file into lotus
CI / Build & Quality Checks (push) Canceled after 9m42s
CI / Secret scan (gitleaks) (push) Canceled after 5s
CI / Trigger Desktop Build (push) Canceled after 0s
CI / Docker image build & smoke test (push) Canceled after 0s
CI / Playwright smoke (e2e) (push) Canceled after 0s

This commit was merged in pull request #477.
This commit is contained in:
2026-10-28 20:42:24 -04:00
+31
View File
@@ -136,6 +136,36 @@ function denoiseSources() {
};
}
// 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 app's
// CSP (rightly) has no blob: there, so DeepFilterNet 3 failed to start ("denoise
// setProcessor failed … Failed to load worklet module script: blob:…"). Write
// the worklet out as a real file next to the module and load it by URL instead,
// which script-src 'self' allows everywhere. Fails the build if the library's
// shape changes, rather than shipping a model that cannot start.
const DFN_WORKLET_FILE = 'dfn-worklet.js';
const DFN_BLOB_LOAD = ` const blob = new Blob([workletCode], { type: 'application/javascript' });
const blobUrl = URL.createObjectURL(blob);
await audioContext.audioWorklet.addModule(blobUrl);`;
function dfnWorkletToFile(esmPath) {
const src = fs.readFileSync(esmPath, 'utf8');
const literal = src.match(/^var workletCode = (".*");\s*$/m)?.[1];
const code = literal ? JSON.parse(literal) : undefined;
if (!code?.includes('registerProcessor(') || !src.includes(DFN_BLOB_LOAD)) {
throw new Error(
`[lotus-denoise] deepfilternet3-noise-filter changed shape (inline worklet / blob loader not found in ${esmPath}) — build aborted; update dfnWorkletToFile in vite.config.js.`,
);
}
fs.writeFileSync(path.join(path.dirname(esmPath), DFN_WORKLET_FILE), code);
fs.writeFileSync(
esmPath,
src.replace(
DFN_BLOB_LOAD,
` // [lotus] Loaded from a file, not a blob: URL (CSP script-src 'self').\n await audioContext.audioWorklet.addModule(new URL('./${DFN_WORKLET_FILE}', import.meta.url).href);`,
),
);
}
// Lotus ML noise suppression: ship the denoise worklets/wasm/models alongside
// the vendored Element Call bundle. Runs after viteStaticCopy has populated
// dist/public/element-call (closeBundle order). [Gitea #293] The dev server
@@ -212,6 +242,7 @@ function lotusDenoise() {
fs.mkdirSync(path.dirname(d), { recursive: true });
fs.copyFileSync(s, d);
});
dfnWorkletToFile(path.join(denoiseDir, 'deepfilternet/index.esm.js'));
// [lotus] DENOISE CUTOVER: the getUserMedia shim is no longer injected.
// Our forked Element Call now runs ML denoise in-source as a real LiveKit