Broadcaster Can’t Connect
Use this guide when shiloh-broadcaster connect fails to establish a session with the mixer.
The broadcaster goes through this handshake:
client mixer
|── REGISTER_TX ──────────────▶| (name, channel count, protocol version)
|◀─ ACCEPT_TX or REJECT_TX ───|
|── AUDIO_TX (stream) ────────▶|
|── PING (every 1 s) ─────────▶|
|◀─ PONG ─────────────────────|
Branch 1: DNS resolution failure
Symptom: Startup immediately prints an error like:
ERROR resolving stg-srv001.bq.shilohbv.com:5005: failed to lookup address information
or the process exits before printing accepted:.
Test reachability:
# Check DNS
host stg-srv001.bq.shilohbv.com
# Check UDP reachability (sends one packet, expects no response — that's fine)
nc -u stg-srv001.bq.shilohbv.com 5005
# Then Ctrl-C. No "connection refused" means the port is reachable.
# Or ping the IP directly
ping stg-srv001.bq.shilohbv.com
Common causes:
| Cause | Fix |
|---|---|
| Hostname typo | Double-check --server argument |
| DNS not resolving on this host | Check /etc/resolv.conf; try --server <IP>:5005 |
| Firewall blocking UDP 5005 | See firewall notes in Security |
| On a different network (WAN) | Use WireGuard tunnel; see Security |
Branch 2: Sender name not in allow-list
Symptom: Log on the mixer server shows:
WARN REJECT_TX unknown sender 'studio' from 192.168.1.50:XXXXX
What it means: The --name you passed to shiloh-broadcaster connect does not match any [[ingest.sender]] entry in ~/mixer/shiloh-mixer.toml.
Check the mixer reject log:
journalctl --user -u shiloh-mixer | grep REJECT
Fix — add the sender to the config:
Edit ~/mixer/shiloh-mixer.toml on the mixer server:
[ingest]
slot_count = 2 # must be >= sum of all sender channels
[[ingest.sender]]
name = "studio" # must match --name on the broadcaster
channels = 2
start_slot = 0
Then add or update the channel that reads from this slot:
[[channel]]
id = "studio"
ingest_slot = 0 # matches start_slot above
Restart the mixer to pick up the new config:
systemctl --user restart shiloh-mixer
Branch 3: Channel count mismatch
Symptom: Mixer log shows:
WARN REJECT_TX 'studio' wants 2ch, config 1ch
or vice versa.
What it means: The --channels argument passed to shiloh-broadcaster does not match the channels field for that sender in the TOML config.
Reject code: REJECT_CHANNEL_COUNT (code 0x05).
Fix: Either change --channels on the broadcaster to match the config, or update channels in [[ingest.sender]] and slot_count accordingly, then restart the mixer.
Branch 4: Sample rate mismatch
Symptom: Broadcaster prints a warning like:
WARN sample rate mismatch: local JACK = 44100 Hz, server = 48000 Hz — audio will be pitched
The connection still succeeds, but audio will play back at the wrong pitch and speed. A 44.1 → 48 kHz mismatch causes audio to play ~8.8% fast and about a semitone sharp.
What it means: Your local JACK/PipeWire graph is running at a different sample rate than the mixer server. The broadcaster sends raw S16LE frames; no resampling is done.
Fix — set local PipeWire to 48 kHz:
# Check current rate
pw-metadata -n settings 0 clock.rate
# Set to 48000
pw-metadata -n settings 0 clock.rate 48000
Make permanent in ~/.config/pipewire/pipewire.conf.d/rate.conf:
context.properties = {
default.clock.rate = 48000
}
Then restart PipeWire:
systemctl --user restart pipewire pipewire-pulse wireplumber
Branch 5: Ring full / underruns
Symptom: With --verbose, the stats line shows non-zero ring_full or underruns:
[stat] 375 pps underruns=0 ring_full=47
ring_full means the mixer’s ingest ring buffer is overflowing. The RT JACK thread on the mixer is not consuming samples fast enough relative to the network delivery rate.
underruns means the local JACK callback is not producing samples fast enough for the broadcaster’s TX loop. The TX loop emits silence to maintain cadence, which sounds like dropouts.
Tuning ring_frames (broadcaster side):
The broadcaster sizes its ring at frames * 8 by default (where frames is the mixer’s JACK period). Increase headroom by running with a larger local JACK buffer (see Mixer Won’t Start — xruns).
Diagnosing on the mixer server side:
journalctl --user -u shiloh-mixer | grep "ingest_drop"
If the mixer logs ingest_drop events, its ingest ring is overflowing. The fix is to increase the mixer’s broadcast_frames or reduce the number of concurrent ingest senders.
Branch 6: PipeWire null-sink creation failure
Symptom: Broadcaster exits immediately with:
ERROR loading PipeWire null-sink: ...
The broadcaster creates a PipeWire null-sink at startup (unless --no-sink is passed) so that applications can route audio to it.
Check existing sinks:
pactl list sinks short
Look for shiloh-broadcaster or the --sink-name you specified.
Check for duplicate sink name:
If a previous broadcaster run crashed without cleanup, the sink may still exist. List and remove it:
pactl list modules short | grep null-sink
# Find the module number for your sink, then:
pactl unload-module <module-number>
Restart PipeWire if the sink load still fails:
systemctl --user restart pipewire pipewire-pulse wireplumber
Skip the sink entirely (use an existing one):
shiloh-broadcaster connect --server HOST:PORT --name studio --channels 2 --no-sink
Then route audio to an existing PipeWire sink manually with pw-link or pavucontrol.