2

I am trying to execute a PyAudio python capturing program on Rasbian in my RaspberryPi model B board, but getting error:

Traceback (most recent call last):
  File "/home/pi/pythonsound/record.py", line 35, in <module>
    data = stream.read(CHUNK)
  File "/usr/local/lib/python2.7/dist-packages/pyaudio.py", line 605, in read
    return pa.read_stream(self._stream, num_frames)
IOError: [Errno Input overflowed] -9981

There are some other suggestions available but not effective Here is what I've tried, This is the code

import pyaudio
import wave
import sys
CHUNK = 1024
FORMAT = pyaudio.paInt16
CHANNELS = 1
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 my USB Audio Card device info,

{'defaultSampleRate': 44100.0, 
'defaultLowOutputLatency': 0.011609977324263039, 
'defaultLowInputLatency': 0.011609977324263039, 
'maxInputChannels': 1L, 
'structVersion': 2L, 
'hostApi': 0L, 
'index': 0, 
'defaultHighOutputLatency': 0.046439909297052155, 
'maxOutputChannels': 2L, 
'name': u
'USB PnP Sound Device: USB Audio (hw:0,0)', 
'defaultHighInputLatency': 0.046439909297052155}

can you please guide me resolve this problem?

Gajanan Kulkarni
  • 697
  • 6
  • 22
Fahadkalis
  • 2,971
  • 8
  • 23
  • 40
  • 4
    Typically, an input overflow means that data is arriving faster than that computers ability to read the data. Can you tell if you have received any data? – HeatfanJohn Jan 27 '15 at 16:28
  • 1
    @HeatfanJohn On command Terminal it is receiving audio input from this command `arecord -D plug:default -f S16_LE -c 1 -r 16000 -d 300 a.wav` – Fahadkalis Jan 27 '15 at 16:32
  • @HeatfanJohn How do i know on python that it is really receiving data or not, although it shows above error – Fahadkalis Jan 27 '15 at 16:34
  • 2
    Maybe add a `print i` prior to the `data = stream` line in the python script. – HeatfanJohn Jan 27 '15 at 17:05
  • 1
    @HeatfanJohn I got this output when I add `print i` line before `data=stream` in the python script `* recording 0 1 Traceback (most recent call last): File "/home/pi/pythonsound/myaudio01JAN27.py", line 25, in data = stream.read(CHUNK) File "/usr/local/lib/python2.7/dist-packages/pyaudio.py", line 605, in read return pa.read_stream(self._stream, num_frames) IOError: [Errno Input overflowed] -9981` – Fahadkalis Jan 27 '15 at 17:13

3 Answers3

4

After reading different users experience and their of correction with just changing the value of parameters.

As an expert describe above, the actual reason of

IOError: [Errno Input overflowed] -9981

so I also start increasing the value of CHUNK and at last I also get success over this error. And now my coding after correction is:

import pyaudio, wave, time, sys
from datetime import datetime

CHUNK = 8192
FORMAT = pyaudio.paInt16
CHANNELS = 1
RATE = 44100
RECORD_SECONDS = 5

current_time = str(datetime.now())  #"Date/Time for File Name"
current_time = "_".join(current_time.split()).replace(":","-")
current_time = current_time[:-7]
WAVE_OUTPUT_FILENAME = 'Audio_'+current_time+'.wav'

p = pyaudio.PyAudio()

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

print("* recording")

frames = []
for i in range(0, int(RATE / CHUNK * RECORD_SECONDS)):
    print i
    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()
Fahadkalis
  • 2,971
  • 8
  • 23
  • 40
0

I had the same issue and tried to change the chunk size and sampling rate without success. By using multiprocessing the issue was resolved. Here is my code:

recordAudioSamples.py

import pyaudio
import wave
import datetime
import signal
import ftplib
import sys
import os

# configuration for assos_listen
import config


# run the audio capture and send sound sample processes
# in parallel
from multiprocessing import Process

# CONFIG
CHUNK = config.chunkSize
FORMAT = pyaudio.paInt16
CHANNELS = 1
RATE = config.samplingRate
RECORD_SECONDS = config.sampleLength

