mrkeyoor.com_
Wed 23 Sept 00:34 UTC
PyPIUtilsupdated 22 Sept 2026

sounddevice review

sounddevice 0.5.6 connects Python code to PortAudio input and output devices on Linux, macOS, and Windows. `play()`, `rec()`, and `playrec()` handle short NumPy jobs; blocking and callback streams cover longer work, while Raw streams exchange byte buffers. Version 0.5.6 fixes architecture detection for Windows ARM64. Our binding import took 0.05 seconds, but that check did not prove that a microphone, speaker, host API, or requested sample rate existed. This package moves sample buffers to hardware; it does not decode audio files or supply a mixer and effects graph.

Verdict

sounddevice 0.5.6 installed in 0.2 seconds and its binding loaded in 0.05 seconds with 2 MB on disk in our sandbox, but no audio device was proven. Use it for PortAudio-backed NumPy I/O only when native routing and callback deadlines are deployment concerns you can test.

We installed it

Lab card: what happened when we installed sounddeviceScreenshot of sounddevice documentation
Install✓ · 0.2s3 packages on disk · 2 MB
Importimport _sounddevice in 0.05s · pure Python · requires Python >=3.7
Known vulns0(pip-audit)

Answers from our run

Does sounddevice install cleanly?

Yes. In a fresh container with an empty cache, pip install sounddevice finished in 0.2s, leaving 3 packages and 2 MB on disk. pip-audit reported no known vulnerabilities.

What does sounddevice need to run?

Python >=3.7, and nothing compiled: it is pure Python. In our run import _sounddevice succeeded in 0.05s.

sounddevice or PyAudio: which should you use?

PyAudio: Use it when maintaining a PortAudio codebase already organized around PyAudio's stream API. sounddevice 0.5.6 installed in 0.2 seconds and its binding loaded in 0.05 seconds with 2 MB on disk in our sandbox, but no audio device was proven.

When should you not use sounddevice?

The task is decoding, encoding, resampling, or editing files. sounddevice talks to hardware; a file codec library handles stored audio.

API stability4/5Device queries, module defaults, convenience playback and recording, blocking streams, callback streams, and raw-buffer variants have recognizable contracts throughout the 0.5 series. Version 0.5.6 changes Windows ARM64 detection rather than the stream API. Behavior can still differ with the PortAudio build and host driver, and the helpers' shared module state surprises callers that assume 2 play operations are independent.
Docs5/5The versioned manual separates installation, device discovery, convenience functions, blocking streams, callbacks, raw streams, platform settings, examples, and release notes. Its callback reference states buffer assignment, deadlines, status flags, exceptions, block-size behavior, and latency tradeoffs. Platform pages also explain bundled versus system PortAudio and Windows ASIO selection, the details most likely to fail after moving from a developer laptop.
Maintenance5/5PyPI published version 0.5.6 on August 17, 2026, and the repository was pushed later that day. GitHub shows 1,267 stars, 206 open issues and pull requests, and an unarchived repository. The release fixes current Windows ARM64 architecture detection. The large combined queue deserves attention, although hardware, OS routing, and PortAudio reports often need triage before maintainers can identify a Python binding defect.
Ecosystem4/5PyPI Stats counted 5,115,166 downloads in the latest week. NumPy buffers connect naturally to SciPy, plots, measurement code, and file I/O through separate packages. PortAudio supplies broad desktop host coverage across 3 operating-system families. sounddevice deliberately leaves codecs, resampling, editing, mixing, mobile support, and cross-device policy elsewhere, so a complete audio product needs more than this binding.

Use it if

  • A desktop Python tool needs direct microphone capture or speaker playback through a PortAudio host API.
  • Measurement, synthesis, or signal-processing code works with NumPy buffers and can obey real-time callback limits.
  • A script needs a fixed-duration recording or quick playback from the default device.
  • An existing binary pipeline wants `RawInputStream` or `RawOutputStream` without NumPy conversion.
Skip it if

Setup reality

Our install of sounddevice 0.5.6 completed in 0.2 seconds in a clean Python 3.12 container. Three packages occupied 2 MB, importing _sounddevice took 0.05 seconds, and pip-audit reported 0 known vulnerabilities. The pure-Python package has 2 direct dependencies, requires Python 3.7 or newer, and contains no py.typed marker. PyPI's license field is empty, although the repository README states MIT.

Loading the binding does not validate audio hardware. PortAudio is still native code. Windows and macOS wheels commonly include it; Linux often needs a system library plus ALSA, PulseAudio, PipeWire, or JACK routing. Capture query_hostapis() and query_devices() in diagnostics. Device indexes can change after reconnection, and a name fragment can be ambiguous. Run check_input_settings() or check_output_settings() with the exact device, channel count, sample rate, and dtype before opening a persistent stream.

