Self-hosted shared radio โ everyone listens in sync
๐ง Turn any link into a shared listening experience
Paste a YouTube, SoundCloud, Mixcloud, or Spotify playlist link โ
Airwave creates a single live stream โ
Everyone hears the exact same audio
No accounts. No premium APIs. No โpress play at the same time.โ
โก Try it in 30 seconds
docker run -d -p 8000:8000 ghcr.io/76696265636f646572/airwave
Open โ http://localhost:8000
Paste a link โ music starts โ share the URL ๐
๐ง The idea (why this exists)
Many music apps werenโt built for shared listening:
- Everyone plays their own stream
- Locked into one platform
Airwave solves this:
- One stream โ multiple listeners
- Works across browsers and Sonos
- Import Spotify playlists โ automatically matched to playable tracks
- Multi-source playback (YouTube, SoundCloud, Mixcloud, direct URLs, optional local files)
Simple idea. Huge difference.
โจ What makes Airwave different?
๐ One shared live stream
- One
/stream/live.mp3 - All listeners hear the same thing
- No per-user transcoding
- Perfect sync across devices
๐ Collaborative queue
- Anyone can add tracks
- Drag & reorder in real time
- Shared history
โถ๏ธ Multi-source playback
- YouTube (videos + playlists)
- SoundCloud (tracks + sets)
- Mixcloud (shows)
- Direct HTTP(S) URLs to audio when ffmpeg can read them
- Local files
๐ Paste almost any music link โ it just works
๐ฟ Local files & folders
- Point Airwave at one or more directories with
AIRWAVE_LOCAL_MEDIA_ROOTS - Browse and queue tracks from the UI (paths must stay inside those roots)
- Great for NAS mounts, a music library on disk, or bind-mounted folders in Docker
๐ต Spotify โ playable music
- Import Spotify playlists into your library
- Auto-match tracks to YouTube, SoundCloud, or Mixcloud
- Review and pick the best version for your shared stream
๐ Sonos integration
- Discover speakers on your LAN
- Group and control playback
- Same stream as browser clients
๐ฎ Player experience
- Play / pause / skip / repeat
- Seek (when supported)
- Fullscreen โNow Playingโ
- Lock screen controls (Media Session)
๐ Library & playlists
- Create and manage playlists
- Import YouTube or Spotify playlists
- Merge playlists (with deduplication)
- Pin and reorder
๐ Playlist auto-sync
- Turn on Auto-sync (๐) for any imported playlist
- New tracks are added automatically
- Your order stays untouched
Optional: remove tracks that disappear from the source (off by default)
๐งโ๐คโ๐ง Perfect for
- ๐ Parties (everyone queues music)
- ๐ Shared household audio
- ๐งโ๐ป Remote team listening
- ๐ Sonos multi-room setups
- ๐ง Friends hanging out online
๐ง How it works
yt-dlp โ ffmpeg โ shared MP3 stream โ all listeners
- One pipeline
- One stream
- Unlimited listeners
๐ณ Docker (recommended)
For full functionality (especially Sonos):
Set your public URL:
AIRWAVE_PUBLIC_BASE_URL=http://192.168.1.50:8000
For local files, mount host directories into the container and set AIRWAVE_LOCAL_MEDIA_ROOTS to those in-container paths (see Configuration below).
โ๏ธ Configuration
AIRWAVE_HOST=0.0.0.0 AIRWAVE_PORT=8000 AIRWAVE_PUBLIC_BASE_URL=http://192.168.1.50:8000 AIRWAVE_FFMPEG_PATH=./bin/ffmpeg AIRWAVE_FFPROBE_PATH=./bin/ffprobe AIRWAVE_YT_DLP_PATH=./bin/yt-dlp AIRWAVE_DENO_PATH=./bin/deno # Optional: allow browsing and queuing audio from these directories (server-side paths). # Comma-separated list, or a JSON array string, e.g. ["/music","/data/audio"]. # Leave unset to disable local media. In Docker, bind-mount the host folders and set paths inside the container. AIRWAVE_LOCAL_MEDIA_ROOTS=/path/to/music,/other/library AIRWAVE_MP3_BITRATE=128k AIRWAVE_CHUNK_SIZE=256 AIRWAVE_STREAM_QUEUE_SIZE=16 AIRWAVE_LOG_LEVEL=info # Optional: background playlist auto-sync (SyncService). Only playlists with Auto-sync # enabled in the UI are considered each pass. # Target seconds between the *start* of one sync pass and the start of the next (minimum 30). # If a pass takes longer than this, the next pass begins about a second after the long one ends. AIRWAVE_PLAYLIST_SYNC_INTERVAL_SECONDS=3600 # Max playlists to sync at once within a pass (1โ10). AIRWAVE_PLAYLIST_SYNC_MAX_CONCURRENT=2
AIRWAVE_FFMPEG_PATH and AIRWAVE_FFPROBE_PATH are configured independently. Point each one to the executable you want Airwave to use.
AIRWAVE_CHUNK_SIZE is how many bytes are read from ffmpegโs stdout per pull into the shared stream (default 256). Larger values mean fewer read syscalls; very small values increase overhead. AIRWAVE_STREAM_QUEUE_SIZE is the max depth of the in-memory buffer between ffmpeg and connected listeners (default 16). Raise it if devices such as Sonos underrun the live stream.
๐งฑ Tech Stack
- FastAPI
- Vue 3
- yt-dlp
- ffmpeg
- SQLite
๐ Architecture (simplified)
- StreamEngine โ playback worker & prefetch
- FfmpegPipeline โ transcoding & ffprobe probing
- MediaSourceResolver โ local files & direct media URLs
- PlaylistService โ queue/import orchestration
- SyncService โ optional background sync for imported playlists (off per playlist until enabled)
- SharedMp3Hub โ fan-out
- BinariesService โ yt-dlp/ffmpeg/ffprobe/deno management
- Repository โ persistence
๐ฌ Why Airwave?
Because shared music should be:
- simple
- synced
- platform-independent
Not:
- fragmented
- locked-in
- out of sync
๐ค Contributing
Ideas, issues, and PRs welcome!
๐ See CONTRIBUTING.md
โญ Support
If you like Airwave:
- โญ Star the repo
- ๐ Report bugs
- ๐ก Suggest features
- ๐ข Share it
๐งญ Final thought
Airwave isnโt a music player. Itโs a shared radio for the internet.
