htdemucs-coreml / README.md
dexxdean's picture
Initial release: HTDemucs to Core ML conversion (FP32 + FP16)
8b4d481 verified
|
Raw History Blame Contribute Delete
4.98 kB
---
license: mit
library_name: coreml
tags:
- audio
- music-source-separation
- stem-separation
- demucs
- htdemucs
- coreml
- apple-silicon
- swift
- macos
- ios
pipeline_tag: audio-to-audio
---
# HTDemucs → Core ML
Convert Meta's [Hybrid Transformer Demucs](https://github.com/facebookresearch/demucs) (HTDemucs) into a Core ML `.mlpackage` you can drop into a macOS or iOS app and run with `MLModel`.
The hard part of converting HTDemucs to Core ML is not the network itself — it is the STFT/ISTFT and the multi-head attention around it. This repo contains a **single-file converter** (`convert.py`, ~600 LoC) that solves the three blockers you hit otherwise:
1. Core ML doesn't support `complex64` → real-valued STFT/ISTFT.
2. `coremltools` can't trace `nn.MultiheadAttention` → manual decomposition.
3. Core ML's 1D `scatter_add` is fragile → pre-computed OLA index buffer.
The result is a **stand-alone `.mlpackage`** that takes raw stereo audio and outputs four stems (vocals, drums, bass, other) at 44.1 kHz.
## Why another conversion?
There is one prior public Core ML conversion of HTDemucs by [john-rocky/CoreML-Models](https://github.com/john-rocky/CoreML-Models) at 7.8 s segments / 80 MB. This repo offers:
- **Longer segments (10 s by default)** → fewer overlap-add boundaries on long files.
- **CLI flags** for segment length, FP16 quantization, compute-unit selection.
- **Source order** reordered to `[vocals, drums, bass, other]` (DJ/UI convention).
- **Documented workarounds** so you can reproduce or adapt the pipeline for other audio models (Spleeter, OpenUnmix, MDX-Net).
## Quick start
```bash
git clone https://github.com/dexxdean/htdemucs-coreml
cd htdemucs-coreml
python3 -m venv venv && source venv/bin/activate
pip install -r requirements.txt
# default: 10 s segments, FP32, ~400 MB
python convert.py
# half size, ~200 MB, slight numerical drift but inaudible in practice
python convert.py --fp16
# shorter segments if you want lower latency / smaller buffers
python convert.py --segment 7
```
The output is `HTDemucs_CoreML.mlpackage` (or `HTDemucs_CoreML_FP16.mlpackage`).
## Usage in Swift
```swift
import CoreML
import AVFoundation
// 1. Load the model.
let url = Bundle.main.url(forResource: "HTDemucs_CoreML", withExtension: "mlpackage")!
let config = MLModelConfiguration()
config.computeUnits = .cpuAndGPU // see "Compute units" below
let model = try MLModel(contentsOf: url, configuration: config)
// 2. Feed a (1, 2, 441000) Float32 MLMultiArray named "audio".
// Output is a (1, 4, 2, 441000) Float32 array named "sources",
// in the order [vocals, drums, bass, other].
```
A more complete example with chunking, overlap-add, and `AVAudioEngine` playback is in [`examples/swift/StemSeparator.swift`](examples/swift/StemSeparator.swift).
## Model I/O
| | |
|---|---|
| Input name | `audio` |
| Input shape | `(1, 2, segment_samples)` Float32 |
| Output name | `sources` |
| Output shape | `(1, 4, 2, segment_samples)` Float32 |
| Output order | `vocals, drums, bass, other` |
| Sample rate | 44 100 Hz, stereo |
| Default segment | 441 000 samples (10 s) |
| Min. deployment | macOS 14 / iOS 17 |
## Compute units
HTDemucs is **not stable on the Apple Neural Engine**. Use `.cpuAndGPU` (the default baked into the model). Forcing `.all` or `.cpuAndNeuralEngine` may produce silent garbage on some shapes — the validation step in `convert.py` will warn if numerical drift is large.
## File sizes
| Variant | Size | Notes |
|---|---|---|
| FP32, 10 s | ~400 MB | Default, full reference quality. |
| FP16, 10 s | ~200 MB | Inaudible quality difference for music separation. |
| FP32, 7.8 s | ~310 MB | Closer to john-rocky's segment length. |
## How it works
See [`CONVERSION_NOTES.md`](CONVERSION_NOTES.md) for the technical deep-dive on the three workarounds (real STFT, manual MHA, OLA scatter).
## License & attribution
This repo is **MIT-licensed** — see [`LICENSE`](LICENSE).
The converted model derives from [facebookresearch/demucs](https://github.com/facebookresearch/demucs) © Meta Platforms, Inc., MIT-licensed. The pre-trained HTDemucs weights are downloaded by the `demucs` Python package at conversion time from Meta's official release. **You must comply with Demucs' MIT license when redistributing the resulting `.mlpackage`** — keep the attribution in `ATTRIBUTION.md` alongside the model and in your app's about/legal screen.
This project is **not affiliated with Apple, Meta, or Demucs**. The package name `HTDemucs_CoreML.mlpackage` was chosen to avoid any confusion with Apple-internal model names (e.g., `MusicSourceSeparation`).
## Citation
If you use this in academic work, please cite the original Demucs papers:
```bibtex
@inproceedings{rouard2023hybrid,
title={Hybrid Transformers for Music Source Separation},
author={Rouard, Simon and Massa, Francisco and D{\'e}fossez, Alexandre},
booktitle={ICASSP 2023},
year={2023}
}
```