Skip to main content

Cross-platform audio output for Python, powered by Rust and CPAL

Project description

PyAudioCast

CI PyPI codecov License: MIT

Cross-platform audio output library for Python, powered by Rust and CPAL.

Stream audio to any output device — including PipeWire/PulseAudio virtual sinks on Linux — with a simple Python API backed by a high-performance Rust core.

Features

  • Cross-platform: Linux (ALSA/PipeWire/PulseAudio), Windows (WASAPI), macOS (CoreAudio)
  • Auto-detect: Sample rate and channels are detected from the device — zero config needed
  • Auto-negotiate: If the device doesn't support your sample rate, it automatically resamples and upmixes (e.g. 22050Hz mono TTS → 48000Hz stereo device)
  • Device selection: List and select output devices by name, including PipeWire virtual sinks
  • Streaming audio: Write audio data in chunks via a lock-free ring buffer — ideal for real-time TTS, generative audio, live effects, etc.
  • Unified write(): Accepts bytes, numpy arrays (int16/int32/float32/float64), or list[float] — format is detected automatically
  • Interruption: clear() instantly discards buffered audio and unblocks drain() — perfect for voice assistant barge-in
  • Context manager: Clean resource management with with statement
  • GIL-friendly: Releases the Python GIL during audio writes and drain, so other threads run freely
  • Clean output: ALSA/JACK backend probe noise is automatically suppressed
  • Debug logging: Enable detailed logs with PYAUDIOCAST_LOG=debug

Installation

From PyPI

pip install pyaudiocast

Note (Linux): Pre-built wheels require ALSA. Install libasound2 if not already present:

sudo apt install libasound2  # Debian/Ubuntu
sudo dnf install alsa-lib    # Fedora

From source (requires Rust toolchain)

# Install Rust if needed
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh

# Linux: install ALSA development headers
sudo apt install libasound2-dev  # Debian/Ubuntu
sudo dnf install alsa-lib-devel  # Fedora

# Clone and install
git clone https://github.com/nicokim/PyAudioCast.git
cd PyAudioCast
pip install maturin
maturin develop

Development setup (with uv)

uv venv && source .venv/bin/activate
uv pip install maturin numpy pytest
maturin develop

Quick Start

import pyaudiocast

# List all output devices
for dev in pyaudiocast.list_output_devices():
    print(f"[{dev['index']}] {dev['name']} ({dev['type']})")

# Stream audio — sample rate and channels auto-detected from device
with pyaudiocast.AudioPlayer() as player:
    print(f"Using: {player.sample_rate}Hz, {player.channels}ch")
    player.write(audio_bytes)   # bytes, numpy array, or list[float]
    player.drain()              # wait for playback to finish

# Override sample rate if your source requires it (auto-resampled to device)
with pyaudiocast.AudioPlayer(sample_rate=22050) as player:
    player.write(tts_audio)
    player.drain()

# Stream to a specific device
with pyaudiocast.AudioPlayer(device="Virtual-Mic") as player:
    player.write(samples)
    player.drain()

# One-shot WAV playback
pyaudiocast.play_file("audio.wav", device="pulse")

Streaming with Interruption

For real-time applications like voice assistants, you can interrupt playback instantly:

import pyaudiocast
import threading

with pyaudiocast.AudioPlayer(sample_rate=22050) as player:
    # Stream TTS chunks as they arrive
    for chunk in tts_stream:
        player.write(chunk)
    player.drain()  # wait for playback to finish
# Interrupt from another thread (e.g., when user starts speaking)
def on_user_speech_detected(player):
    player.clear()  # instantly stops audio, unblocks drain()

clear() discards all buffered audio immediately. Any blocked drain() returns right away. Calling write() again resumes normal playback.

Supported Audio Formats

write() auto-detects the input format:

Input type Format Conversion
bytes int16 little-endian PCM Converted to float32
numpy.ndarray (int16) int16 samples Converted to float32
numpy.ndarray (int32) int32 samples Converted to float32
numpy.ndarray (float32) float32 samples Direct (no conversion)
numpy.ndarray (float64) float64 samples Converted to float32
list[float] float32 samples (-1.0 to 1.0) Direct
import numpy as np

