Local-only multicast audio for silent discos. No cloud, tight sync.
Stream DJ audio from your laptop to dozens of phones/devices on the same WiFi network with ultra-low latency (typically 50-200ms). Perfect for silent disco parties, outdoor events, or anywhere you need synchronized audio without cables.
- Ultra-low latency: UDP multicast for real-time audio (~50-200ms delay)
- No internet required: Everything runs on your local network
- Easy client setup: Scan QR code → open in VLC/media player
- Cross-platform: Works with iOS, Android, Windows, macOS, Linux
- Dockerized: Simple deployment, no complex dependencies
- HTTP fallback: Uses udpxy proxy for WiFi compatibility
- Linux host with Docker and Docker Compose installed
- PulseAudio or PipeWire audio system (standard on most Linux desktops)
- Router with multicast support and optionally udpxy for HTTP streaming
- Same WiFi network for DJ laptop and all clients
- udpxy running on your router (converts UDP multicast to HTTP for better WiFi compatibility)
- DNS override capability on your router (to point
dj.danceto the DJ laptop)
This creates a "MixxxMaster" virtual audio device that captures your DJ software output:
make sinkThis installs a systemd user service that persists across reboots.
Auto-detect your system UID and PulseAudio sources:
make envThis creates .env with your configuration. If auto-detection fails:
# List available audio sources
pactl list short sources
# Edit .env and set PULSE_SOURCE manually
# Example: PULSE_SOURCE=alsa_output.pci-0000_00_1f.3.analog-stereo.monitor
nano .envPoint dj.dance to your DJ laptop's LAN IP address (e.g., 192.168.8.100). How to do this depends on your router:
- OpenWrt/LEDE: Add entry in
/etc/hostsor use DNS override - DD-WRT: Services → Additional DNSMasq Options:
address=/dj.dance/192.168.8.100 - pfSense: Services → DNS Resolver → Host Overrides
- Consumer routers: Look for "DNS Override" or "Custom DNS entries" in settings
If your router supports udpxy, enable it on port 4022. This provides HTTP access to UDP multicast streams, which works better across WiFi.
If using a different IP or port, update .env:
UDPXY_HOST=192.168.8.1
UDPXY_PORT=4022Without udpxy, clients must use the raw UDP multicast playlists (stream-udp.m3u).
make upThis builds and starts two Docker containers:
- web: Serves the landing page, playlists, and QR code (port 80)
- streamer: Captures audio and broadcasts via multicast
Set your DJ software (Mixxx, Traktor, etc.) to output audio to:
- Master Output: MixxxMaster (the virtual sink)
- Headphones/Monitor: Your physical audio device
Users on the same WiFi network:
- Open browser to
http://dj.dance/ - Follow instructions for their device (iOS, Android, Windows, etc.)
- Scan QR code or manually open
http://dj.dance/stream.m3uin VLC/nPlayer/mpv
All settings are in .env:
# System
UID=1000 # Your user ID (auto-detected)
# Audio streaming
GROUP=239.255.0.1 # Multicast group (224.0.0.0 - 239.255.255.255)
PORT=1234 # Multicast port (1-65535)
BITRATE=192k # Audio bitrate (128k, 192k, 256k, 320k)
PULSE_SOURCE=MixxxMaster.monitor # PulseAudio source (auto-detected)
# HTTP proxy (optional, recommended)
UDPXY_HOST=192.168.8.1 # Router IP running udpxy
UDPXY_PORT=4022 # udpxy port| Bitrate | Quality | Network Bandwidth | Recommended For |
|---|---|---|---|
| 128k | Good | ~128 kbps | Large events (50+ users), weak WiFi |
| 192k | Very Good | ~192 kbps | Standard (default) |
| 256k | Excellent | ~256 kbps | Small events, strong WiFi |
| 320k | Maximum | ~320 kbps | Audiophile, wired connections |
make help # Show all available commands
make sink # Create MixxxMaster virtual audio sink
make env # Auto-detect configuration and create .env
make up # Build Docker images and start containers
make down # Stop containers
make logs # Follow logs from both containers
make rebuild # Force rebuild (no cache) and restartmake build # Build Docker images only (don't start)
docker compose up -d # Start containers in detached mode
docker compose logs -f streamer # Follow logs for specific service
docker compose exec web sh # Shell into web containerFor events without internet access:
# Prepare on machine with internet
make save-cache # Save images to cache/silentdisco-images.tar
make save-cache-gz # Save images to cache/silentdisco-images.tar.gz (compressed)
# Transfer the cache file to offline machine, then:
make load-cache # Load images from cache (tar or tar.gz)
make up-offline # Load cache (if needed) and start containers without buildingNote: make up-offline automatically checks if images exist, loads from cache if needed, then starts containers. It's the complete offline startup command.
make clean-images # Remove silentdisco Docker images
make clean # Stop containers, remove images and volumes, delete .env# After editing .env
make down
make up
# After editing source code
make rebuild-
Check PulseAudio source:
pactl list short sources | grep monitorEnsure your PULSE_SOURCE in
.envmatches an available monitor source. -
Verify containers are running:
docker ps
Both
silentdisco-webandsilentdisco-streamershould be running. -
Check container logs:
make logs
Look for FFmpeg errors or PulseAudio connection issues.
-
Test direct multicast (on DJ laptop):
ffplay udp://@239.255.0.1:1234
-
Verify DNS resolution:
# On client device ping dj.danceShould resolve to your DJ laptop's IP.
-
Check web server:
curl http://dj.dance/
Should return the landing page HTML.
-
Verify same network: DJ laptop and clients must be on the same WiFi network.
-
Check firewall: Ensure ports 80 (HTTP) and 1234 (UDP) are not blocked.
- Increase buffer size: Edit
streamer/entrypoint.shand increasefifo_size(default: 500000) - Lower bitrate: Change
BITRATE=128kin.env - Check WiFi signal strength: Clients should be close to access point
- Use HTTP mode: Ensure udpxy is configured (better reliability than raw multicast)
The multicast group must be in range 224.0.0.0 to 239.255.255.255. The default 239.255.0.1 is recommended for local networks.
Run make sink to create the virtual audio sink, then make env to regenerate configuration.
-
Check Docker is running:
docker ps
-
Verify .env exists:
cat .env
-
Check PulseAudio socket:
ls /run/user/$(id -u)/pulse/native
Edit .env:
GROUP=239.192.0.1
PORT=5000Then restart: make down && make up
Run multiple instances on different multicast groups/ports. Copy the project directory and edit .env for each stream.
On any client machine:
ffmpeg -i udp://@239.255.0.1:1234 -c copy recording.aac- streamer container: Captures from PulseAudio, encodes to AAC with FFmpeg, broadcasts via UDP multicast
- web container: Runs lighttpd, serves landing page, generates playlists and QR code
- host networking: Required for multicast to work properly
- udpxy proxy: Optional HTTP proxy for multicast (runs on router)
See CLAUDE.md for detailed architecture documentation.
- VLC for Mobile (recommended)
- nPlayer
- OPlayer
- Infuse Pro
- VLC (recommended)
- MX Player
- BSPlayer
- Kodi
- VLC (recommended)
- mpv
- ffplay (FFmpeg)
- Kodi
Note: Web browsers cannot play UDP streams directly. Users must install a compatible media player app.