System Overview

Shiloh Broadcaster is a low-latency audio distribution system built for live broadcast and
monitoring workflows. It routes audio from one or more sender machines through a central
mix bus and delivers it to any number of listener endpoints — local hardware, networked
playback clients, or WebRTC browser sessions.

All components are Rust binaries except the web UI, which is an Elixir/Phoenix LiveView
application.

Component Summary

Component Language Role
shiloh-broadcaster Rust Captures audio from a PipeWire null-sink and sends it to the mixer over UDP
shiloh-mixer Rust JACK mix bus: receives ingest, mixes channels, fans out to relay clients
shiloh-relay Rust Lightweight receiver: plays one mixer bus feed to a local ALSA/cpal device
shiloh-web-relay Rust WebRTC/WHEP egress: subscribes to the mixer and serves Opus streams to browsers
mixer_web Elixir/Phoenix LiveView web UI: fader control, VU meters, scene management, MIDI panel
shiloh-midi-sender Rust Forwards USB MIDI events to the mixer’s MIDI listener over UDP

Signal Flow Diagram

[Laptop / Studio]              [Mixer Server (stg-srv001)]           [Listeners]
                               
shiloh-broadcaster             shiloh-mixer                          shiloh-relay
  PipeWire null-sink  ──UDP──► JACK mix bus ──UDP AUDIO──────────►  (Pi, workstation)
  JACK capture client          (48 kHz JACK, RT thread)              cpal → ALSA out
  REGISTER_TX / AUDIO_TX       3 buses: main / monitor / cue
                                                                      shiloh-web-relay
                               shiloh-mixer ──UDP AUDIO──────────►   Opus encoder
                                                                      WHEP HTTP server
                               mixer_web (Elixir :8889)              ──WebRTC──► browser
                                 polls meters.json / sessions.json
                                 UDP control → :19997

[MIDI keyboard PC]
  shiloh-midi-sender ──UDP──► shiloh-mixer :19999 (MIDI listener)

The Mixer Is the Hub

shiloh-mixer is the central process. Everything else connects to it:

  • shiloh-broadcaster pushes audio in (ingest protocol, port 5005)
  • shiloh-relay / shiloh-web-relay pull audio out (relay protocol, same port 5005)
  • mixer_web sends control commands in (control plane, port 19997)
  • shiloh-midi-sender sends MIDI note-ons in (MIDI listener, port 19999)

All real-time audio work happens on a JACK RT callback thread inside the mixer. The
control plane, relay fan-out, and web sidecar files run on separate threads and
communicate with the RT thread via lock-free SPSC rings and atomic swaps.

Sidecar State Files

The mixer writes JSON sidecar files to ~/mixer-state/ at runtime. mixer_web reads
these to populate the browser UI.

File Contents Rate
meters.json Per-channel peak levels (L/R) ~10 Hz
sessions.json Active UDP + local + broadcaster sessions ~5 Hz
gains.json Current fader / mute state Not currently persisted (in-memory only)
scenes.json Saved scene snapshots On change
relay-assignments.json Client name → feed (main/monitor/cue) On change