with pyaudiocast.AudioPlayer() as player:
    # All of these work with the same write() method
    player.write(b"\x00\x00" * 100)                    # bytes (int16 LE)
    player.write(np.zeros(100, dtype=np.int16))         # numpy int16
    player.write(np.zeros(100, dtype=np.float32))       # numpy float32 (fastest)
    player.write(np.zeros(100, dtype=np.float64))       # numpy float64
    player.write(np.zeros(100, dtype=np.int32))         # numpy int32
    player.write([0.0] * 100)                           # list[float]

API Reference

pyaudiocast.list_output_devices() -> list[dict]

Returns a list of available output devices. Each dict contains:

  • name (str): Device name
  • index (int): Device index
  • type (str): "alsa" for ALSA/cpal devices, "pipewire" for PipeWire/PulseAudio sinks

pyaudiocast.AudioPlayer(device=None, sample_rate=None, channels=None)

Streaming audio player with ring buffer.

Parameter Type Default Description
device str | None None Device name (substring match) or None for default
sample_rate int | None None Sample rate in Hz, or None to auto-detect
channels int | None None Number of audio channels, or None to auto-detect

If sample_rate or channels don't match the device natively, pyaudiocast automatically resamples and/or upmixes to the device's supported configuration.

Methods:

Method Description
write(data) Write audio data (bytes, numpy array, or list[float])
drain() Block until all buffered audio is played
clear() Discard buffer and unblock drain() immediately
stop() Stop playback and release resources

Properties:

Property Type Description
sample_rate int Requested sample rate (what you send)
channels int Requested channel count (what you send)
device_sample_rate int Actual device sample rate (what plays)
device_channels int Actual device channel count (what plays)
is_active bool Whether the player is active

Context manager: Supports with statement (calls stop() on exit).

pyaudiocast.play_file(path, device=None)

Play a WAV file to completion. Blocks until playback is done.

Device Selection

Default device

player = pyaudiocast.AudioPlayer()  # uses system default

ALSA device (by name substring)

player = pyaudiocast.AudioPlayer(device="pulse")
player = pyaudiocast.AudioPlayer(device="hw:CARD=Audio")

PipeWire/PulseAudio virtual sinks (Linux)

# Virtual sinks are auto-detected via pactl
player = pyaudiocast.AudioPlayer(device="Virtual-Mic")

PipeWire sinks are routed transparently through PULSE_SINK + the pulse ALSA device.

Environment Variables

Variable Description Example
PYAUDIOCAST_LOG Enable debug logging. Uses env_logger filter syntax. PYAUDIOCAST_LOG=debug

Logging

# Show everything (including ALSA/JACK backend messages)
PYAUDIOCAST_LOG=debug python my_script.py

# Show info and above
PYAUDIOCAST_LOG=info python my_script.py

# Default (no env var): warnings only, ALSA/JACK noise suppressed
python my_script.py

Cross-Platform Support

Platform Backend Device listing Virtual sinks
Linux ALSA + PipeWire/Pulse Full Yes (via pactl)
Windows WASAPI cpal devices N/A
macOS CoreAudio cpal devices N/A

The audio engine (cpal) is fully cross-platform. PipeWire/PulseAudio virtual sink detection uses pactl and is automatically compiled out on non-Linux systems via #[cfg(target_os = "linux")].

Architecture

Python (pyaudiocast)
  |
  +- write(data)  ->  auto-detect format  ->  convert to f32
  |     |
  |     v
  |  [resample + upmix if needed]
  |     |
  |     v
  |  Lock-free Ring Buffer (ringbuf crate)
  |     |
  |     v
  |  cpal audio callback (OS audio thread)
  |     |                          ^
  |     v                          |
  +- Speaker / Virtual Sink    clear() -> discard + silence
  • Ring buffer: Lock-free producer/consumer. Python pushes samples, the OS audio callback pulls them — no locks in the audio path.
  • GIL release: write() and drain() release the Python GIL during blocking operations.
  • Sample conversion: All input formats are converted to float32 in Rust before entering the ring buffer.
  • Auto-resample: If the device doesn't natively support the requested sample rate, linear interpolation resampling is applied transparently.
  • Auto-upmix: Mono audio is automatically duplicated to stereo (or more channels) to match the device.
  • Interruption: clear() sets an atomic flag checked by the audio callback, which discards remaining samples and outputs silence.

