Installing the Broadcaster Sender

shiloh-broadcaster runs on any Linux machine that needs to send audio into the mix bus — a studio laptop, a desktop in another room, a guest’s machine on the same LAN. It creates a PipeWire null-sink, captures it via JACK, and streams the audio to shiloh-mixer over UDP.

Prerequisites

  • Linux with PipeWire (and the pipewire-pulse compatibility shim)
  • JACK client libraries (provided by pipewire-jack on modern distros)
  • pactl (part of the pulseaudio-utils package, works with PipeWire)
  • Rust toolchain (if building from source — see Building from Source)

Verify PipeWire is running:

pactl info | grep "Server Name"
# Expected: Server Name: PulseAudio (on PipeWire ...)

Install missing packages if needed:

sudo apt install pipewire pipewire-pulse pipewire-jack pulseaudio-utils

1. Build the binary

cd ~/shiloh-broadcaster
cargo build --release -p shiloh-broadcaster

Optionally install it to ~/.local/bin:

mkdir -p ~/.local/bin
ln -sfn "$(pwd)/target/release/shiloh-broadcaster" ~/.local/bin/shiloh-broadcaster

2. Verify PipeWire null-sink support

shiloh-broadcaster list-sinks

You should see your current sinks listed (output from pactl list sinks short). If pactl fails, PipeWire’s pulse bridge is not active — run systemctl --user start pipewire-pulse.service.

3. Connect to the mixer

The --name argument must match an [[ingest.sender]] entry in the mixer’s shiloh-mixer.toml. --channels must also match the channels value in that entry.

shiloh-broadcaster connect stg-srv001.bq.shilohbv.com:5005 \
    --channels 2 \
    --name "studio"

Replace stg-srv001.bq.shilohbv.com:5005 with your mixer’s address. A stereo send uses --channels 2; a mono send uses --channels 1.

Additional flags:

Flag Default Description
--sink-name NAME Same as --name Override the name shown in PipeWire/PulseAudio sink lists
--no-sink false Skip creating the null-sink (use an externally managed sink)
--verbose / -v false Print per-second packet/underrun counters

On successful connection you will see:

INFO shiloh_broadcaster::sink: loaded null-sink 'studio' (module 42) with 2 channels
INFO shiloh_broadcaster::net: registered with mixer; session=0x1a2b3c4d frames=128 rate=48000

4. Route audio to the null-sink

The null-sink appears in PipeWire/PulseAudio as a normal output device named after --name (or --sink-name). Route audio to it using any of:

GUI — GNOME / KDE sound settings: select studio (or your sink name) as the output device for the application you want to broadcast.

pavucontrol:

pavucontrol
# In the "Playback" tab, click the output selector for your app and choose the null-sink.

pw-link (command-line):

# List available ports
pw-link --output

# Connect a specific app output to the null-sink monitor inputs
pw-link "Ardour:out 1" "studio:monitor_AUX0"
pw-link "Ardour:out 2" "studio:monitor_AUX1"

NOTE: The null-sink’s JACK/PipeWire ports are named {sink_name}:monitor_AUX0, monitor_AUX1, etc. The broadcaster auto-connects these to its own capture ports — you only need to route your application output to the sink, not to the broadcaster’s JACK ports directly.

5. Verify the connection

On the mixer host, watch the logs:

journalctl --user -u shiloh-mixer.service -f

You should see:

INFO shiloh_mixer::ingest: accepted sender "studio" → slots 0..2, session=0x1a2b3c4d

On the broadcaster side with --verbose:

[stat] 375 pps  underruns=0  ring_full=0

375 pps at 128 frames/packet is correct for 48 kHz stereo (48000 / 128 = 375).

6. systemd user unit for auto-start

Create ~/.config/systemd/user/shiloh-broadcaster.service:

[Unit]
Description=shiloh-broadcaster — PipeWire→JACK→UDP audio sender
After=pipewire.service pipewire-pulse.service

[Service]
Type=simple
ExecStart=%h/.local/bin/shiloh-broadcaster connect \
    stg-srv001.bq.shilohbv.com:5005 \
    --channels 2 \
    --name studio
Restart=on-failure
RestartSec=5
Environment=RUST_LOG=info
Environment=XDG_RUNTIME_DIR=/run/user/1000

[Install]
WantedBy=default.target

NOTE: Replace 1000 with your actual UID (id -u). Replace the server address and --name with your values.

systemctl --user daemon-reload
systemctl --user enable shiloh-broadcaster.service
systemctl --user start  shiloh-broadcaster.service
systemctl --user status shiloh-broadcaster.service

Troubleshooting

Symptom Likely cause
pactl load-module failed PipeWire-pulse bridge not running; systemctl --user start pipewire-pulse
rejected by mixer --name does not match any [[ingest.sender]] entry in the mixer config
sample rate mismatch Local JACK session not at 48 kHz; check with pw-jack jack_samplerate
Choppy audio at the relay Increase ring size by setting broadcast_frames = 320 on the mixer
Null-sink disappears on exit Expected — it is unloaded on Drop. The systemd unit will reload it on restart.