A cross-platform, low-latency LAN audio bridge between Linux and macOS.
It captures “what you hear” (system or app audio), encodes with Opus, ships over RTP/UDP, and plays it on the other machine.
Think “DIY Dante Lite” for home/office, written in Rust.
- 🔄 Bidirectional streaming (run on both machines).
- 🎧 Captures system audio (BlackHole on macOS, PipeWire monitor on Linux).
- ⚡ Low-latency Opus (2.5–5 ms frames).
- 🔊 Automatic playback on system speakers.
- 🌐 Optional mDNS advertisement for peer auto-discovery.
cd scripts
./macos_setup.sh
This installs:
- GStreamer + plugins
- BlackHole 2ch (virtual device)
- SwitchAudioSource CLI
Then in Audio MIDI Setup:
-
Create a Multi-Output Device with:
- ✅ BlackHole 2ch
- ✅ Your speakers (MacBook Speakers / Headphones)
-
Set it as the default output.
cd scripts
./linux_setup.sh
This installs:
- GStreamer + plugins
- PipeWire + WirePlumber
- Pulseaudio utils (
pactl
)
It also creates a null sink called bridge_out
.
Use its .monitor
source as your TX input.
Install Rust (1.75+ recommended):
cargo build --release
Binary is at:
target/release/ab-daemon
./target/release/ab-daemon --listen-port 5004
AB_SRC_BUFFER_US=200000 AB_SRC_LATENCY_US=10000 \
./target/release/ab-daemon \
--capture-device "BlackHole 2ch" \
--send-to <LINUX_IP> \
--send-port 5002 \
--listen-port 5004
- Replace
<LINUX_IP>
with your Linux machine’s LAN IP. - Run the reverse command on Linux (with
--send-to <MAC_IP>
) for full duplex.
💡 Note: AB_SRC_BUFFER_US
and AB_SRC_LATENCY_US
are critical on macOS.
Start with 200000
/ 10000
and tune as needed.
# macOS (sender)
gst-launch-1.0 osxaudiosrc device="BlackHole 2ch" \
! audioconvert ! audioresample \
! opusenc frame-size=2.5 bitrate=256000 \
! rtpopuspay pt=97 \
! udpsink host=<LINUX_IP> port=5004
# Linux (receiver)
gst-launch-1.0 udpsrc port=5004 caps="application/x-rtp,media=audio,encoding-name=OPUS,clock-rate=48000,pt=97" \
! rtpjitterbuffer latency=30 drop-on-late=true do-lost=true \
! rtpopusdepay ! opusdec \
! audioconvert ! audioresample ! pipewiresink
-
Silence on macOS sender Ensure you run from the Terminal (not VSCode), so the app has microphone permissions. Set
AB_SRC_BUFFER_US=200000
andAB_SRC_LATENCY_US=10000
. -
CoreAudio device not found Check your device list with:
gst-device-monitor-1.0 Audio
Then use the correct
--capture-device <INDEX>
. -
Linux internal mic sounds noisy Use the
.monitor
source of a null sink (e.g.,bridge_out.monitor
) instead of the raw mic. -
No audio on Linux playback Confirm the RTP caps match exactly (
payload=97
,clock-rate=48000
,encoding-name=OPUS
).
- Drift correction (adaptive resampling).
- SRTP/DTLS encryption.
- WebRTC transport for WAN.
- GUI (Tauri tray app with meters).
- Per-app routing (Loopback on macOS, PipeWire filters on Linux).
- Better install scripts (brew/apt).
- Smart Setup Scripts, that handles inputs and outputs cleanly, and save the default for graceful exit.
- Graceful exit, currently it's just Ctrl + C, re assigns the inputs and outputs to what they were.
- Add smarter handling for the same in case is they want to pause the connection or similar.
- Make it adaptable to windows too.
MIT