Running Tests

# Python tests
pytest tests/ -v

# Rust tests
cargo test

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

pyaudiocast-0.1.8.tar.gz (30.7 kB view details)

Uploaded Source

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

pyaudiocast-0.1.8-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (1.5 MB view details)

Uploaded CPython 3.14manylinux: glibc 2.17+ x86-64

pyaudiocast-0.1.8-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (1.5 MB view details)

Uploaded CPython 3.13manylinux: glibc 2.17+ x86-64

pyaudiocast-0.1.8-cp312-cp312-win_amd64.whl (737.0 kB view details)

Uploaded CPython 3.12Windows x86-64

pyaudiocast-0.1.8-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (1.5 MB view details)

Uploaded CPython 3.12manylinux: glibc 2.17+ x86-64

pyaudiocast-0.1.8-cp312-cp312-macosx_11_0_arm64.whl (843.8 kB view details)

Uploaded CPython 3.12macOS 11.0+ ARM64

pyaudiocast-0.1.8-cp312-cp312-macosx_10_12_x86_64.whl (897.9 kB view details)

Uploaded CPython 3.12macOS 10.12+ x86-64

pyaudiocast-0.1.8-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (1.5 MB view details)

Uploaded CPython 3.11manylinux: glibc 2.17+ x86-64

pyaudiocast-0.1.8-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (1.5 MB view details)

Uploaded CPython 3.10manylinux: glibc 2.17+ x86-64

pyaudiocast-0.1.8-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (1.5 MB view details)

Uploaded CPython 3.9manylinux: glibc 2.17+ x86-64

File details

Details for the file pyaudiocast-0.1.8.tar.gz.

File metadata

  • Download URL: pyaudiocast-0.1.8.tar.gz
  • Upload date:
  • Size: 30.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for pyaudiocast-0.1.8.tar.gz
Algorithm Hash digest
SHA256 87ad5010f6421247287be3a2b9c29ea359d379f1ec2407a19600374fb771fc61
MD5 c189bdb2027decf5011fd120428e96f0
BLAKE2b-256 74e1813b204d481773cb3e66a6ffa9fdb8c1b3f2af8c2c6420f9cdef8fba5422

See more details on using hashes here.

Provenance

The following attestation bundles were made for pyaudiocast-0.1.8.tar.gz:

Publisher: release.yml on nicokim/PyAudioCast

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file pyaudiocast-0.1.8-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for pyaudiocast-0.1.8-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 a45924a9bd82fdf6948df05f2553bcb50ada81202d9ce42ed3d29b959c274612
MD5 43e99e8ed4c16e9ede1a69c4e26a6943
BLAKE2b-256 a8d7cf802df24e693547dfc8b7a06a53223b83fc5e2549759a5d097a8c7e7a7e

See more details on using hashes here.

Provenance

The following attestation bundles were made for pyaudiocast-0.1.8-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl:

Publisher: release.yml on nicokim/PyAudioCast

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file pyaudiocast-0.1.8-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for pyaudiocast-0.1.8-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 3d64e1849c159c96e078e2b09622a3df31c0ba35df6ffa2ae44d42f58a85be95
MD5 eca8d8749e8cf7a8ee7c4c7b93ad7308
BLAKE2b-256 bc1632757bc8dc7d228a8bb2a53015e779866e69a88871b1761257943263af72

See more details on using hashes here.

Provenance

The following attestation bundles were made for pyaudiocast-0.1.8-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl:

Publisher: release.yml on nicokim/PyAudioCast

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file pyaudiocast-0.1.8-cp312-cp312-win_amd64.whl.

File metadata

  • Download URL: pyaudiocast-0.1.8-cp312-cp312-win_amd64.whl
  • Upload date:
  • Size: 737.0 kB
  • Tags: CPython 3.12, Windows x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for pyaudiocast-0.1.8-cp312-cp312-win_amd64.whl
