First Session
This walkthrough gets you from a cold system to a working audio feed in one browser tab
and one relay speaker. It assumes:
stg-srv001is the mixer server (Ubuntu 24.04, PipeWire running)- One laptop or workstation is the broadcaster machine
- One Raspberry Pi or other Linux box will be the relay listener
- You have all binaries built and on PATH
Step 1: Verify JACK is running on the mixer server
shiloh-mixer uses JACK via the PipeWire JACK shim. Confirm PipeWire is active and the
JACK shim is in place:
ssh stg-srv001
pw-jack jack_lsp 2>&1 | head -5
You should see system port names. If jack_lsp hangs or errors, check PipeWire:
systemctl --user status pipewire pipewire-pulse wireplumber
Step 2: Start shiloh-mixer with a minimal config
Create a minimal ~/mixer/shiloh-mixer.toml:
jack_name = "shiloh-mixer"
broadcast_port = 5005
control_port = 19997
[ingest]
slot_count = 2
[[ingest.sender]]
name = "studio"
channels = 2
start_slot = 0
[[channels]]
id = "bcast1"
label = "Studio"
kind = "stereo"
main_gain = 1.0
ingest_slot = 0
Start the mixer:
shiloh-mixer --config ~/mixer/shiloh-mixer.toml
Expected log output:
INFO shiloh_mixer: config (json): 1 channels, jack_name=shiloh-mixer, control=127.0.0.1:19997, broadcast_port=5005
INFO shiloh_mixer::jack_io: jack client 'shiloh-mixer' opened (sample_rate=48000 buffer=1024 frames, status=Empty)
INFO shiloh_mixer::broadcast: broadcast relay listening on udp://0.0.0.0:5005
Step 3: Route an audio source to the null-sink on the broadcaster machine
On the broadcaster laptop, verify PipeWire is running and check that the null-sink will
appear properly when the broadcaster starts it:
pactl info | grep -i server
Route any audio source to the broadcaster sink. You can test with a tone generator:
# This creates a null-sink manually to test routing
# (shiloh-broadcaster does this automatically on startup)
pactl load-module module-null-sink sink_name=studio media.class=Audio/Sink channel_map=stereo
pactl list sinks short | grep studio
Use pavucontrol or pw-link to route an application’s output to the studio sink.
The broadcaster will connect to this same sink automatically.
Step 4: Start shiloh-broadcaster, verify connection in logs
On the broadcaster laptop (remove the manually-created null-sink first if you tested
above, as the broadcaster creates its own):
pactl unload-module $(pactl list modules short | grep studio | awk '{print $1}')
shiloh-broadcaster connect \
--server stg-srv001:5005 \
--name studio \
--channels 2
Expected output:
INFO shiloh_broadcaster: server: stg-srv001:5005 → 192.168.0.64:5005
INFO shiloh_broadcaster::sink: loaded null-sink 'studio'
INFO shiloh_broadcaster::capture: jack client 'studio-send' opened (sample_rate=48000 buffer=1024)
INFO shiloh_broadcaster::capture: autoconnect: studio:monitor_AUX0 → studio-send:in_1
INFO shiloh_broadcaster::capture: autoconnect: studio:monitor_AUX1 → studio-send:in_2
INFO shiloh_broadcaster::net: accepted: session=0xabcd1234 48000 Hz 2 ch 128 frames/pkt slot=0
If you see REJECT_TX unknown sender, the --name flag doesn’t match any entry in
[[ingest.sender]] in the mixer config. Check spelling — it’s case-sensitive.
Now route an audio source to the studio sink using pavucontrol or by setting it as
the default output device.
Step 5: Open mixer_web, confirm the input strip is active and metering
Start mixer_web if it isn’t already running:
# On stg-srv001
systemctl --user status mixer_web
# or start it manually:
cd ~/mixer_web && MIX_ENV=prod mix phx.server
Open http://stg-srv001:8889 in a browser. You should see:
- The “Studio” fader strip visible
- The VU meters flickering when audio plays on the broadcaster machine
- In the session list, “studio” listed as a connected broadcaster
If meters are flat: confirm audio is routing to the studio null-sink on the broadcaster.
Use pw-top to verify the sink is receiving samples.
Step 6: Start shiloh-relay on a listening machine
On the Pi or another Linux machine:
shiloh-relay connect \
--server stg-srv001:5005 \
--name pi-relay
Expected output:
INFO shiloh_relay: server: stg-srv001:5005 → 192.168.0.64:5005
INFO shiloh_relay::net: accepted: session=0x00000042 48000 Hz 2 ch 128 frames/pkt
INFO shiloh_relay::audio: opened output device 'default' (48000 Hz, 2 ch)
Audio from the broadcaster should now be audible on the relay machine’s default audio
output.
If you hear silence:
- Is audio actually playing on the broadcaster and routed to the null-sink?
- Run with
--verboseto check fordropsorring_fullin the stats line. - In
mixer_web, check the sessions panel: findpi-relayand confirm its feed
assignment is “main”. If it shows a different feed, click to change it.
Step 7: Adjust fader levels in the web UI
In mixer_web at http://stg-srv001:8889:
- Drag the Studio fader to adjust the main mix contribution for that channel.
- Click the mute button (speaker icon) to silence the channel on the main bus.
Monitor and cue buses are mute-exempt — they always carry signal. - Use the relay gain control on the output bus section to scale the relay send level
independently from the main JACK output.
Changes are applied immediately on the mixer’s RT thread and written to gains.json for
persistence across restarts.
Common First-Session Problems
| Symptom | Likely cause |
|---|---|
Broadcaster: REJECT_TX unknown sender |
--name not matching any [[ingest.sender]] in config (case-sensitive) |
| Autoconnect times out after 30 s | PipeWire null-sink ports didn’t settle; check pw-jack jack_lsp |
| Relay connects but no audio | Check feed assignment in mixer_web; check mute state on channel |
| VU meters flat in mixer_web | Audio not routed to null-sink; verify with pw-top or pavucontrol |
| Relay audio choppy / clicking | Ring underruns; try --buffer-ms 100 on the relay |
| Sample rate mismatch warning | JACK on broadcaster isn’t at 48 kHz; fix PipeWire default sample rate |
JACK client (is the JACK server running?) error |
PipeWire JACK shim not active; check systemctl --user status pipewire |