Example: Blocking Mode Audio I/O¶
"""PyAudio Example: Play a wave file."""
import wave
import sys
import pyaudio
CHUNK = 1024
if len(sys.argv) < 2:
print(f'Plays a wave file. Usage: {sys.argv[0]} filename.wav')
sys.exit(-1)
with wave.open(sys.argv[1], 'rb') as wf:
# Instantiate PyAudio and initialize PortAudio system resources (1)
p = pyaudio.PyAudio()
# Open stream (2)
stream = p.open(format=p.get_format_from_width(wf.getsampwidth()),
channels=wf.getnchannels(),
rate=wf.getframerate(),
output=True)
# Play samples from the wave file (3)
while len(data := wf.readframes(CHUNK)): # Requires Python 3.8+ for :=
stream.write(data)
# Close stream (4)
stream.close()
# Release PortAudio system resources (5)
p.terminate()
To use PyAudio, first instantiate PyAudio using pyaudio.PyAudio()
(1),
which acquires system resources for PortAudio.
To record or play audio, open a stream on the desired device with the
desired audio parameters using pyaudio.PyAudio.open()
(2). This sets up a pyaudio.PyAudio.Stream
to play or record
audio.
Play audio by writing audio data to the stream using
pyaudio.PyAudio.Stream.write()
, or read audio data from the stream
using pyaudio.PyAudio.Stream.read()
. (3)
Note that in “blocking mode”, each pyaudio.PyAudio.Stream.write()
or
pyaudio.PyAudio.Stream.read()
blocks until all frames have been
played/recorded. An alternative approach is “callback mode”, described below, in
which PyAudio invokes a user-defined function to process recorded audio or
generate output audio.
Use pyaudio.PyAudio.Stream.close()
to close the stream. (4)
Finally, terminate the PortAudio session and release system resources using
pyaudio.PyAudio.terminate()
. (5)
Example: Callback Mode Audio I/O¶
"""PyAudio Example: Play a wave file (callback version)."""
import wave
import time
import sys
import pyaudio
if len(sys.argv) < 2:
print(f'Plays a wave file. Usage: {sys.argv[0]} filename.wav')
sys.exit(-1)
with wave.open(sys.argv[1], 'rb') as wf:
# Define callback for playback (1)
def callback(in_data, frame_count, time_info, status):
data = wf.readframes(frame_count)
# If len(data) is less than requested frame_count, PyAudio automatically
# assumes the stream is finished, and the stream stops.
return (data, pyaudio.paContinue)
# Instantiate PyAudio and initialize PortAudio system resources (2)
p = pyaudio.PyAudio()
# Open stream using callback (3)
stream = p.open(format=p.get_format_from_width(wf.getsampwidth()),
channels=wf.getnchannels(),
rate=wf.getframerate(),
output=True,
stream_callback=callback)
# Wait for stream to finish (4)
while stream.is_active():
time.sleep(0.1)
# Close the stream (5)
stream.close()
# Release PortAudio system resources (6)
p.terminate()
In callback mode, PyAudio will call a user-defined callback function (1)
whenever it needs new audio data to play and/or when new recorded audio data
becomes available. PyAudio calls the callback function in a separate thread. The
callback function must have the following signature callback(<input_data>,
<frame_count>, <time_info>, <status_flag>)
. It must return a tuple containing
frame_count
frames of audio data to output (for output streams) and a flag
signifying whether there are more expected frames to play or record. (For
input-only streams, the audio data portion of the return value is ignored.)
The audio stream starts processing once the stream is opened (3), which will
call the callback function repeatedly until that function returns
pyaudio.paComplete
or pyaudio.paAbort
, or until either
pyaudio.PyAudio.Stream.stop
or
pyaudio.PyAudio.Stream.close
is called. Note that if the callback
returns fewer frames than the frame_count
argument (2), the stream
automatically closes after those frames are played.
To keep the stream active, the main thread must remain alive, e.g., by sleeping
(4). In the example above, once the entire wavefile is read,
wf.readframes(frame_count)
will eventually return fewer than the
requested frames. The stream will stop, and the while loop (4) will end.