PyAudio
PyAudio provides Python bindings for PortAudio, a cross-platform audio I/O library. It allows you to easily use Python to play and record audio on a variety of platforms. The current version is 0.2.14, and the library maintains a stable but slow release cadence.
Warnings
- gotcha PyAudio requires the PortAudio system library (specifically, its development headers) to be installed before `pip install pyaudio` can succeed. This is a common installation barrier.
- gotcha Forgetting to close streams (`stream.close()`) and terminate the PyAudio instance (`p.terminate()`) can lead to resource leaks, prevent other applications from accessing audio devices, or cause unexpected behavior.
- gotcha Encountering `IndexError: no input device found` or `OSError: [Errno -9996] Invalid output device` indicates issues with audio device detection, permissions, or drivers. This is common on fresh installs or virtual machines.
- gotcha The `stream.write()` and `stream.read()` methods expect audio data as raw `bytes`. Passing data in other formats (e.g., `str`, `list`, `numpy.ndarray` without conversion) will result in `TypeError` or `ValueError`.
Install
-
pip install pyaudio -
sudo apt-get install portaudio19-dev # Debian/Ubuntu brew install portaudio # macOS
Imports
- PyAudio
import pyaudio p = pyaudio.PyAudio()
- Stream
import pyaudio p = pyaudio.PyAudio() stream = p.open(...)
Quickstart
import pyaudio
import math
# Configuration
CHUNK = 1024
FORMAT = pyaudio.paInt16
CHANNELS = 1
RATE = 44100
FREQUENCY = 440 # A4 note
DURATION = 3 # seconds
# Initialize PyAudio
p = pyaudio.PyAudio()
# Generate a sine wave
def generate_sine_wave(frequency, duration, rate, amplitude=1.0):
samples = []
for i in range(int(rate * duration)):
value = amplitude * math.sin(2 * math.pi * frequency * (i / rate))
# Scale to 16-bit integer range
samples.append(int(value * 32767))
# Convert to bytes (little-endian, signed)
return b''.join(s.to_bytes(2, byteorder='little', signed=True) for s in samples)
print(f"Generating a {FREQUENCY} Hz sine wave for {DURATION} seconds...")
wave_data = generate_sine_wave(FREQUENCY, DURATION, RATE)
# Open stream for playback
stream = p.open(format=FORMAT,
channels=CHANNELS,
rate=RATE,
output=True)
print("Playing audio...")
stream.write(wave_data)
print("Finished playing.")
# Clean up
stream.stop_stream()
stream.close()
p.terminate()