mirror of
https://github.com/vector-im/element-call.git
synced 2026-09-04 21:35:19 +00:00
bundle deepfilternet assets within element call bundle
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -7,6 +7,7 @@ dist-ssr
|
|||||||
*.bkp
|
*.bkp
|
||||||
.idea/
|
.idea/
|
||||||
public/config.json
|
public/config.json
|
||||||
|
public/assets/deepfilternet3
|
||||||
backend/synapse_tmp/*
|
backend/synapse_tmp/*
|
||||||
backend/synapse_tmp_othersite/*
|
backend/synapse_tmp_othersite/*
|
||||||
/coverage
|
/coverage
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
"dev:full": "vite",
|
"dev:full": "vite",
|
||||||
"dev:embedded": "vite --config vite-embedded.config.js",
|
"dev:embedded": "vite --config vite-embedded.config.js",
|
||||||
"build": "yarn build:full",
|
"build": "yarn build:full",
|
||||||
"build:full": "NODE_OPTIONS=--max-old-space-size=16384 vite build",
|
"build:full": "yarn setup:assets && NODE_OPTIONS=--max-old-space-size=16384 vite build",
|
||||||
"build:full:production": "yarn build:full",
|
"build:full:production": "yarn build:full",
|
||||||
"build:full:development": "yarn build:full --mode development",
|
"build:full:development": "yarn build:full --mode development",
|
||||||
"build:embedded": "yarn build:full --config vite-embedded.config.js",
|
"build:embedded": "yarn build:full --config vite-embedded.config.js",
|
||||||
@@ -17,6 +17,7 @@
|
|||||||
"build:sdk": "yarn build:full --config vite-sdk.config.js",
|
"build:sdk": "yarn build:full --config vite-sdk.config.js",
|
||||||
"build:sdk:production": "yarn build:sdk",
|
"build:sdk:production": "yarn build:sdk",
|
||||||
"serve": "vite preview",
|
"serve": "vite preview",
|
||||||
|
"setup:assets": "node scripts/setup-noise-suppression-assets.js",
|
||||||
"prettier:check": "prettier -c .",
|
"prettier:check": "prettier -c .",
|
||||||
"prettier:format": "prettier -w .",
|
"prettier:format": "prettier -w .",
|
||||||
"lint": "yarn lint:types && yarn lint:eslint && yarn lint:knip",
|
"lint": "yarn lint:types && yarn lint:eslint && yarn lint:knip",
|
||||||
|
|||||||
152
scripts/setup-noise-suppression-assets.js
Normal file
152
scripts/setup-noise-suppression-assets.js
Normal file
@@ -0,0 +1,152 @@
|
|||||||
|
#!/usr/bin/env node
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Setup script to download DeepFilterNet3 assets for local bundling.
|
||||||
|
* This downloads the WASM binary and AI model from Mezon's CDN
|
||||||
|
* and places them in public/assets/deepfilternet3/ for bundling.
|
||||||
|
*
|
||||||
|
* Usage:
|
||||||
|
* node scripts/setup-noise-suppression-assets.js
|
||||||
|
*
|
||||||
|
* Environment variables:
|
||||||
|
* DEEPFILTERNET3_CDN_URL: Override the default CDN URL (optional)
|
||||||
|
*/
|
||||||
|
|
||||||
|
import fs from "fs";
|
||||||
|
import path from "path";
|
||||||
|
import https from "https";
|
||||||
|
import { fileURLToPath } from "url";
|
||||||
|
|
||||||
|
const __filename = fileURLToPath(import.meta.url);
|
||||||
|
const __dirname = path.dirname(__filename);
|
||||||
|
const projectRoot = path.join(__dirname, "..");
|
||||||
|
|
||||||
|
const CDN_URL =
|
||||||
|
process.env.DEEPFILTERNET3_CDN_URL ||
|
||||||
|
"https://cdn.mezon.ai/AI/models/datas/noise_suppression/deepfilternet3";
|
||||||
|
|
||||||
|
const ASSETS_DIR = path.join(projectRoot, "public", "assets", "deepfilternet3");
|
||||||
|
const V2_DIR = path.join(ASSETS_DIR, "v2");
|
||||||
|
const PKG_DIR = path.join(V2_DIR, "pkg");
|
||||||
|
const MODELS_DIR = path.join(V2_DIR, "models");
|
||||||
|
|
||||||
|
const FILES_TO_DOWNLOAD = [
|
||||||
|
{
|
||||||
|
url: `${CDN_URL}/v2/pkg/df_bg.wasm`,
|
||||||
|
path: path.join(PKG_DIR, "df_bg.wasm"),
|
||||||
|
description: "WASM binary",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
url: `${CDN_URL}/v2/pkg/df_bg.wasm.d.ts`,
|
||||||
|
path: path.join(PKG_DIR, "df_bg.wasm.d.ts"),
|
||||||
|
description: "WASM TypeScript definitions",
|
||||||
|
optional: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
url: `${CDN_URL}/v2/models/DeepFilterNet3_onnx.tar.gz`,
|
||||||
|
path: path.join(MODELS_DIR, "DeepFilterNet3_onnx.tar.gz"),
|
||||||
|
description: "AI Model (ONNX format)",
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
function ensureDir(dir) {
|
||||||
|
if (!fs.existsSync(dir)) {
|
||||||
|
fs.mkdirSync(dir, { recursive: true });
|
||||||
|
console.log(`✓ Created directory: ${dir}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function downloadFile(fileUrl, filePath, isOptional = false) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
const fileName = path.basename(filePath);
|
||||||
|
|
||||||
|
// Skip if already exists
|
||||||
|
if (fs.existsSync(filePath)) {
|
||||||
|
console.log(`✓ Already exists: ${fileName}`);
|
||||||
|
resolve();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(`⏳ Downloading ${fileName}...`);
|
||||||
|
|
||||||
|
https
|
||||||
|
.get(fileUrl, (response) => {
|
||||||
|
// Handle redirects
|
||||||
|
if (
|
||||||
|
response.statusCode === 301 ||
|
||||||
|
response.statusCode === 302 ||
|
||||||
|
response.statusCode === 307
|
||||||
|
) {
|
||||||
|
const redirectUrl = response.headers.location;
|
||||||
|
console.log(` Redirected to: ${redirectUrl}`);
|
||||||
|
downloadFile(redirectUrl, filePath, isOptional).then(resolve).catch(reject);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (response.statusCode !== 200) {
|
||||||
|
const error = new Error(
|
||||||
|
`Download failed: HTTP ${response.statusCode} for ${fileName}`,
|
||||||
|
);
|
||||||
|
if (isOptional) {
|
||||||
|
console.warn(`⚠ Optional file skipped: ${fileName}`);
|
||||||
|
resolve();
|
||||||
|
} else {
|
||||||
|
reject(error);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const fileStream = fs.createWriteStream(filePath);
|
||||||
|
|
||||||
|
response.pipe(fileStream);
|
||||||
|
|
||||||
|
fileStream.on("finish", () => {
|
||||||
|
fileStream.close();
|
||||||
|
const sizeMB = (fs.statSync(filePath).size / 1024 / 1024).toFixed(2);
|
||||||
|
console.log(`✓ Downloaded: ${fileName} (${sizeMB} MB)`);
|
||||||
|
resolve();
|
||||||
|
});
|
||||||
|
|
||||||
|
fileStream.on("error", (err) => {
|
||||||
|
fs.unlink(filePath, () => {}); // Clean up partial file
|
||||||
|
reject(err);
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.on("error", (err) => {
|
||||||
|
if (isOptional) {
|
||||||
|
console.warn(`⚠ Optional file skipped: ${fileName} (${err.message})`);
|
||||||
|
resolve();
|
||||||
|
} else {
|
||||||
|
reject(err);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async function main() {
|
||||||
|
try {
|
||||||
|
console.log("\n🚀 Setting up DeepFilterNet3 assets for bundling...\n");
|
||||||
|
console.log(`📦 CDN URL: ${CDN_URL}`);
|
||||||
|
console.log(`📁 Asset directory: ${ASSETS_DIR}\n`);
|
||||||
|
|
||||||
|
// Ensure directories exist
|
||||||
|
ensureDir(ASSETS_DIR);
|
||||||
|
ensureDir(V2_DIR);
|
||||||
|
ensureDir(PKG_DIR);
|
||||||
|
ensureDir(MODELS_DIR);
|
||||||
|
|
||||||
|
// Download files
|
||||||
|
for (const file of FILES_TO_DOWNLOAD) {
|
||||||
|
await downloadFile(file.url, file.path, file.optional);
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log("\n✅ Asset setup complete!");
|
||||||
|
console.log("\nAssets are ready for bundling. Next build will include them.\n");
|
||||||
|
process.exit(0);
|
||||||
|
} catch (error) {
|
||||||
|
console.error("\n❌ Asset setup failed:", error.message);
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
main();
|
||||||
@@ -34,14 +34,11 @@ export class NoiseSuppressionTransformer {
|
|||||||
// Clamp level between 0-1
|
// Clamp level between 0-1
|
||||||
const clampedLevel = Math.max(0, Math.min(1, level));
|
const clampedLevel = Math.max(0, Math.min(1, level));
|
||||||
|
|
||||||
// Determine asset URL based on environment
|
// Load from bundled local assets by default (avoids CDN/CORS issues),
|
||||||
// In development, use local proxy to avoid CORS issues
|
// but allow override via env var for custom deployments.
|
||||||
// In production, use direct CDN or custom assetConfig
|
const assetUrl =
|
||||||
const isProduction = import.meta.env.PROD;
|
import.meta.env.VITE_NOISE_SUPPRESSION_CDN_URL ||
|
||||||
const assetUrl = isProduction
|
`${window.location.origin}/assets/deepfilternet3`;
|
||||||
? process.env.VITE_NOISE_SUPPRESSION_CDN_URL ||
|
|
||||||
"https://cdn.mezon.ai/AI/models/datas/noise_suppression/deepfilternet3"
|
|
||||||
: `${window.location.origin}/assets/deepfilternet3`;
|
|
||||||
|
|
||||||
this.processor = new DeepFilterNoiseFilterProcessor({
|
this.processor = new DeepFilterNoiseFilterProcessor({
|
||||||
sampleRate: this.sampleRate,
|
sampleRate: this.sampleRate,
|
||||||
|
|||||||
Reference in New Issue
Block a user