Algorithm Hash digest
SHA256 0422bb6c56d4adb89675735a85dee81fc6b2d53b219dfc613d26bdcd29c029a7
MD5 e029ae828ca6f5b3d957617cea0b0788
BLAKE2b-256 7fc166bb2fc86d3b0ceef0ea6d6a50d51e08e7adbc2264a63ad156957cdd2ace

See more details on using hashes here.

Provenance

The following attestation bundles were made for pyaudiocast-0.1.8-cp312-cp312-win_amd64.whl:

Publisher: release.yml on nicokim/PyAudioCast

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file pyaudiocast-0.1.8-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for pyaudiocast-0.1.8-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 6c189f872d48d80d286d9461bf19a6d8687b2a83bfad795a1beda5768092cc01
MD5 a6c1b72920c5c40b80fb9d83a313fbb6
BLAKE2b-256 b8340667a56ecff4b44b69f3494e4ea3d75519ed973fedc49c28a46a8dab2c0b

See more details on using hashes here.

Provenance

The following attestation bundles were made for pyaudiocast-0.1.8-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl:

Publisher: release.yml on nicokim/PyAudioCast

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file pyaudiocast-0.1.8-cp312-cp312-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for pyaudiocast-0.1.8-cp312-cp312-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 21bfab84e87187150b1f33addc04a57054f45132f277a827eff878a93ff1a932
MD5 dab3bb366e58905150e97b7b69253484
BLAKE2b-256 b9e541b669c223dd439e9104ba70ffaa217a6e3aa306162599c2c19a8eb7cb86

See more details on using hashes here.

Provenance

The following attestation bundles were made for pyaudiocast-0.1.8-cp312-cp312-macosx_11_0_arm64.whl:

Publisher: release.yml on nicokim/PyAudioCast

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file pyaudiocast-0.1.8-cp312-cp312-macosx_10_12_x86_64.whl.

File metadata

File hashes

Hashes for pyaudiocast-0.1.8-cp312-cp312-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 877861dfdb64f87a0d50a41aa31a4f6131d06729522ebe96355731f6f2a0890e
MD5 c695218373dd12521ea995cd3c3bbbe2
BLAKE2b-256 557357afbe547cb567c9b9234ffc6472cae66373567d2a8df88d44eeedac4e55

See more details on using hashes here.

Provenance

The following attestation bundles were made for pyaudiocast-0.1.8-cp312-cp312-macosx_10_12_x86_64.whl:

Publisher: release.yml on nicokim/PyAudioCast

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file pyaudiocast-0.1.8-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for pyaudiocast-0.1.8-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 7227591f84c48ab6156f188f49f4325a7fe00f6033d632ffc2f666fb36223a8e
MD5 4789d79678e1502a5b5355d88d700fc8
BLAKE2b-256 331442e1a5d7c3a9a698b43b83a467e2f2264a52197b1898287693566998cbf8

See more details on using hashes here.

Provenance

The following attestation bundles were made for pyaudiocast-0.1.8-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl:

Publisher: release.yml on nicokim/PyAudioCast

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file pyaudiocast-0.1.8-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for pyaudiocast-0.1.8-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 842042cc2706a241775de16658f356decb564a60495e941e12e78697d8c9886a
MD5 e2d2e3dd16b3e45dc1d4492e82fdcc7b
BLAKE2b-256 33a3e92476f4c1ac6981a12c647e1806ffcda0e90cbdb166b8fd57d3070fbc0e

See more details on using hashes here.

Provenance

The following attestation bundles were made for pyaudiocast-0.1.8-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl:

Publisher: release.yml on nicokim/PyAudioCast

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file pyaudiocast-0.1.8-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for pyaudiocast-0.1.8-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 9e588f2ed78187949bdb4acde48632d6c6ce1b3798e3ef93ec7b6c2d660853d2
MD5 a41942197886b0dd65138e4188f9eeeb
BLAKE2b-256 b5a09930922a246497c4dbd90f7f2d35a7b58075dfcb59a1ccd5c9d19f769976

See more details on using hashes here.

Provenance

The following attestation bundles were made for pyaudiocast-0.1.8-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl:

Publisher: release.yml on nicokim/PyAudioCast

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page