mirror of
https://github.com/zephrynis/nix-flake.git
synced 2026-08-17 21:45:53 +00:00
noise-suppression: RNNoise virtual mic via PipeWire, enable on host
App-independent mic denoising as a PipeWire filter-chain exposing a "Noise Canceling source" — replaces Discord's unusable Krisp and works in every app. Imported into the nixos-pc host. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -8,6 +8,7 @@
|
||||
../../modules/nvidia.nix
|
||||
../../modules/gaming.nix
|
||||
../../modules/tailscale.nix
|
||||
../../modules/noise-suppression.nix
|
||||
];
|
||||
|
||||
networking.hostName = "nixos-pc";
|
||||
|
||||
74
modules/noise-suppression.nix
Normal file
74
modules/noise-suppression.nix
Normal file
@@ -0,0 +1,74 @@
|
||||
{ pkgs, ... }:
|
||||
|
||||
# App-independent microphone noise suppression via PipeWire + RNNoise.
|
||||
#
|
||||
# Replaces Discord's Krisp (which can't be enabled on current nixpkgs Discord:
|
||||
# the binary is patchelf'd, and even after bypassing Krisp's signature check the
|
||||
# newer "THz SDK" stage fails with KRISP_INIT_ERROR_GLOBAL_INIT). Instead we run
|
||||
# RNNoise as a PipeWire filter-chain that exposes a cleaned virtual microphone.
|
||||
#
|
||||
# This works in EVERY app (Discord, browser, OBS, games), survives Discord
|
||||
# updates, and touches no DRM. In each app's input settings, pick the source
|
||||
# named "Noise Canceling source" instead of the raw mic.
|
||||
|
||||
{
|
||||
# LADSPA plugin providing noise_suppressor_mono/stereo (werman RNNoise).
|
||||
environment.systemPackages = [ pkgs.rnnoise-plugin ];
|
||||
|
||||
services.pipewire.extraConfig.pipewire."99-input-denoising" = {
|
||||
"context.modules" = [
|
||||
{
|
||||
name = "libpipewire-module-filter-chain";
|
||||
args = {
|
||||
"node.description" = "Noise Canceling source";
|
||||
"media.name" = "Noise Canceling source";
|
||||
"filter.graph" = {
|
||||
nodes = [
|
||||
{
|
||||
type = "ladspa";
|
||||
name = "rnnoise";
|
||||
plugin = "${pkgs.rnnoise-plugin}/lib/ladspa/librnnoise_ladspa.so";
|
||||
label = "noise_suppressor_mono";
|
||||
control = {
|
||||
# Higher threshold = more aggressive gating of non-voice.
|
||||
# 50% is a balanced starting point; raise toward 90–95 if a
|
||||
# noisy background still leaks through, lower if speech clips.
|
||||
"VAD Threshold (%)" = 50.0;
|
||||
"VAD Grace Period (ms)" = 200.0;
|
||||
"Retroactive VAD Grace (ms)" = 0.0;
|
||||
};
|
||||
}
|
||||
{
|
||||
# Makeup gain baked into the graph so the source volume is
|
||||
# reproducible instead of living only in WirePlumber's runtime
|
||||
# state. Mult = 1.53 matches the 153% level set in the mixer.
|
||||
type = "builtin";
|
||||
name = "gain";
|
||||
label = "linear";
|
||||
control = {
|
||||
"Mult" = 1.53;
|
||||
"Add" = 0.0;
|
||||
};
|
||||
}
|
||||
];
|
||||
links = [
|
||||
{ output = "rnnoise:Output"; input = "gain:In"; }
|
||||
];
|
||||
};
|
||||
# The virtual mic apps select. media.class = Audio/Source makes it
|
||||
# appear as a capture device throughout the desktop.
|
||||
"capture.props" = {
|
||||
"node.name" = "capture.rnnoise_source";
|
||||
"node.passive" = true;
|
||||
"audio.rate" = 48000;
|
||||
};
|
||||
"playback.props" = {
|
||||
"node.name" = "rnnoise_source";
|
||||
"media.class" = "Audio/Source";
|
||||
"audio.rate" = 48000;
|
||||
};
|
||||
};
|
||||
}
|
||||
];
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user