Skip to content

Instantly share code, notes, and snippets.

@h4rm0n1c
Last active August 14, 2025 23:09
Show Gist options
  • Save h4rm0n1c/2ac8c543e35efdd4ccb53e8c52f68e2b to your computer and use it in GitHub Desktop.
Save h4rm0n1c/2ac8c543e35efdd4ccb53e8c52f68e2b to your computer and use it in GitHub Desktop.
#create as ~/.config/pipewire/pipewire.conf.d/21-vban-rnnoise-filter.conf
context.modules = [
{ name = libpipewire-module-filter-chain
flags = [ ifexists, nofail ]
args = {
node.name = "RNNOISEMONO"
node.description = "RNNOISEMONO"
media.class = "Audio/Filter"
audio.rate = 48000
audio.channels = 1
audio.position = [ MONO ]
filter.graph = {
nodes = [
{ type = ladspa
name = rnnoise
plugin = "/usr/lib/ladspa/librnnoise_ladspa.so"
label = "noise_suppressor_mono"
}
]
inputs = [ "rnnoise:Input" ]
outputs = [ "rnnoise:Output" ]
}
}
}
]

What is this? A vban reciever daemon for your microphone audio from voicemeeter in windows, to your linux box, this inserts a "rnnoise" filter in the audio chain

You end up with a Microphone device that can work in OBS studio, Veadotube mini, prefiltered, no nvidia AI garbage required, no developer SDKs.

you will need the prerequisite pipewire, pipewire-jack, rnnoise filters, etc... consult with google or chatgpt for instructions on obtaining pre-requisites for this script.

I have run this on Devuan Daedalus which is equivalent to Debian 12, under a minimal XFCE env with flatpab OBS, works great.

My linux powerlevel is rising.

#!/bin/sh
# Minimal VBAN → CleanBus → RNNoise → MicBus → VBAN_Mic setup
# PipeWire (Pulse-based) audio flow with JACK filter-chain for RNNoise
VBAN_HOST=10.0.42.249
VBAN_PORT=6980
SCREEN_NAME=vban_mic
VBAN_SOURCE_NAME=rawmic
INGEST_SINK=CleanBus
MIC_SINK=MicBus
VIRTUAL_MIC=VBAN_Mic
start() {
echo "Starting VBAN service…"
screen -S "$SCREEN_NAME" -X quit 2>/dev/null || true
ensure_pipewire_ready
ensure_virtual_devices
echo "Launching vban_receptor…"
screen -dmS "$SCREEN_NAME" \
env PULSE_SINK="$INGEST_SINK" \
vban_receptor -i "$VBAN_HOST" -p "$VBAN_PORT" -s "$VBAN_SOURCE_NAME" -b pulseaudio -d "VBAN RX" --channels=1
# Wait and forcibly seat VBAN on CleanBus
for _ in $(seq 1 80); do
ID="$(pactl list sink-inputs | awk '
/^[[:space:]]*Sink Input #/ { cur=$0; sub(/^.*#/, "", cur); sub(/[^0-9].*$/, "", cur) }
/application.process.binary = "vban_receptor"/ { print cur; exit }
/application.name = "VBAN RX"/ { print cur; exit }
')"
[ -n "$ID" ] && { pactl move-sink-input "$ID" "$INGEST_SINK" >/dev/null 2>&1 || true; break; }
sleep 0.25
done
# Link CleanBus → RNNoise → MicBus
pw-link "${INGEST_SINK}:monitor_MONO" "input.RNNOISEMONO:input_FL" 2>/dev/null || true
pw-link "output.RNNOISEMONO:output_FL" "${MIC_SINK}:playback_MONO" 2>/dev/null || true
echo "VBAN mic active: $SOURCE_NAME"
}
stop() {
echo "Stopping VBAN service…"
screen -S "$SCREEN_NAME" -X quit 2>/dev/null || true
}
purge() {
stop
for name in "$INGEST_SINK" "$MIC_SINK"; do
pactl unload-module "$(pactl list short modules | awk "/module-null-sink/ && /$name/ {print \$1}")" 2>/dev/null || true
done
pactl unload-module "$(pactl list short modules | awk "/module-remap-source/ && /$VIRTUAL_MIC/ {print \$1}")" 2>/dev/null || true
}
status() {
echo "VBAN status:"
screen -list | grep -q "$SCREEN_NAME" && echo " → Running" || echo " → Not running"
pw-link -l | awk '
/^CleanBus:monitor_MONO$/ { print; getline; print }
/^MicBus:playback_MONO$/ { print; getline; print }
/^input.RNNOISEMONO:input_FL$/ { print; getline; print }
/^output.RNNOISEMONO:output_FL$/ { print; getline; print }
/^input.VBAN_Mic:input_MONO$/ { print; getline; print }
'
}
case "$1" in
start) start ;;
stop) stop ;;
restart) stop; sleep 1; start ;;
purge) purge ;;
status) status ;;
*) echo "Usage: $0 {start|stop|restart|purge|status}" ;;
esac
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment