mirror of
https://github.com/vector-im/element-call.git
synced 2026-08-02 19:49:23 +00:00
implement noise reduction based on DeepFilterNet3
This commit is contained in:
147
src/livekit/NoiseSuppressionTransformer.ts
Normal file
147
src/livekit/NoiseSuppressionTransformer.ts
Normal file
@@ -0,0 +1,147 @@
|
||||
/*
|
||||
Copyright 2024 New Vector Ltd.
|
||||
|
||||
SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
|
||||
Please see LICENSE in the repository root for full details.
|
||||
*/
|
||||
|
||||
import { DeepFilterNoiseFilterProcessor } from "deepfilternet3-noise-filter";
|
||||
import { logger } from "matrix-js-sdk/lib/logger";
|
||||
|
||||
/**
|
||||
* Wrapper for DeepFilterNet3 Noise Suppression Processor.
|
||||
* Integrates with LiveKit audio track processing.
|
||||
*/
|
||||
export class NoiseSuppressionTransformer {
|
||||
private processor: DeepFilterNoiseFilterProcessor | null = null;
|
||||
private initialized = false;
|
||||
private readonly sampleRate: number = 48000;
|
||||
|
||||
/**
|
||||
* Initialize the noise suppression processor
|
||||
* @param level - Noise reduction level (0-1)
|
||||
* @param enabled - Whether noise suppression is enabled
|
||||
*/
|
||||
public async initialize(
|
||||
level: number = 0.75,
|
||||
enabled: boolean = true,
|
||||
): Promise<void> {
|
||||
if (this.initialized) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
// Clamp level between 0-1
|
||||
const clampedLevel = Math.max(0, Math.min(1, level));
|
||||
|
||||
// Determine asset URL based on environment
|
||||
// In development, use local proxy to avoid CORS issues
|
||||
// In production, use direct CDN or custom assetConfig
|
||||
const isProduction = import.meta.env.PROD;
|
||||
const assetUrl = isProduction
|
||||
? 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({
|
||||
sampleRate: this.sampleRate,
|
||||
noiseReductionLevel: clampedLevel * 100,
|
||||
enabled,
|
||||
assetConfig: {
|
||||
cdnUrl: assetUrl,
|
||||
},
|
||||
});
|
||||
|
||||
this.initialized = true;
|
||||
logger.log(
|
||||
`[NoiseSuppressionTransformer] Initialized with level=${clampedLevel}, enabled=${enabled}, assetUrl=${assetUrl}`,
|
||||
);
|
||||
} catch (error) {
|
||||
logger.error(
|
||||
"[NoiseSuppressionTransformer] Initialization failed:",
|
||||
error,
|
||||
);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the underlying processor instance
|
||||
*/
|
||||
public getProcessor(): DeepFilterNoiseFilterProcessor | null {
|
||||
return this.processor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the noise reduction level (0-1)
|
||||
*/
|
||||
public setSuppressionLevel(level: number): void {
|
||||
if (!this.processor) {
|
||||
logger.warn(
|
||||
"[NoiseSuppressionTransformer] Processor not initialized, cannot set suppression level",
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
const clampedLevel = Math.max(0, Math.min(1, level));
|
||||
try {
|
||||
this.processor.setSuppressionLevel(clampedLevel * 100);
|
||||
logger.log(
|
||||
`[NoiseSuppressionTransformer] Suppression level set to ${clampedLevel}`,
|
||||
);
|
||||
} catch (error) {
|
||||
logger.error(
|
||||
"[NoiseSuppressionTransformer] Failed to set suppression level:",
|
||||
error,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable or disable noise suppression
|
||||
*/
|
||||
public setEnabled(enabled: boolean): void {
|
||||
if (!this.processor) {
|
||||
logger.warn(
|
||||
"[NoiseSuppressionTransformer] Processor not initialized, cannot set enabled state",
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
this.processor.setEnabled(enabled);
|
||||
logger.log(
|
||||
`[NoiseSuppressionTransformer] Noise suppression ${enabled ? "enabled" : "disabled"}`,
|
||||
);
|
||||
// Log processor state for debugging
|
||||
const processorState = (this.processor as any).enabled;
|
||||
logger.debug(
|
||||
`[NoiseSuppressionTransformer] Processor internal state: enabled=${processorState}`,
|
||||
);
|
||||
} catch (error) {
|
||||
logger.error(
|
||||
"[NoiseSuppressionTransformer] Failed to set enabled state:",
|
||||
error,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Clean up resources
|
||||
*/
|
||||
public destroy(): void {
|
||||
if (this.processor) {
|
||||
try {
|
||||
// Note: DeepFilterNoiseFilterProcessor may have a destroy method
|
||||
// Call it if available
|
||||
if (typeof (this.processor as any).destroy === "function") {
|
||||
(this.processor as any).destroy();
|
||||
}
|
||||
} catch (error) {
|
||||
logger.error("[NoiseSuppressionTransformer] Cleanup failed:", error);
|
||||
}
|
||||
this.processor = null;
|
||||
this.initialized = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user