Split any song into its individual stems — vocals, drums, bass, and other instruments — directly on your Mac.
demucs-mlx is a fast, native Apple Silicon port of Meta's Demucs music source separation model, built on MLX. No PyTorch required.
- ~73x realtime on Apple Silicon — 2.6x faster than Demucs with PyTorch MPS
- Bit-exact parity with upstream Demucs stems (within floating-point tolerance)
- Custom fused Metal kernels (GroupNorm+GELU, GroupNorm+GLU, OLA)
- Metal-free fallbacks for non-Apple platforms (Linux)
- No PyTorch required at inference time
- Automatic resampling — input files at any sample rate are resampled to the model rate
- Audio I/O via mlx-audio-io
- STFT/iSTFT via mlx-spectro
- Python >= 3.10
- macOS with Apple Silicon (recommended) or Linux with MLX
pip install demucs-mlxOn first run, demucs-mlx will automatically download and convert the PyTorch weights to MLX format. This requires the convert extra:
pip install 'demucs-mlx[convert]'Once weights are cached in ~/.cache/demucs-mlx, the convert extra is no longer needed.
demucs-mlx /path/to/audio.wavOptions:
-n, --name Model name (default: htdemucs)
-o, --out Output directory (default: separated)
--shifts Number of random shifts (default: 1)
--seed Optional RNG seed for reproducible shifts (default: none)
--overlap Overlap ratio (default: 0.25)
-b, --batch-size Batch size (default: 8)
--write-workers Concurrent writer threads (default: 1)
--list-models List available models
-v, --verbose Verbose logging
from demucs_mlx import Separator
separator = Separator()
origin, stems = separator.separate_audio_file("song.wav")
# stems is a dict: {"drums": array, "bass": array, "other": array, "vocals": array}
for name, audio in stems.items():
print(f"{name}: {audio.shape}")To keep outputs as MLX arrays (avoids GPU-to-CPU copy):
origin, stems = separator.separate_audio_file("song.wav", return_mx=True)For reproducible shift sampling (while keeping shifts=1 behavior), pass a seed:
separator = Separator(model="htdemucs", shifts=1, seed=0)
origin, stems = separator.separate_audio_file("song.wav")resample_mx()now uses directmac.resample()instead of writing/reading a temp file — eliminates an unnecessary MLX→numpy→disk→MLX round-trip.- Bumped minimum
mlx-audio-ioto>=1.3.9(auto-selects best resampling quality).
- Audio loading now stays as native MLX arrays end-to-end (no numpy round-trip).
- Automatic resampling via
mlx-audio-io— input files no longer need to match the model sample rate. - Uses
soxr_vhqresampling quality when available, with automatic fallback. - Bumped minimum dependencies:
mlx>=0.31.0,mlx-audio-io>=1.3.8,mlx-spectro>=0.2.4.
- Fixed shifted-inference
TensorChunkpropagation so chunk length/offset is handled correctly in all paths. - Added optional deterministic RNG control (
seed) for Python API and CLI. - Default behavior is unchanged:
shifts=1remains stochastic unlessseedis provided.
Benchmarked on a 3:15 stereo track (44.1 kHz, 16-bit) using htdemucs with default settings:
| Package | Backend | Time | Speedup |
|---|---|---|---|
demucs 4.0.1 |
PyTorch (CPU) | 52.3s | 0.1x |
demucs 4.0.1 |
PyTorch (MPS) | 6.9s | 1x |
demucs-mlx 1.1.0 |
MLX + Metal | 2.7s | 2.6x |
Apple M4 Max, 128 GB. All runs use htdemucs with default settings and a single warm-up pass before timing.
| Model | Sources | Description |
|---|---|---|
htdemucs |
4 | Hybrid Transformer Demucs (default) |
htdemucs_ft |
4 | Fine-tuned HTDemucs |
htdemucs_6s |
6 | 6-source (adds piano, guitar) |
hdemucs_mmi |
4 | Hybrid Demucs MMI |
mdx |
4 | Music Demixing model |
mdx_extra |
4 | MDX with extra training |
Pre-converted MLX weights are cached under ~/.cache/demucs-mlx. Delete to force re-conversion.
- API reference:
docs/api.md - Development workflow:
docs/development.md - Platform notes:
docs/platform.md
MIT. Based on Demucs by Meta Research. See LICENSE for details.