GitHub - 76696265636f646572/Airwave: Shared live audio from YouTube. Add tracks and playlists to the queue, stream to browsers and Sonos and more.

4 min read Original article โ†—

Self-hosted shared radio โ€” everyone listens in sync

GitHub stars GitHub forks Python FastAPI Vue

๐ŸŽง 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.โ€

Airwave Demo


โšก 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.