Overview
Add a tuitube serve (or tuitube broadcast) command that streams the currently playing audio as a continuous HTTP audio stream — like a personal internet radio station. Any device on the LAN (phone, laptop, TV browser) can tune in by opening a single URL. No frontend, no app, no playback controls required.
How It Works
tuitube playing a playlist (TUI works as normal)
└── mpv audio output → ffmpeg pipe → Go HTTP chunked response
└── http://<LAN-IP>:8080/stream
├── phone browser → <audio src="..."> just plays
├── VLC / mpv → open URL, plays immediately
└── any browser → works out of the box
mpv continues playing normally in the TUI. The broadcast layer taps into the audio output (via ffmpeg pipe or mpv's --audio-device stdout) and fans it out to all connected HTTP listeners simultaneously.
Startup Output
On tuitube serve, print the resolved URLs so the user can just copy-paste:
tuitube is broadcasting on:
→ http://192.168.1.42:8080/stream (LAN)
→ http://localhost:8080/stream (this machine)
Open in any browser, VLC, or mpv to listen.
LAN IP is auto-detected via net.InterfaceAddrs() — no config needed for basic use.
ICY Metadata (Now Playing)
Use the Icecast ICY metadata protocol so the current track title shows up in VLC, mpv, and browser media sessions automatically:
icy-name: tuitube
icy-metaint: 8192
Every 8192 bytes, inject a metadata frame with the current track title + artist. This means listeners see "Now Playing: Track Name" in their player with zero extra work.
Now Playing Page
GET / serves a minimal HTML page (no JS framework, pure HTML):
- Current track title + artist
- Album art (if available)
- The stream URL to copy
- Auto-refreshes on track change via SSE or a simple meta-refresh
Implementation Notes
- Audio pipe:
ffmpeg -i pipe:0 -f mp3 - reading from mpv's stdout, or use mpv's --audio-device=pcm + ffmpeg stdin
- Fan-out: a broadcaster goroutine reads mp3 frames and writes to all connected
http.ResponseWriter clients via channels
- mp3 frame boundaries: only start new listeners on a clean mp3 frame boundary to avoid glitches (see
mp3frame pattern from cliamp-server)
- LAN ACL:
--lan flag required to accept non-loopback connections (safe default = localhost only)
- mDNS announce (optional stretch): register
tuitube.local via mDNS so devices can use http://tuitube.local:8080/stream instead of IP
CLI
tuitube serve [--port 8080] [--lan] [--no-mdns]
| Flag |
Default |
Description |
--port |
8080 |
Port to listen on |
--lan |
false |
Accept connections from LAN (non-loopback) |
--no-mdns |
false |
Disable mDNS tuitube.local announcement |
Dependencies
net/http — stdlib, already present
ffmpeg — already a soft dependency via yt-dlp workflows; document as required for broadcast mode
- No new Go deps for core broadcast; optional
hashicorp/mdns for mDNS announce
Non-Goals (v1)
- Playback control from the browser (skip, pause) — that's a separate web UI feature
- Authentication / passwords
- External internet exposure (that's the user's job via Tailscale etc.)
- HLS / DASH streaming
References
Overview
Add a
tuitube serve(ortuitube broadcast) command that streams the currently playing audio as a continuous HTTP audio stream — like a personal internet radio station. Any device on the LAN (phone, laptop, TV browser) can tune in by opening a single URL. No frontend, no app, no playback controls required.How It Works
mpv continues playing normally in the TUI. The broadcast layer taps into the audio output (via ffmpeg pipe or mpv's
--audio-devicestdout) and fans it out to all connected HTTP listeners simultaneously.Startup Output
On
tuitube serve, print the resolved URLs so the user can just copy-paste:LAN IP is auto-detected via
net.InterfaceAddrs()— no config needed for basic use.ICY Metadata (Now Playing)
Use the Icecast ICY metadata protocol so the current track title shows up in VLC, mpv, and browser media sessions automatically:
Every 8192 bytes, inject a metadata frame with the current track title + artist. This means listeners see "Now Playing: Track Name" in their player with zero extra work.
Now Playing Page
GET /serves a minimal HTML page (no JS framework, pure HTML):Implementation Notes
ffmpeg -i pipe:0 -f mp3 -reading from mpv's stdout, or use mpv's--audio-device=pcm+ ffmpeg stdinhttp.ResponseWriterclients via channelsmp3framepattern from cliamp-server)--lanflag required to accept non-loopback connections (safe default = localhost only)tuitube.localvia mDNS so devices can usehttp://tuitube.local:8080/streaminstead of IPCLI
--port8080--lanfalse--no-mdnsfalsetuitube.localannouncementDependencies
net/http— stdlib, already presentffmpeg— already a soft dependency via yt-dlp workflows; document as required for broadcast modehashicorp/mdnsfor mDNS announceNon-Goals (v1)
References
icy,mp3frame,broadcast,transcodepackages worth studying