The native audio data layer for Apple MLX: fast file decode and encode directly to and from mlx.core.array, with one unified API across macOS and Linux.
- Zero-Copy MLX Pipeline: Direct decode and encode via DLPack capsules (
mx.from_dlpack) and the Python buffer protocol. - Zero Torch, Zero NumPy: MLX is the sole required runtime dependency. No heavyweight PyTorch or NumPy runtime overhead.
- Apple Silicon Optimized: Native macOS backend powered by Apple AudioToolbox loads a WAV 6.8x faster than librosa and saves one 1.5x faster than SoundFile on an M4 Max (measurements).
- Decoupled Architecture: Upgrading
mlxnever requires rebuildingmlx-audio-io. One build works with any installed MLX (0.32.0+). - Concurrent Writer Engine: Staged buffer preparation (
prepare_save/save_prepared) releases the Python GIL and avoids MLX contention across background export workers.
pip install mlx-audio-ioPrebuilt wheels are published for macOS 14 or later on Apple Silicon (Python 3.10 to 3.14), so nothing is compiled there. Other platforms build from source during install; see the Installation Guide for the compiler and Linux packages that needs.
mlx-audio-io requires:
- macOS:
mlx>=0.32.0(Apple Silicon) - Linux:
mlx[cpu]>=0.32.0
Because decoded audio enters MLX via DLPack and save operations consume arrays through the buffer protocol, mlx-audio-io does not link against libmlx.dylib. Upgrading MLX versions in your environment does not require rebuilding mlx-audio-io.
For Linux build dependencies, source checkout, and troubleshooting, see the Installation Guide.
import mlx_audio_io as audio_io
# Decode native format directly into an mx.array: [frames, channels]
audio, sr = audio_io.load("speech.wav")
# Load with automatic high-quality resampling and mono fold-down
audio_16k, sr_16k = audio_io.load("speech.wav", sr=16000, mono=True)# Save float32 or pcm16 WAV
audio_io.save("out.wav", audio, sr)
audio_io.save("out_pcm16.wav", audio, sr, encoding="pcm16")
# Save compressed formats (MP3, AAC/M4A, FLAC)
audio_io.save("out.mp3", audio, sr, bitrate="192k")
audio_io.save("out.m4a", audio, sr, bitrate="256k")
audio_io.save("out.flac", audio, sr)Stream long audio files in fixed-duration chunks without decoding the whole file into RAM:
for chunk, chunk_sr in audio_io.stream("long_recording.wav", chunk_duration=2.0):
# chunk is an mx.array of shape [frames, channels]
process(chunk)For multi-stem export pipelines (e.g. Demucs, audio separators), stage the buffer once on the producer thread and delegate writing to background file workers:
from concurrent.futures import ThreadPoolExecutor
import mlx_audio_io as audio_io
# Producer: stage read-only view and evaluate lazy MLX graph
prepared = audio_io.prepare_save(stem, layout="channels_first")
# Worker threads: encode and write without holding the Python GIL
with ThreadPoolExecutor(max_workers=4) as workers:
workers.submit(audio_io.save_prepared, "vocals.wav", prepared, 44100, encoding="pcm16")Read container metadata in microseconds without reading or decoding sample frames:
meta = audio_io.info("speech.wav")
print(meta.duration, meta.sample_rate, meta.channels, meta.subtype)| Function / Class | Description | Documentation |
|---|---|---|
load |
Decode audio file to mx.array with optional resampling, slicing, and mono mix |
Details |
save |
Write mx.array or buffer-compatible array to WAV, MP3, M4A, FLAC, AIFF |
Details |
prepare_save |
Stage evaluated buffer view on producer for concurrent export threads | Details |
save_prepared |
File encoder for background worker threads (releases the GIL while encoding) | Details |
PreparedAudio |
Read-only audio buffer wrapper preserving strides and memory layout | Details |
stream |
Generator yielding fixed-frame or fixed-duration mx.array chunks |
Details |
info |
Fast header inspection returning AudioInfo (frames, duration, channels) |
Details |
batch_load |
Multi-threaded multi-file audio decoding into a list of mx.array |
Details |
supports_soxr |
Check whether high-quality libsoxr resampling support is enabled |
Details |
For complete signatures and parameter contracts, see the Full API Reference.
| Capability | macOS Backend | Linux Backend |
|---|---|---|
| Engine | Apple AudioToolbox | Native C++ WAV/MP3 + libav (FFmpeg) |
| Supported Formats | WAV, MP3, M4A/AAC, FLAC, AIFF, CAF | WAV, MP3, FLAC, M4A/AAC, AIFF, CAF |
| Encodings | float32, pcm16, alac (lossless M4A) |
float32, pcm16, alac (lossless M4A) |
| Resampling | AudioToolbox (best) / libsoxr (soxr_vhq) |
Native linear / libav / libsoxr |
| Streaming | Full chunked streaming across all formats | Full chunked streaming across all formats |
Measured on Apple M4 Max (macOS 27.0) on a 194.8-second stereo 44.1 kHz PCM16 WAV track (median p50 latency):
| Operation | macOS M4 Max | vs librosa / soundfile | vs torchaudio |
|---|---|---|---|
| Full WAV Load | 3.74 ms | 6.8x faster than librosa | 9.2x faster |
| WAV Partial Read (1s) | 0.05 ms | 3.4x faster than librosa | 708x faster |
| MP3 Load (native SR) | 37.88 ms | 1.1x faster than librosa | 1.9x faster |
| WAV Save (Float32) | 14.07 ms | 1.5x faster than SoundFile | 1.5x faster |
Save Prepared (save_prepared) |
13.77 ms | 1.5x faster than SoundFile | 1.6x faster |
Load + Resample (16 kHz, fastest) |
10.76 ms | 5.6x faster than librosa | 5.0x faster |
Load + Resample (16 kHz, best) |
33.17 ms | 1.8x faster than librosa | 1.6x faster |
For complete benchmarking methodology, Linux arm64/x86_64 numbers, and tail latency profiles, see Benchmarking & Performance.
- 📖 API Reference — Comprehensive signatures, parameters, and return types for all functions.
- ⚡ Benchmarking & Performance — Detailed latency tables, methodology, and cross-framework comparisons.
- 🛠️ Installation, Builds & Troubleshooting — Linux libav dependencies, wheel repair, Docker workflows, and diagnostic tools.
MIT