easyaudiostream
Simple playback for intermittent audio byte streams in Python.
I built this library because I was tired of existing audio playback solutions in Python not supporting audio streams particularly well (compared to audio files). easyaudiostream is intended for simple, high-enough-fidelity playback of audio byte streams:
- No choppiness between bytestream segments
- Handles non-real-time streams -- faster and slower than real-time
- Handles intermittent streams (i.e., streams that may not yield bytes for a while)
- asyncio-safe -- no blocking computation on main thread
easyaudiostream also includes basic utilities for recording audio from a microphone.
Installation
Requires Python 3.8 or higher.
By default, easyaudiostream will use the ffmpeg (if it is installed) or the bundled PyDub library for playback.
$ pip install easyaudiostream
[!NOTE] You can also install PyAudio to slightly improve playback startup time and enable the microphone input utilities:
$ pip install easyaudiostream[pyaudio]This is not installed by default due to compatibility issues across operating systems.
Usage
There are two main ways of playing an audio stream: using an iterator (if your audio generator yields bytes) or callbacks (if your audio generator calls a function with generated bytes).
Iterator Mode
For iterator mode, use the following two functions:
def play_stream(audio_stream: Iterable[bytes]):
"""
Consume bytes from the audio stream and play them.
.. note::
This function will return as soon as the stream is exhausted!
If your program ends after calling this function, the audio will not play - you might need to ``sleep(...)``.
"""
def play_raw_stream(
audio_stream: Iterable[bytes], *, sample_width: int = 2, channels: int = 1, frame_rate: int = 24000
):
"""
Consume PCM audio bytes from the audio stream and play them.
.. warning::
If you aren't sure which function to use, use :func:`.stream_audio` instead! Playing raw audio bytes is
a minor optimization that avoids converting the audio format, but requires a specific input format.
.. note::
This function will return as soon as the stream is exhausted!
If your program ends after calling this function, the audio will not play - you might need to ``sleep(...)``.
By default, this method accepts raw 16 bit PCM audio at 24kHz, 1 channel, little-endian. You can control the
expected format of the raw audio using the keyword arguments.
"""
Callback Mode
For callback mode, use the following two functions:
def play_audio(audio_bytes: bytes):
"""
Play the given audio at the next available opportunity, using a global audio queue.
.. note::
This function will return immediately - it just puts the audio on a queue!
If your program ends after calling this function, the audio will not play - you might need to ``sleep(...)``.
"""
def play_raw_audio(audio_bytes: bytes, *, sample_width: int = 2, channels: int = 1, frame_rate: int = 24000):
"""
Play the given raw audio at the next available opportunity, using a global audio queue.
.. warning::
If you aren't sure which function to use, use :func:`.play_audio` instead! Playing raw audio bytes is
a minor optimization that avoids converting the audio format, but requires a specific input format.
.. note::
This function will return immediately - it just puts the audio on a queue!
If your program ends after calling this function, the audio will not play - you might need to ``sleep(...)``.
By default, this method accepts raw 16 bit PCM audio at 24kHz, 1 channel, little-endian. You can control the
expected format of the raw audio using the keyword arguments.
"""
Record Mic
The following functions are available to record audio from a mic:
def get_mic_stream(mic_id: int | None) -> Iterable[bytes]:
"""Return an audio stream manager that yields audio frames from the given mic."""
def get_mic_stream_async(mic_id: int | None) -> AsyncIterable[bytes]:
"""Return an audio stream manager that yields audio frames from the given mic."""
def list_mics():
"""Print a list of all microphones connected to this device."""
You can use python -m easyaudiostream to view a list of connected microphones.
Examples
import time
from easyaudiostream import play_stream
# load dummy audio from file -- normally you would get an audio stream from somewhere else
# in this example, test_audio.wav contains 16bLE mono PCM audio at 24kHz
with open("test_audio.wav", "rb") as f:
audio = f.read()
# yield it in 1s packets every 0.95s
# but every 5s, add a 3s delay
def choppy_stream():
for sec in range(0, len(audio), 48000 * 5):
for i in range(0, 48000 * 5, 48000):
yield audio[sec + i : sec + i + 48000]
time.sleep(0.95)
# oh no, my bytes!
time.sleep(3)
play_stream(choppy_stream())
time.sleep(10) # to allow all the audio to play
Release files for easyaudiostream 0.0.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| easyaudiostream-0.0.1.tar.gz | 9.3 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| easyaudiostream-0.0.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 18.4 kB
Release files / easyaudiostream-0.0.1.tar.gz
| Download URL | easyaudiostream-0.0.1.tar.gz |
|---|---|
| Size | 9.3 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
88eb9b102fa1496c9cf2a82c313c05f738ad15cbca49a07c8a8256fefc62797e
|
|
BLAKE2b-256 checksum How to use checksums |
6ee428e50d76f8bb4dd0a8ba2c9a4768f4028a3a8775afb5c80fe61b71298042
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.12.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.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jan 29, 2025.
Transparency logRelease files / easyaudiostream-0.0.1-py3-none-any.whl
| Download URL | easyaudiostream-0.0.1-py3-none-any.whl |
|---|---|
| Size | 9.2 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
5fdd84b5b8c46bf3e461e406b00ed92e2200a43ad471b46b6062dc7c53c869c3
|
|
BLAKE2b-256 checksum How to use checksums |
191ad788e6897f6574c494676472f78afc8c0801f406109a2a3b19c0f7d26621
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.12.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.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jan 29, 2025.
Transparency log