Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
WAV recording functionality using pyaudio
# -*- coding: utf-8 -*-
'''recorder.py
Provides WAV recording functionality via two approaches:
Blocking mode (record for a set duration):
>>> rec = Recorder(channels=2)
>>> with rec.open('blocking.wav', 'wb') as recfile:
... recfile.record(duration=5.0)
Non-blocking mode (start and stop recording):
>>> rec = Recorder(channels=2)
>>> with rec.open('nonblocking.wav', 'wb') as recfile2:
... recfile2.start_recording()
... time.sleep(5.0)
... recfile2.stop_recording()
'''
import pyaudio
import wave
class Recorder(object):
'''A recorder class for recording audio to a WAV file.
Records in mono by default.
'''
def __init__(self, channels=1, rate=44100, frames_per_buffer=1024):
self.channels = channels
self.rate = rate
self.frames_per_buffer = frames_per_buffer
def open(self, fname, mode='wb'):
return RecordingFile(fname, mode, self.channels, self.rate,
self.frames_per_buffer)
class RecordingFile(object):
def __init__(self, fname, mode, channels,
rate, frames_per_buffer):
self.fname = fname
self.mode = mode
self.channels = channels
self.rate = rate
self.frames_per_buffer = frames_per_buffer
self._pa = pyaudio.PyAudio()
self.wavefile = self._prepare_file(self.fname, self.mode)
self._stream = None
def __enter__(self):
return self
def __exit__(self, exception, value, traceback):
self.close()
def record(self, duration):
# Use a stream with no callback function in blocking mode
self._stream = self._pa.open(format=pyaudio.paInt16,
channels=self.channels,
rate=self.rate,
input=True,
frames_per_buffer=self.frames_per_buffer)
for _ in range(int(self.rate / self.frames_per_buffer * duration)):
audio = self._stream.read(self.frames_per_buffer)
self.wavefile.writeframes(audio)
return None
def start_recording(self):
# Use a stream with a callback in non-blocking mode
self._stream = self._pa.open(format=pyaudio.paInt16,
channels=self.channels,
rate=self.rate,
input=True,
frames_per_buffer=self.frames_per_buffer,
stream_callback=self.get_callback())
self._stream.start_stream()
return self
def stop_recording(self):
self._stream.stop_stream()
return self
def get_callback(self):
def callback(in_data, frame_count, time_info, status):
self.wavefile.writeframes(in_data)
return in_data, pyaudio.paContinue
return callback
def close(self):
self._stream.close()
self._pa.terminate()
self.wavefile.close()
def _prepare_file(self, fname, mode='wb'):
wavefile = wave.open(fname, mode)
wavefile.setnchannels(self.channels)
wavefile.setsampwidth(self._pa.get_sample_size(pyaudio.paInt16))
wavefile.setframerate(self.rate)
return wavefile
@maelfosso

This comment has been minimized.

Copy link

@maelfosso maelfosso commented Feb 21, 2017

Hi,
How could I use this code to send sound to the server as It is recorded that is in real time instead of save it before send the whole file ?

@nngogol

This comment has been minimized.

Copy link

@nngogol nngogol commented Feb 21, 2018

Works Great!

@NescobarAlopLop

This comment has been minimized.

Copy link

@NescobarAlopLop NescobarAlopLop commented Apr 9, 2018

Hey,
Thank you ))

@agrawalhemant5393

This comment has been minimized.

Copy link

@agrawalhemant5393 agrawalhemant5393 commented May 5, 2018

Hi, I want to trigger event using GUI on button event. Can you help me how to acess.

@mave240

This comment has been minimized.

Copy link

@mave240 mave240 commented Aug 29, 2018

Hi, nice example. Is there a reason for the get_callback wrapper?

@loveAlakazam

This comment has been minimized.

Copy link

@loveAlakazam loveAlakazam commented Sep 17, 2018

Your code is very helpful to me. Thanks :)

@cormacp

This comment has been minimized.

Copy link

@cormacp cormacp commented Feb 27, 2019

Excellent non-blocking example, really clean

@PelayoChoya

This comment has been minimized.

Copy link

@PelayoChoya PelayoChoya commented Jun 26, 2019

Congratulations! Very well written code

@chrisfraschetti

This comment has been minimized.

Copy link

@chrisfraschetti chrisfraschetti commented Aug 27, 2019

Hi @sloria

Nice library - do you mind supplying a license, either here in the comments here or on the file itself?

@sloria

This comment has been minimized.

Copy link
Owner Author

@sloria sloria commented Aug 27, 2019

@benoitvalery

This comment has been minimized.

Copy link

@benoitvalery benoitvalery commented Oct 14, 2019

Many thanks. Exactly what I was looking for. Non-blocking recording examples are hard to find.

@ivopisarovic

This comment has been minimized.

Copy link

@ivopisarovic ivopisarovic commented Nov 13, 2019

Great! Saved my life :)

@ofelix03

This comment has been minimized.

Copy link

@ofelix03 ofelix03 commented Feb 16, 2020

Thanks man. This is amazing. It's saved me from having to understanding PyAudio.

@sreya0299

This comment has been minimized.

Copy link

@sreya0299 sreya0299 commented Mar 7, 2020

Hi @sloria
Even after using this code I am getting errors related to ALSA lib. Please help

@benoitvalery

This comment has been minimized.

Copy link

@benoitvalery benoitvalery commented Mar 9, 2020

Hi @sreya0299, could you post more information about the errors you get ? A copy-paste to begin with ? At what line ? Do you use this exact code ?

@sreya0299

This comment has been minimized.

Copy link

@sreya0299 sreya0299 commented Mar 10, 2020

@williamhatcher

This comment has been minimized.

Copy link

@williamhatcher williamhatcher commented Apr 19, 2020

Great job!

@kepler62f

This comment has been minimized.

Copy link

@kepler62f kepler62f commented May 21, 2020

Hi, nice example. Is there a reason for the get_callback wrapper?

The actual callback method is defined outside of the start_recording method but within the RecordingFile class. A wrapper is required so that start_recording can reference the callback through "self" object.

@Alge

This comment has been minimized.

Copy link

@Alge Alge commented Jul 10, 2020

Thank you! does exactly what i need without me having to write a single line of code :D

@david-f-johnston-nuance

This comment has been minimized.

Copy link

@david-f-johnston-nuance david-f-johnston-nuance commented Jul 27, 2020

Hi, nice example. Is there a reason for the get_callback wrapper?

PyAudio callbacks cannot be class methods, and do not take a 'self' argument. The wrapper creates a Python closure. This binds the 'self' passed into the 'get_callback' method for use by the 'callback' function, which needs it to call 'self.wavefile.writeframes'.

@WalkerC7

This comment has been minimized.

Copy link

@WalkerC7 WalkerC7 commented Aug 12, 2020

I am looking for record multiple channels in to multiple .WAV, I can do that with numpy, specific select the rows.
However, I am not sure if I can apply non-blocking with that. as I am not able to using stream.read for non-blocking, right?

@lochbika

This comment has been minimized.

Copy link

@lochbika lochbika commented Sep 1, 2020

Thank you! This made it so much easier for me :) The only thing that I added is an additional argument called "device" to select the audio source.

@qkrwjdan

This comment has been minimized.

Copy link

@qkrwjdan qkrwjdan commented Oct 13, 2020

thanks to you i made my work too easily.
thank you very much!!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.