Empty Orchestra
2026A karaoke maker that strips vocals from any song, or an entire YouTube playlist, and hands back a studio-quality instrumental.
The problem
Karaoke means "empty orchestra" in Japanese, and that emptiness is exactly what's hard to find. Instrumental versions exist for chart hits, but good luck finding one for a Nepali classic or an album deep cut. I wanted a tool where any song goes in and a clean instrumental comes out, whether the source is a local file or a YouTube link.
The bar was: upload a song or paste a YouTube URL (playlists included), wait a few minutes, download both the instrumental and the original in high-quality formats.
Architecture
The app is a pnpm workspace with two packages: an Express + TypeScript API and a Vite + React client styled with Tailwind v4 and shadcn components on Base UI.
The interesting part is the processing pipeline, which runs entirely as child processes: yt-dlp fetches audio from YouTube, Demucs (Meta's htdemucs model, running in a project-local Python venv with two-stems mode) separates vocals from everything else, and ffmpeg encodes the result to AAC m4a or 320k MP3.
Jobs flow through an in-memory FIFO queue with concurrency 1, because vocal separation is memory-hungry and running two Demucs jobs at once would grind a laptop to a halt. Job state persists to a JSON file so a restart doesn't lose history, and the frontend polls every 1.5 seconds for progress.
Decisions and trade-offs
Child processes over Python bindings: keeping yt-dlp, Demucs, and ffmpeg as separate executables means each tool can be upgraded independently, crashes stay isolated from the API server, and progress can be parsed off stderr in real time.
Two-stems mode over full four-stem separation: karaoke only needs vocals-vs-everything, and two-stems roughly halves processing time.
Polling over WebSockets: with concurrency 1 and jobs measured in minutes, a 1.5-second poll is indistinguishable from push updates, and removes a whole class of connection-management code.
The signature UI detail: job progress renders as a karaoke lyric line that fills with yellow as the pipeline advances, using background-clip: text. The progress bar is the product.
Gotchas worth knowing
yt-dlp goes stale fast. YouTube changes its internals constantly, and most "YouTube import is broken" reports trace back to an outdated yt-dlp binary rather than a bug in the app.
Demucs model downloads happen on first run, so the Docker image (node:20-slim + a Python venv + ffmpeg) pre-warms the model to keep first-job latency sane in deployment.
Outcome
Open source under MIT, verified end-to-end with both upload and YouTube import producing valid stereo instrumentals. Local runs never need Docker. Clone, install, and sing.