Py-Audio instantaneous recording to file without buffering

On March 23, 2017 by aTutorMe

Py-Audio has an awesome script to record sound from your recording device {mic, webcam, etc.} and output to a wave file.

Here is the example script to record audio taken from the Py-Audio website:

"""PyAudio example: Record a few seconds of audio and save to a WAVE file."""

import pyaudio
import wave

CHUNK = 1024
FORMAT = pyaudio.paInt16
CHANNELS = 2
RATE = 44100
RECORD_SECONDS = 5
WAVE_OUTPUT_FILENAME = "output.wav"

p = pyaudio.PyAudio()

stream = p.open(format=FORMAT,
                channels=CHANNELS,
                rate=RATE,
                input=True,
                frames_per_buffer=CHUNK)

print("* recording")

frames = []

for i in range(0, int(RATE / CHUNK * RECORD_SECONDS)):
    data = stream.read(CHUNK)
    frames.append(data)

print("* done recording")

stream.stop_stream()
stream.close()
p.terminate()

wf = wave.open(WAVE_OUTPUT_FILENAME, 'wb')
wf.setnchannels(CHANNELS)
wf.setsampwidth(p.get_sample_size(FORMAT))
wf.setframerate(RATE)
wf.writeframes(b''.join(frames))
wf.close()

This is awesome, BUT if you’re doing a long recording and something happens like an automatic reboot, crash, etc. then all your recorded samples will be lost.

An alternate way to make sure that your audio is written to file instantaneously is by making a small modification to the above code.

  1. Instantiate the wave file before reading the audio stream.
  2. Write the frames as soon as you read a chunk of input from the stream.

See the modified portion of the script below:

wf = wave.open(WAVE_OUTPUT_FILENAME, 'wb')
wf.setnchannels(CHANNELS)
wf.setsampwidth(p.get_sample_size(FORMAT))
wf.setframerate(RATE)
for i in range(0, int(RATE / CHUNK * RECORD_SECONDS)):
    data = stream.read(CHUNK)
    frames = []
    frames.append(data)
    wf.writeframes(b''.join(frames))
print("* done recording")
stream.stop_stream()
stream.close()
p.terminate()
wf.close()