djprep
I DJ on the side and got tired of paying for Mixed In Key. I also wanted an excuse to write something real in Rust — I'd been curious about it and wanted to see if the ownership model and performance story held up outside of toy examples. So I built an open-source alternative: a CLI for BPM and key detection, stem separation, and Rekordbox XML export.
Rust was the right call for this. The FFI boundary to ONNX Runtime is clean, and Rust's ownership model made it much easier to reason about memory when you're passing audio buffers between CPU and GPU pipelines. The CLI is fast and predictable in a way that would've taken more effort in Python.
What I built
Detection pipeline. BPM, key, and stem separation in one CLI. Outputs Rekordbox-compatible XML so you can drop results straight into your library.
HTDemucs via ONNX. Integrated the Demucs model for stem separation, with automatic execution provider selection across CoreML (Mac), CUDA (NVIDIA), and DirectML (Windows). One binary, multiple backends.
Bounded concurrency. GPU inference and CPU work (rayon) run in isolation. Batch processing without memory exhaustion — the CPU pipeline doesn't block the GPU; the GPU doesn't starve the CPU.
What I learned
Execution providers matter. CoreML on Mac, CUDA on Linux, DirectML on Windows — picking the right one at runtime saves users from configuration hell. Auto-detection was worth the upfront work.
DJ tooling is surprisingly closed. Rekordbox XML is well-documented; the rest of the ecosystem is not. Building an open alternative means reverse-engineering formats and workflows that most people assume are locked in.
Built with