play(), rec(), and playrec() return before completion unless blocking=True is used or wait() follows. Starting a second convenience operation stops the first because those helpers share module state. Use separate Stream objects for overlap. A callback must fill every output frame with outdata[:], inspect status flags, and put slow work onto a bounded queue. blocksize=0 lets PortAudio choose buffers and often has more scheduling margin than an aggressively small fixed block.

Low latency reduces the time available before an underflow or overflow. Normal callback exceptions do not propagate to the main thread; use CallbackStop or CallbackAbort for documented control and communicate other failures through shared state or a queue. Windows ASIO depends on the PortAudio DLL that loads. For the pip build switch, set SD_ENABLE_ASIO before importing sounddevice. Version 0.5.6 only fixes Windows ARM64 detection, so every target device and driver still needs a real playback and capture test.

Patterns

List device channel capacities list-audio-devices

import sounddevice as sd

for index, device in enumerate(sd.query_devices()):
    print(index, device['name'], device['max_input_channels'], device['max_output_channels'])

Device indexes can change after reboot or reconnection. Store a human-readable identity and validate the selected index again at startup.

Inspect the loaded PortAudio host APIs inspect-host-apis

import sounddevice as sd

for api in sd.query_hostapis():
    print(api['name'], api['default_input_device'], api['default_output_device'])

The machine and loaded PortAudio DLL determine this list. Installing version 0.5.6 does not guarantee ASIO, JACK, or another named backend.

Check a device format before opening it validate-input-format

sd.check_input_settings(device='USB Audio', channels=1, samplerate=48000, dtype='float32')

A text selector must match one device unambiguously. Query devices after a failure and verify all 4 parameters against the intended hardware.

Play samples and wait for completion play-numpy-array

sd.play(samples, samplerate=48000)
status = sd.wait()
if status: print(status)

`play()` starts asynchronously. `wait()` blocks until completion and returns callback status, including output underflow information.

Record 5 seconds of mono audio record-fixed-duration

rate = 48000
audio = sd.rec(5 * rate, samplerate=rate, channels=1, dtype='float32')
sd.wait()

The returned NumPy array is still being filled until `wait()` completes. Validate the input format before depending on its 240000 frames.

Capture input while playing an array play-and-record

recorded = sd.playrec(output_samples, samplerate=48000, channels=1, dtype='float32')
sd.wait()

The playback array shape sets output channels, while `channels=1` selects the number of recorded input channels.

Set process-wide input and output defaults configure-default-devices

sd.default.device = ('USB Microphone', 'Built-in Output')
sd.default.samplerate = 48000
sd.default.channels = (1, 2)

These assignments mutate module-wide state. Reusable libraries should pass stream arguments rather than changing the host application's defaults.

Copy microphone frames to the output run-duplex-callback

def callback(indata, outdata, frames, time_info, status):
    outdata[:] = indata

with sd.Stream(samplerate=48000, channels=1, blocksize=0, callback=callback):
    sd.sleep(5000)

Use headphones to avoid feedback. Move logging and other slow work out of the callback, and copy with `outdata[:]` so the supplied buffer is filled.

Stop after the source buffer ends stop-output-stream

position = 0
def callback(outdata, frames, time_info, status):
    global position
    count = min(frames, len(samples) - position)
    outdata.fill(0)
    outdata[:count] = samples[position:position + count]
    position += count
    if count < frames: raise sd.CallbackStop

Zero unused frames before raising `CallbackStop`. A normal exception is printed to stderr and does not arrive as an exception in the main thread.

Read one input block outside a callback read-blocking-input

with sd.InputStream(samplerate=48000, channels=1, dtype='float32') as stream:
    block, overflowed = stream.read(1024)

Blocking reads are simple only when the caller drains frames fast enough. Check `overflowed` on every 1024-frame read.

Read int16 frames without NumPy capture-raw-bytes

with sd.RawInputStream(samplerate=48000, channels=1, dtype='int16') as stream:
    data, overflowed = stream.read(1024)
    payload = bytes(data)

Raw consumers must agree on byte order, 16-bit sample format, channel order, and frame boundaries. The buffer carries no self-describing header.

Request the pip ASIO build before import enable-windows-asio

import os
os.environ['SD_ENABLE_ASIO'] = '1'
import sounddevice as sd
print(sd.query_hostapis())

Set the variable before the first import. A different PortAudio DLL earlier on PATH can still determine which host APIs appear.

Alternatives

PackageRegistryPick it when
PyAudioPyPIUse it when maintaining a PortAudio codebase already organized around PyAudio's stream API.
SoundCardPyPIUse it for a compact NumPy capture and playback layer over native platform audio backends.
simpleaudioPyPIUse it for straightforward playback when recording and callback streams are unnecessary.

More utils guides

lru-cache · ajv · type-fest · p-limit · find-up · js-yaml · the whole shelf →

How this guide is made: grounded in the library's documentation, release notes, changelog, and issue history, on a fixed rubric — not a hands-on install of every release. The 50 most-downloaded entries are additionally install-verified in clean containers. Corrections: contact the desk.