🎵 sound_rs
sound_rs is a fast, Rust-powered audio playback library for Python that I built and maintain — decoding with symphonia, output through cpal, so the same code runs on macOS, Windows and Linux.
🚀 Features
- Formats: WAV, MP3, FLAC, OGG/Vorbis, M4A, AAC — any bit depth, including 24-bit
- NumPy arrays: play 1D mono
(samples,)or 2D(channels, samples)float32 arrays - Decode to array:
load(path) -> (ndarray, sample_rate), shape(frames, channels) - Gapless (MP3, OGG, AAC/MP4): encoder delay and padding are trimmed, so decoded length matches the original. MP4 priming comes from the edit list; at most one trailing frame can remain, because the container does not declare it
- Fast metadata:
get_audio_inforeads the container header; for AAC, whose container carries no channel layout, one packet is decoded to learn it - Resampling: linear interpolation to the device rate, channel folding to the device layout
- Device-native output: the stream is opened in whatever sample format the device wants (f32, i16, u16, ...)
- Non-blocking for others: playback blocks the calling thread but releases the GIL, so other Python threads keep running
- Tone generator:
play_sine_wave(440, 2.0, 44100)
🧠 Installation
pip install sound_rs
💻 Usage
Playback
import sound_rs
sound_rs.play_audio("sound.wav")
sound_rs.play_audio("sound.mp3")
sound_rs.play_audio("sound.flac")
sound_rs.play_audio("sound.m4a")
Inspect a file (no decoding)
sample_rate, channels, duration = sound_rs.get_audio_info("sound.mp3")
sound_rs.is_supported_format("sound.mp3") # probes the header, does not decode
Decode to a NumPy array
import sound_rs
audio, rate = sound_rs.load("music.flac") # float32, shape (frames, channels)
From a NumPy array
import numpy as np
import sound_rs
rate = 44100
t = np.linspace(0, 2.0, rate * 2, endpoint=False, dtype=np.float32)
sound_rs.play_array(np.sin(2 * np.pi * 440 * t), rate) # mono, 1D
sound_rs.play_array(np.stack([left, right]), rate) # 2D, channels first
Background playback
import threading
threading.Thread(target=sound_rs.play_audio, args=("long.mp3",)).start()
Tone generator
sound_rs.play_sine_wave(440.0, 1.0, 44100) # frequency, duration, sample rate
🧩 Benchmark
play_audio is synchronous, so its wall-clock time is dominated by the track's
own duration. The interesting numbers are metadata, decode and
overhead (wall clock − audio duration) — and decode is only worth measuring
if the output is correct, so every run also compares PCM against libsndfile.
python examples/benchmark.py # generated 3s tone: decode + playback
python examples/benchmark.py --compare # + sounddevice / soundfile
python examples/benchmark.py --files a.mp3 b.flac # decode table for real files
Hardware and setup I measured on: Apple M5 Pro, macOS 26.6.2, Python 3.14.7,
release build (lto = "fat", opt-level = 3), 60 s of 44.1 kHz stereo,
median and p95 of 7 runs, competitor is libsndfile (soundfile 0.14).
| format | metadata | decode (median / p95) | libsndfile | result | PCM vs libsndfile |
|---|---|---|---|---|---|
| WAV (PCM 16) | 0.02 ms | 9.1 / 11.2 ms | 11.4 ms | 1.25× faster | identical |
| FLAC | 0.03 ms | 16.3 / 17.7 ms | 41.0 ms | 2.5× faster | identical |
| MP3 | 0.02 ms | 33.8 / 34.3 ms | 24.5 ms | 1.4× slower | 1.9e-07 |
| M4A (AAC) | 0.17 ms | 34.7 / 38.2 ms | unsupported | sound_rs only | matches ffmpeg to 8e-08 |
Playback of a 3 s tone, overhead over the track duration (median of 5):
| median | p95 | overhead | |
|---|---|---|---|
| sound_rs | 3.124 s | 3.280 s | +0.124 s |
| sounddevice | 3.125 s | 3.131 s | +0.125 s |
What the numbers say, including the unflattering parts:
- Metadata no longer decodes the file. Reading a 2-hour file costs the same as reading a 3-second one, because it comes from the container header.
- PCM output matches libsndfile exactly for WAV and FLAC, and to 1.9e-07 for MP3 — both trim the encoder delay and padding, so sample N means the same thing in both libraries. For AAC/MP4 the priming is read from the MP4 edit list, which libsndfile cannot even decode.
- MP3 decoding is ~1.4× behind libmpg123. That is the decoder itself, not the plumbing; fixing it means a different MP3 decoder.
- Playback overhead is stream setup and teardown, ~0.1 s per call. Reducing it to single-digit milliseconds needs a persistent stream, which is the next item on the roadmap.
🛠️ Roadmap
| Step | Feature | Description |
|---|---|---|
| ✅ 1 | WAV playback | Core playback |
| ✅ 2 | MP3, FLAC, M4A, AAC, 24-bit | Full symphonia decode path |
| ✅ 3 | NumPy integration | 1D/2D float32 arrays |
| ✅ 4 | Decode to array | load(path) -> (ndarray, sample_rate) without playing |
| 🔜 5 | Player object |
Persistent stream: pause, resume, seek, volume, position |
| 🔜 6 | Device selection | list_devices(), choose input/output |
| 🔜 7 | Recording | Microphone → array or WAV |
🧪 Development
cargo test # resampler and channel conversion
maturin develop --release # build the extension into your venv
python tests/smoke.py # end-to-end decode checks
SOUND_RS_PLAY=1 python tests/smoke.py # also plays (needs an audio device)
python examples/benchmark.py
⚙️ Built With
- 🦀 Rust — performance and safety
- 🔗 PyO3 — Python bridge
- 🧰 Maturin — building and publishing
- 🔊 cpal + symphonia — audio backend and decoders
👨💻 Author
Nurassyl Mussainov Kazakhstan 🇰🇿 Python / Rust Developer
🔗 GitHub: Neksand 📦 PyPI: sound_rs
📜 License
Licensed under the MIT License — free for personal and commercial use.
Metadata
Release files for sound-rs 0.1.8
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| sound_rs-0.1.8.tar.gz | 31.0 kB | Without provenance | Details for sound_rs-0.1.8.tar.gz |
Built distributions (wheels)
Total release size: 14.1 MB
Release files / sound_rs-0.1.8.tar.gz
| Download URL | sound_rs-0.1.8.tar.gz |
|---|---|
| Size | 31.0 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
d965dfaeb612218a277b06db7d0e293a43f576379c1a762f0428d05275403787
|
|
BLAKE2b-256 checksum How to use checksums |
eff29f7da0bcb339e8412926f12535cd20b4334b0fcc0a2397801f910d6b6299
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Release files / sound_rs-0.1.8-cp314-cp314-win_amd64.whl
| Download URL | sound_rs-0.1.8-cp314-cp314-win_amd64.whl |
|---|---|
| Size | 767.8 kB |
| Tags | CPython 3.14 Windows x86-64 |
|
SHA-256 checksum How to use checksums |
b7d7f4aec1a203517ff95ed9b557364f7d2c0251582faf896e5235b1f9f83e57
|
|
BLAKE2b-256 checksum How to use checksums |
352de3b5b9fe981dfd115a339d6181146b2e813c5b8e6ce1980671083184d556
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Release files / sound_rs-0.1.8-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl
| Download URL | sound_rs-0.1.8-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl |
|---|---|
| Size | 1.3 MB |
| Tags | CPython 3.14 Linux glibc 2.17+ x86-64 |
|
SHA-256 checksum How to use checksums |
1fd474f658ea95ed9f52e24703fc4f5481b1ed3dda511979c3a73c786d84895d
|
|
BLAKE2b-256 checksum How to use checksums |
736a08b6d75c04ba1d6dfc7fe3bd5fbe97e36669bd51aa647b59ee03f07c0821
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Release files / sound_rs-0.1.8-cp314-cp314-macosx_11_0_arm64.whl
| Download URL | sound_rs-0.1.8-cp314-cp314-macosx_11_0_arm64.whl |
|---|---|
| Size | 768.2 kB |
| Tags | CPython 3.14 macOS 11.0+ ARM64 |
|
SHA-256 checksum How to use checksums |
ccff0e18e497055ca999547e5963b6a4bc064babb8f53537351d50cdffb8acb4
|
|
BLAKE2b-256 checksum How to use checksums |
3d7af6be504f6ac3dd391d11a8a874da2831b32f9684a305b8f3e975e5fea64e
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Release files / sound_rs-0.1.8-cp313-cp313-win_amd64.whl
| Download URL | sound_rs-0.1.8-cp313-cp313-win_amd64.whl |
|---|---|
| Size | 767.6 kB |
| Tags | CPython 3.13 Windows x86-64 |
|
SHA-256 checksum How to use checksums |
a716c878d9f6b7b132b8322a815894e42fc5f0a859517459c27c2d116e7e2efa
|
|
BLAKE2b-256 checksum How to use checksums |
6073d95b0049848b52daa5fa052f0c1cdeaa246072f18dfe16a27e73d11fbbb6
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Release files / sound_rs-0.1.8-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl
| Download URL | sound_rs-0.1.8-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl |
|---|---|
| Size | 1.3 MB |
| Tags | CPython 3.13 Linux glibc 2.17+ x86-64 |
|
SHA-256 checksum How to use checksums |
c32d77eda2b2199fbb4c30afb06089d324851b211cc9e0fbca261ac9c4bb5269
|
|
BLAKE2b-256 checksum How to use checksums |
09569b9abe3e0a321fd841fa2771eb82fdd45b837d062c1efd990f8e63efb06b
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Release files / sound_rs-0.1.8-cp313-cp313-macosx_11_0_arm64.whl
| Download URL | sound_rs-0.1.8-cp313-cp313-macosx_11_0_arm64.whl |
|---|---|
| Size | 768.1 kB |
| Tags | CPython 3.13 macOS 11.0+ ARM64 |
|
SHA-256 checksum How to use checksums |
af233d3687db1c57d4edf5e2d87e03850f24eaddac63f133ea36d7b56e91994c
|
|
BLAKE2b-256 checksum How to use checksums |
1eb494cb68c54bd476bb2acfde27e57a373340a7f24e45fcc8a46195de611953
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Release files / sound_rs-0.1.8-cp312-cp312-win_amd64.whl
| Download URL | sound_rs-0.1.8-cp312-cp312-win_amd64.whl |
|---|---|
| Size | 767.7 kB |
| Tags | CPython 3.12 Windows x86-64 |
|
SHA-256 checksum How to use checksums |
e680950d35c3e0ccfa9e719fa540793f32eaf93fc9497c9a9188ad995ef99099
|
|
BLAKE2b-256 checksum How to use checksums |
9822c6904d86c595859884d51af068db786748abdb080b745bbd4c39f474b09e
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Release files / sound_rs-0.1.8-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl
| Download URL | sound_rs-0.1.8-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl |
|---|---|
| Size | 1.3 MB |
| Tags | CPython 3.12 Linux glibc 2.17+ x86-64 |
|
SHA-256 checksum How to use checksums |
3fa5d7389ff36346844d2890a9a19d686c684cb632a578f38272f274c8617062
|
|
BLAKE2b-256 checksum How to use checksums |
456a67228266f7887ac8ba406e14b52ad134527656361825f7b8b8a2c7df4d7a
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Release files / sound_rs-0.1.8-cp312-cp312-macosx_11_0_arm64.whl
| Download URL | sound_rs-0.1.8-cp312-cp312-macosx_11_0_arm64.whl |
|---|---|
| Size | 768.1 kB |
| Tags | CPython 3.12 macOS 11.0+ ARM64 |
|
SHA-256 checksum How to use checksums |
74e16750f0be0c6c7336be256e9156892a7b634061deb48f33db001c47fb3d3c
|
|
BLAKE2b-256 checksum How to use checksums |
9d184425d862a95cedfc23350f3e9553a66af80bbad99275257e88ba20beeb10
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Release files / sound_rs-0.1.8-cp311-cp311-win_amd64.whl
| Download URL | sound_rs-0.1.8-cp311-cp311-win_amd64.whl |
|---|---|
| Size | 767.1 kB |
| Tags | CPython 3.11 Windows x86-64 |
|
SHA-256 checksum How to use checksums |
a719ad6a56bf1545fa31fbad044ce9793c6a99b8c765c8cc0c033df5ede994b5
|
|
BLAKE2b-256 checksum How to use checksums |
57be470d5a89fb66df0d31d78b22e79192dce40f5f181b1c03cbd3fdde43c360
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Release files / sound_rs-0.1.8-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl
| Download URL | sound_rs-0.1.8-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl |
|---|---|
| Size | 1.3 MB |
| Tags | CPython 3.11 Linux glibc 2.17+ x86-64 |
|
SHA-256 checksum How to use checksums |
429069cf14c171eb6d08125210153fee97b3dd5317dcc9a384928f7e58d32016
|
|
BLAKE2b-256 checksum How to use checksums |
52c471cad02cc6fb18b334806fec271ac7820bfc5d3ec28ac671ade8e3cef260
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Release files / sound_rs-0.1.8-cp311-cp311-macosx_11_0_arm64.whl
| Download URL | sound_rs-0.1.8-cp311-cp311-macosx_11_0_arm64.whl |
|---|---|
| Size | 768.3 kB |
| Tags | CPython 3.11 macOS 11.0+ ARM64 |
|
SHA-256 checksum How to use checksums |
76326fc6baa944fbbbb0784047785d0c5e7df03bbdc49bd54e8ac353f0a3be5d
|
|
BLAKE2b-256 checksum How to use checksums |
e9b7cd5b2c2f65003cf3cf279039d0942afe9a78b1763676bb0554a311d9d926
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Release files / sound_rs-0.1.8-cp310-cp310-win_amd64.whl
| Download URL | sound_rs-0.1.8-cp310-cp310-win_amd64.whl |
|---|---|
| Size | 767.1 kB |
| Tags | CPython 3.10 Windows x86-64 |
|
SHA-256 checksum How to use checksums |
2564c8fc1bfac64e1afe00c7f108769985baccccce48ec6c9f5da427a84f4b87
|
|
BLAKE2b-256 checksum How to use checksums |
4a79aa30bf7fb2b35421737635867688268bbf49e33ad81f6c5b2966e2d4bcef
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Release files / sound_rs-0.1.8-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl
| Download URL | sound_rs-0.1.8-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl |
|---|---|
| Size | 1.3 MB |
| Tags | CPython 3.10 Linux glibc 2.17+ x86-64 |
|
SHA-256 checksum How to use checksums |
975e7c3e5dcd22d5859608c93c1f5f67eb4cdd05a9622427f81052165b0ca432
|
|
BLAKE2b-256 checksum How to use checksums |
43024bc9d70fd42412110dbf70872e01cd2fe7d204b703dab54dca26e4ad6ebe
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Release files / sound_rs-0.1.8-cp310-cp310-macosx_11_0_arm64.whl
| Download URL | sound_rs-0.1.8-cp310-cp310-macosx_11_0_arm64.whl |
|---|---|
| Size | 768.0 kB |
| Tags | CPython 3.10 macOS 11.0+ ARM64 |
|
SHA-256 checksum How to use checksums |
1327abcf918cdeb05bab10dfe7ac1038dba2a76d99b33361c8847c7623fca2f1
|
|
BLAKE2b-256 checksum How to use checksums |
d2f460c64a436020f6609d490ff2d5caa59f951f47542ad249bfb2ca1a56b9cb
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Security for sound-rs 0.1.8
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.