# HELPER FUNCTIONS

# write to ftp
def uploadFile(filename):

    print("start uploading file: " + filename)
    # connect to container
    ftp = ftplib.FTP(config.ftp_server_ip, config.username, config.password)

    # write file
    ftp.storbinary('STOR '+filename, open(filename, 'rb'))
    # close connection
    ftp.quit()
    print("finished uploading: " +filename)


# write to sd-card
def storeFile(filename,frames):

    print("start writing file: " + filename)
    wf = wave.open(filename, 'wb')
    wf.setnchannels(CHANNELS)
    wf.setsampwidth(p.get_sample_size(FORMAT))
    wf.setframerate(RATE)
    wf.writeframes(b''.join(frames))
    wf.close()
    print(filename + " written")


# abort the sampling process
def signal_handler(signal, frame):
    print('You pressed Ctrl+C!')

    # close stream and pyAudio
    stream.stop_stream()
    stream.close()
    p.terminate()

    sys.exit(0)

# MAIN FUNCTION
def recordAudio(p, stream):

    sampleNumber = 0
    while (True):
        print("*  recording")
        sampleNumber = sampleNumber +1

        frames = []
        startDateTimeStr = datetime.datetime.now().strftime("%Y_%m_%d_%I_%M_%S_%f")
        for i in range(0, int(RATE / CHUNK * RECORD_SECONDS)):
            data = stream.read(CHUNK)
            frames.append(data)

        fileName =  str(config.sensorID) + "_" + startDateTimeStr + ".wav"

        # create a store process to write the file in parallel
        storeProcess = Process(target=storeFile, args=(fileName,frames))
        storeProcess.start()

        if (config.upload == True):
            # since waiting for the upload to finish will take some time
            # and we do not want to have gaps in our sample
            # we start the upload process in parallel
            print("start uploading...")
            uploadProcess = Process(target=uploadFile, args=(fileName,))
            uploadProcess.start()



# ENTRYPOINT FROM CONSOLE
if __name__ == '__main__':

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


    # directory to write and read files from
    os.chdir(config.storagePath)

    # abort by pressing C
    signal.signal(signal.SIGINT, signal_handler)
    print('\n\n--------------------------\npress Ctrl+C to stop the recording')

    # start recording
    recordAudio(p, stream)

config.py

### configuration file for assos_listen
# upload
upload = False

# config for this sensor
sensorID = "al_01"

# sampling rate & chunk size
chunkSize = 8192
samplingRate = 44100 # 44100 needed for Aves sampling
# choices=[4000, 8000, 16000, 32000, 44100] :: default 16000

# sample length in seconds
sampleLength = 10

# configuration for assos_store container
ftp_server_ip = "192.168.0.157"
username = "sensor"
password = "sensor"

# storage on assos_listen device
storagePath = "/home/pi/assos_listen_pi/storage/"
gannebamm
  • 1
  • 2
0

I had the same issue when running in an interactive environment (Jupyter Notebook) and for me it ended up being caused by the buffer not being cleared between runs of the code. Notice that the for loop has the possibility of leaving a chunk unread, depending on the values of RATE, CHUNK, RECORD_SECONDS. Run this snippet to see:

CHUNK = 1024
RATE = 44100
RECORD_SECONDS = 5
count = RATE * RECORD_SECONDS
for i in range(0, int(RATE / CHUNK * RECORD_SECONDS)):
    count = count - CHUNK
    print("Buffer unread count:", count)`

This results in 340 samples still in the buffer. I think this causes the buffer overrun error the next time the code is executed. I experimented with multiple runs and ratios of RATE/CHUNK right below 1.0 and right above 1.0 and it's not clear to me what conditions trigger an overrun error. Overruns occurred for me when I ran a ratio a little less than one (48000/4799) followed by a ratio a little greater than one (48000/4801) at 3 second samples. It seems to be a cumulative effect of the runs leaving data in the buffer which at some point triggers the overrun condition.

For the fix I ended up using a CHUNK that is an even multiple of the sampling frequency (like 4800 for 48000kHz) and recordings an integer number of seconds long so that no data was left in the buffer.

filipmu
  • 66
  • 3