ytstr: Intelligent Auto-DJ Streamer
Inspiration
The inspiration for ytstr came from a frustration with modern music streaming. While algorithmic recommendations are great, the actual playback experience is often disjointed. Playlists feel like discrete tracks separated by awkward silences rather than a cohesive journey. We wanted to recreate the magic of a live DJ set—where the energy flows seamlessly from one track to the next—but apply it automatically to any YouTube playlist, directly from the terminal. The goal was to build a tool that didn't just play music, but mixed it with broadcast-grade intelligence.
What it does
ytstr is a terminal-native YouTube playlist streamer powered by a psychoacoustic DecisionEngine. Instead of just playing tracks sequentially, it analyzes the spectral energy (RMS, Bass, Treble, Variance) of the outgoing and incoming tracks in real-time. Based on this analysis, the DecisionEngine automatically selects one of 8 specialized DJ transition styles—such as Fade, Blend, Rise, Cut In, Bass Swap, Filter Wash, Melt, or a vinyl-style Tape Stop. It runs seamlessly in the background with a minimal TUI, intercepts global hardware media keys for control, and manages its own memory to provide an infinite, gapless listening experience.
How we built it
We built ytstr entirely in Python, leveraging a multi-threaded daemon architecture.
- Audio Fetching: We use
yt-dlpto asynchronously pull audio streams from YouTube. - Audio Processing:
pydubhandles the heavy lifting for DSP (Digital Signal Processing). We implemented complex filtering (high-pass/low-pass) and volume envelopes to create the 8 transition styles. - Playback & IPC: We integrated
mpvvia IPC (Inter-Process Communication) sockets. This allowsytstrto command the player precisely without blocking the main thread. - Memory Management: To achieve true gapless playback, we stage processed tracks in the
/dev/shmRAM disk. We built a custom backpressure and garbage collection system to ensure the footprint remains under ~260MB, regardless of playlist size.
Challenges we ran into
- Memory Leaks & SHM Exhaustion: Initially, baking tracks into
/dev/shmcaused unbounded RAM usage, quickly consuming gigabytes of memory and crashing the system. Implementing the backpressure queue (limiting baked tracks to 2-3 ahead) and active garbage collection was a major hurdle. - Headless Terminal Crashes: When trying to run
ytstras a background daemon, thetermioslibrary crashed because there was no active TTY. We had to carefully architect the keyboard listener to gracefully degrade when running headless. - Orphaned Processes: Managing
mpvsubprocesses across thread boundaries led to zombie processes persisting after the user quit the app. Transitioning fromatexitto strict UNIXSIGTERM/SIGINTsignal handlers solved this.
Accomplishments that we're proud of
- The DecisionEngine: Successfully translating psychoacoustic theory (how humans perceive audio energy) into code. The engine genuinely makes smart decisions—choosing a "Rise" for high-energy drops or a "Bass Swap" to prevent muddy low-end clashes.
- 70% RAM Reduction: Optimizing the V2 architecture to bound RAM disk usage, making
ytstrstable enough to run indefinitely on low-resource machines. - Terminal Elegance: Creating a tool that is immensely complex under the hood but requires zero configuration to use. Just pass a URL and enjoy the mix.
What we learned
- Advanced IPC: We gained deep experience in controlling subprocesses (
mpv) via JSON IPC sockets, learning how to synchronize state between an asynchronous player and our Python controller. - Signal Processing in Python: We pushed
pydubto its limits, learning how to efficiently manipulate raw audio buffers, apply equal-power crossfade curves, and calculate RMS energy windows. - System Resource Management: We learned the critical importance of defensive programming when dealing with system-level resources like
/dev/shmand process IDs.
What's next for ytstr
- Harmonic Mixing: The next big step is implementing BPM and Key detection. This will allow the DecisionEngine to not just transition tracks, but actively beatmatch and harmonize them for true club-standard mixing.
- Systemd Integration: Providing a seamless setup script to install
ytstras a persistent background daemon on Linux systems. - Advanced Caching: Implementing an optional disk-based cache for frequently played playlists to save bandwidth and reduce pre-compute times.
Log in or sign up for Devpost to join the conversation.