livekit-plugins-dtln
v0.1.5
Published
DTLN noise suppression plugin for LiveKit — self-hosted, in-process, no cloud API
Maintainers
Readme
livekit-plugins-dtln
In-process DTLN noise suppression for Node.js — self-hosted, open-source alternative to Krisp/noisecancellation plugins. No cloud API, no per-minute billing. Works with any LiveKit deployment or standalone.
Install
npm install livekit-plugins-dtlnONNX model weights (~4 MB) are bundled in the package — no extra downloads needed.
Quick Start
import { DTLNNoiseSuppressor } from "livekit-plugins-dtln";
const suppressor = new DTLNNoiseSuppressor({ strength: 0.7 });
await suppressor.init();
// Process 16kHz mono float32 audio
const denoised = await suppressor.processAudio(samples);
// Or raw Int16 PCM (WebRTC-style)
const denoisedPcm = await suppressor.processInt16(pcmBuffer);
// Done
await suppressor.close();With LiveKit (@livekit/rtc-node)
Handles any sample rate (48kHz, 16kHz, etc.) and channel count automatically:
import { DTLNNoiseSuppressor } from "livekit-plugins-dtln";
import { Room, RoomEvent, AudioStream } from "@livekit/rtc-node";
const suppressor = new DTLNNoiseSuppressor({ strength: 0.7 });
await suppressor.init();
room.on(RoomEvent.TrackSubscribed, (track) => {
const stream = new AudioStream(track, 16000, 1);
for await (const frame of stream) {
const denoised = await suppressor.processFrame(
frame.data, // Int16Array — any sample rate
frame.sampleRate, // 48000, 16000, etc.
frame.channels, // 1 or 2
);
// publish or use denoised audio...
}
});API
new DTLNNoiseSuppressor(options?)
| Option | Type | Default | Description |
| -------------- | --------- | ------- | ------------------------------------------------ |
| strength | number | 0.5 | Wet/dry blend (0 = bypass, 1 = full suppression) |
| model1Path | string | bundled | Path to model_1.onnx |
| model2Path | string | bundled | Path to model_2.onnx |
| debugLogging | boolean | false | Log spectral mask stats every ~800ms |
Methods
| Method | Input | Output | Use case |
| ----------------------------- | ------------------------------- | ----------------------- | ------------------------------- |
| init() | — | Promise<void> | Load ONNX models (call once) |
| processAudio(samples) | Float32Array 16kHz mono | Promise<Float32Array> | Pre-resampled audio |
| processInt16(pcm) | Int16Array 16kHz mono | Promise<Int16Array> | Raw PCM buffers |
| processFrame(pcm, rate, ch) | Int16Array, any rate/channels | Promise<Int16Array> | LiveKit frames (auto-resamples) |
| close() | — | Promise<void> | Release ONNX sessions |
Properties
enabled— get/set boolean to bypass processinginitialized— read-only, true afterinit()
How It Works
Two-stage LSTM pipeline via ONNX Runtime:
Audio → FFT → Magnitude → [LSTM Model 1: Spectral Mask] → Masked IFFT
→ [LSTM Model 2: Time-domain Refinement] → Denoised Output- ~10 dB noise reduction on typical speech+noise
- ~3ms latency per frame on modern hardware
- Stateful LSTM — one instance per call session
- Models from DTLN (Westhausen & Meyer, Interspeech 2020)
Platform Support
| Platform | Status |
| ---------------------- | ------ |
| Linux x64 | ✓ |
| Linux ARM64 (Graviton) | ✓ |
| macOS x64/ARM | ✓ |
| Windows x64 | ✓ |
| Node.js 18+ | ✓ |
| CommonJS (require) | ✓ |
| ESM (import) | ✓ |
Performance
- CPU: ~2-4ms per 128-sample frame (8ms of audio) on x86-64
- Memory: ~50 MB (ONNX Runtime + model weights)
- Concurrency: One instance per session; safe to run many in parallel
License
MIT
Credits
- DTLN model: breizhn/DTLN (MIT)
- ONNX Runtime: microsoft/onnxruntime (MIT)
- Python version: aloware/livekit-plugins-dtln
