DIY Home KTV System: Karaoke Eternal + Cloudflare Tunnel + Two-Stage Loudness Normalization + Custom Web Mixer
Turn your living room into a private karaoke lounge!
This article documents how I built a self-hosted, private home KTV (karaoke) setup using the open-source Karaoke Eternal as the core playback engine. The stack is augmented with Cloudflare Tunnel (Zero Trust) for secure remote smartphone song queueing, a two-stage ffmpeg loudnorm audio pipeline, and a custom-built Node.js downloader portal with a Web Audio API mixer. The result: friends and family can queue songs from their phones via Google OAuth, the living room TV streams 4K/1080p video over the local network with zero buffering, and not a single router inbound port is exposed to the public internet.
1. System Architecture: Split-Traffic Zero Trust¶
Traditional home media setups face a classic dilemma: high-bitrate video streaming demands local network bandwidth, whereas letting guests queue tracks on their phones requires exposing an interface to the outside world.
I solved this using Split-Traffic + Zero Trust Architecture:
- Big Screen Playback: The living room TV or tablet connects directly to the server's local subnet IP (http://192.168.X.XXX:8080/player). High-bitrate video remains 100% on the local LAN, completely bypassing residential outbound bandwidth bottlenecks.
- Mobile Song Queue: Friends connect via an outbound Cloudflare Tunnel protected by Cloudflare Access (Google OAuth allowlist). No DDNS, no router port forwarding, and zero public port exposure.
- Custom Downloader Portal: A lightweight Node.js/Express service (:8082) styled in neon glassmorphism that parses YouTube URLs and keywords, automatically sanitizing titles and queuing downloads.
┌──────────────── Host Machine (Linux Home Server: 192.168.X.XXX) ──────────────┐
│ │
│ [Living Room TV / Tablet Player] │
│ http://192.168.X.XXX:8080/player │
│ │ (Direct LAN connection) │
│ ▼ │
│ ┌───────────────┐ Docker Bind Mount ┌──────────────────────────────┐ │
│ │karaoke-eternal│ ◀──────────────────── │ Host ./media/library (RO) │ │
│ └───────┬───────┘ └──────────────▲───────────────┘ │
│ ▲ (Docker Network) │ │
│ │ (ingest.sh transcoding) │
│ ┌───────┴───────┐ Drop into inbox ┌──────┴───────────────┐ │
│ │ktv-downloader │ ───────────────────────────▶│ Host ./media/inbox │ │
│ │ (:8082 Portal)│ └──────────────────────┘ │
│ └───────▲───────┘ │
│ │ │
│ ┌───────┴───────┐ │
│ │ cloudflared │ ───Outbound Tunnel───▶ Cloudflare Zero Trust (OAuth Gate) │
│ └───────────────┘ ▲ │
└────────────────────────────────────────────────────────────┼──────────────────┘
│
[Friends' Smartphones]
https://ktv.yourdomain.com
2. Core Technology Stack¶
| Layer | Technology | Problem Solved |
|---|---|---|
| Container Orchestration | Docker Compose | Service decoupling, environmental parity, and reproducible deployments. |
| KTV Core | radrootllc/karaoke-eternal |
SQLite media library, room concurrency, real-time queues, and Web player. |
| Edge Security | Cloudflare Tunnel + Access | Zero inbound NAT, automated SSL termination, and Google OAuth authorization. |
| Audio Processing | ffmpeg (2-pass loudnorm) |
Eliminates volume disparity across disparate web sources (EBU R128). |
| Ingest Portal | Node.js (Express) + yt-dlp |
Automated title cleaning, background downloading, and queue polling. |
| Frontend Audio Mixer | Web Audio API (StereoPanner) |
Real-time vocal channel panning, pitch adjustment, and playback rate control. |
3. Architectural Decision: Should Media Files Live Inside Docker?¶
During early planning, I considered whether to download video files directly inside the Docker container to keep the host operating system pristine.
The answer is an emphatic NO. That is a textbook architectural anti-pattern:
1. Container Lifecycle Hazards: Containers are disposable cattle. Running docker compose down or rebuilding an image would instantly vaporize the entire multi-gigabyte song catalog.
2. Overlay2 Performance Penalties: The Docker storage driver utilizes a Copy-on-Write (CoW) layer. Handling continuous streaming and disk writes for dozens of gigabytes of heavy video files incurs significant I/O overhead and quickly exhausts /var/lib/docker.
3. The Clean Pattern: Manage media storage on the host filesystem + Read-Only Bind Mount into Docker:
yaml
volumes:
- ./config:/config
- ./media/library:/mnt/karaoke:ro
4. Automated Ingest & Audio Normalization Pipeline¶
Different videos on YouTube feature radically inconsistent volume levels. One track requires cranking the amplifier; the next track blasts everyone's eardrums with distorted peaks.
To fix this, I engineered an automated ingest pipeline script (scripts/ingest.sh) triggered whenever a new track lands in media/inbox:
4.1 Two-Pass EBU R128 Loudness Normalization¶
Using ffmpeg's loudnorm filter in dual-pass mode:
- Pass 1 (Analysis): Scans the raw audio stream to calculate Integrated Loudness (I), True Peak (TP), and Loudness Range (LRA).
- Pass 2 (Linear Normalization): Applies measured offsets to bring audio to a target loudness of I=-16 LUFS and TP=-1.5 dBFS. This achieves smooth acoustic balance without clipping or dynamic squash.
4.2 Automated Database Media Rescanning¶
Historically, adding files required manually opening the Karaoke Eternal admin dashboard and clicking "Scan Media." I automated this by having the script invoke the internal CLI command directly within the container upon transcode completion, instantly refreshing the library.
5. Custom Downloader & Song Selection Portal (ktv-downloader)¶
Karaoke Eternal enforces a strict filename convention: Artist - Title.mp4 (with exact spaces surrounding the hyphen). Attempting to import raw YouTube video titles (e.g., Jay Chou【Sunny Day】Official Music Video 4K) results in immediate parsing failures.
I built a dedicated helper microservice in Node.js/Express running on :8082:
5.1 Smart Regex Title Cleaner¶
Applies structured regular expressions to strip out extraneous branding, bracketed tags ([Official MV], (1080p)), audio watermarks, and resolution metadata, cleanly isolating Artist and Title.
5.2 Neon Glassmorphism UI¶
- Quick-Picks: Dedicated tag chips for trending Mandarin and Taiwanese pop stars (e.g., Jay Chou, Accusefive, Mayday) converting clicks directly into
ytsearch1:queries. - Live Preview Input: Displays parsed destination filenames in real-time, preventing tracks from dropping into the
failed/directory. - Asynchronous Telemetry: Real-time polling showing pending downloads, active transcodes, and library size.
6. Real-World Troubleshooting & Deep Pitfalls¶
Several undocumented edge cases surfaced during development:
Pitfall 1: Empty Song Library & High CPU Loop (ELOOP)¶
- Symptom: Files existed in
media/library, but the web dashboard remained persistently empty while the container CPU spiked to 100%, spamming:
ELOOP: too many symbolic links encountered, stat '/proc/...' - Root Cause Analysis: During initial database seeding, Karaoke Eternal set the default
pathstable in SQLite to root (/). Consequently, the media scanner attempted to recursively traverse the host's virtual/procand/sysfilesystems, spiraling into an infinite symlink loop. - Resolution: Directly updated the SQLite
pathstable via CLI, correcting the scan root to the mounted Docker path/mnt/karaoke.
Pitfall 2: Why Left/Right Channel Vocal Removal Failed on Modern MV Tracks¶
- Technical Analysis: Many assume all music videos feature split vocal tracks (e.g., instrumentals on the left, vocals on the right). However, 90%+ of modern official music videos on streaming platforms are true stereo mixes where vocals are centered across both channels. A simple
StereoPannercannot isolate vocals in centered stereo mixes. - Countermeasure:
- For authentic karaoke VCD/DVD rips: Left channel is pure instrumental, right channel is vocals—the Web Audio API panner works flawlessly.
- For standard stereo pop releases: Future iterations can integrate AI source separation models (such as Demucs or Spleeter) directly into
ingest.shduring transcode, splitting tracks into dedicated instrumental and vocal stems.
7. Results & Takeaways: An Engineer's Playground¶
After wrestling with Docker volume permissions, SQLite database paths, and two-pass loudness normalization, the system delivered a remarkably polished home entertainment experience:
- Zero-Trust Connectivity & Local Performance: Guests comfortably browse and queue songs from their smartphones via Cloudflare Tunnel, while video traffic stays 100% local on the gigabit LAN with instant response times.
- Studio Audio Consistency: Dual-pass
loudnormcompletely eliminated the volume roulette common to user-generated web rips. - The Joy of Full-Stack Architectural Ownership: From debugging kernel-level symlink loops in SQLite to engineering automated ingest pipelines, the project was a fantastic end-to-end exercise in distributed media streaming.
Disclaimer & Perspective:
At the end of the day, this was a project born out of pure engineering curiosity and technical amusement. Playing with Docker, Cloudflare Tunnels, and ffmpeg pipelines is deeply rewarding. But when you really want to sing your heart out with a massive crowd, nothing beats booking a room at an authentic karaoke lounge!
Treating your own living room as an experimental media infrastructure lab—and enjoying the thrill of complete architectural control—is where the real fun lies!
Comments
Loading comments…
Leave a Comment