instalar grabar examples con como python audio pyaudio

python - grabar - Entrada de PyAudio desbordada



pyaudio record (8)

Mi otra respuesta resolvió el problema en la mayoría de los casos. Sin embargo, a veces el error todavía ocurre.

Esa fue la razón por la que deseché pyaudio y cambié a pyalsaaudio. My Raspy ahora graba suavemente cualquier sonido.

import alsaaudio import numpy as np import array # constants CHANNELS = 1 INFORMAT = alsaaudio.PCM_FORMAT_FLOAT_LE RATE = 44100 FRAMESIZE = 1024 # set up audio input recorder=alsaaudio.PCM(type=alsaaudio.PCM_CAPTURE) recorder.setchannels(CHANNELS) recorder.setrate(RATE) recorder.setformat(INFORMAT) recorder.setperiodsize(FRAMESIZE) buffer = array.array(''f'') while <some condition>: buffer.fromstring(recorder.read()[1]) data = np.array(buffer, dtype=''f'')

Estoy tratando de hacer un sonido de trazado en tiempo real en Python. Necesito obtener trozos de mi micrófono.

Usando PyAudio, intente usar

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" all = [] for i in range(0, RATE / chunk * RECORD_SECONDS): data = stream.read(chunk) all.append(data) print "* done recording" stream.close() p.terminate()

Después, obtengo el siguiente error:

* recording Traceback (most recent call last): File "gg.py", line 23, in <module> data = stream.read(chunk) File "/usr/lib64/python2.7/site-packages/pyaudio.py", line 564, in read return pa.read_stream(self._stream, num_frames) IOError: [Errno Input overflowed] -9981

No puedo entender este buffer. Quiero usar el bloqueo del modo IO, por lo tanto, si los fragmentos no están disponibles, quiero esperar a esos fragmentos. Pero cuando intento try except segment o sleep (0.1), oigo clics, por lo que esto no es lo que quiero.

Por favor, sugiero la mejor solución para mi ploblem?


Obtuve el mismo error cuando ejecuté su código. Miré la frecuencia de muestreo predeterminada de mi dispositivo de audio predeterminado, el micrófono interno de mi macbook, era 48000Hz no 44100Hz.

p.get_device_info_by_index(0)[''defaultSampleRate''] Out[12]: 48000.0

Cuando cambié la VELOCIDAD a este valor, funcionó.


Parece que mucha gente está encontrando este problema. Cavé un poco en él y creo que significa que entre la llamada anterior a stream.read() y esta llamada actual, los datos de la transmisión se perdieron (es decir, el buffer se llenó más rápido de lo que lo borraste).

Del doc para Pa_ReadStream() (la función stream.read() que stream.read() eventualmente termina llamando):

@return On success PaNoError will be returned, or PaInputOverflowed if input data was discarded by PortAudio after the previous call and before this call.

( PaInputOverflowed causa un IOError en la envoltura de pyaudio).

Si está bien que no capture cada fotograma, puede ignorar este error. Si es absolutamente crítico para ti tener cada cuadro, entonces necesitarás encontrar una manera de aumentar la prioridad de tu aplicación. No estoy lo suficientemente familiarizado con Python como para saber una manera pitónica de hacerlo, pero vale la pena intentar con un simple comando nice o cambiar la política de programación a SCHED_DEADLINE.

Editar:

Un problema ahora es que cuando se lanza IOError, pierdes todos los fotogramas recopilados en esa llamada. Para ignorar el desbordamiento y simplemente devolver lo que tenemos, puedes aplicar el siguiente parche, lo que hará que stream.read () ignore el subdesbordamiento de la salida y los errores de desbordamiento de entrada desde PortAudio (pero aún arrojará algo si se produce un error diferente). Una mejor manera sería personalizar este comportamiento (throw / no throw) dependiendo de sus necesidades.

diff --git a/src/_portaudiomodule.c b/src/_portaudiomodule.c index a8f053d..0878e74 100644 --- a/src/_portaudiomodule.c +++ b/src/_portaudiomodule.c @@ -2484,15 +2484,15 @@ pa_read_stream(PyObject *self, PyObject *args) } else { /* clean up */ _cleanup_Stream_object(streamObject); + + /* free the string buffer */ + Py_XDECREF(rv); + + PyErr_SetObject(PyExc_IOError, + Py_BuildValue("(s,i)", + Pa_GetErrorText(err), err)); + return NULL; } - - /* free the string buffer */ - Py_XDECREF(rv); - - PyErr_SetObject(PyExc_IOError, - Py_BuildValue("(s,i)", - Pa_GetErrorText(err), err)); - return NULL; } return rv;


Trabajé esto en OS X 10.10, obtuve el mismo error al intentar obtener audio del micrófono en una tarjeta USB SYBA (conjunto de chips C Media), y procesarlo en tiempo real con FFT''s y más:

IOError: [Errno Input overflowed] -9981

El desbordamiento se resolvió completamente al usar un Modo de devolución de llamada, en lugar del Modo de bloqueo, tal como lo escribió libbkmz. ( https://www.python.org/dev/peps/pep-0263/ )

Basado en eso, el bit del código de trabajo se veía así:

""" Creating the audio stream from our mic """ rate=48000 self.chunk=2**12 width = 2 p = pyaudio.PyAudio() # callback function to stream audio, another thread. def callback(in_data,frame_count, time_info, status): self.audio = numpy.fromstring(in_data,dtype=numpy.int16) return (self.audio, pyaudio.paContinue) #create a pyaudio object self.inStream = p.open(format = p.get_format_from_width(width, unsigned=False), channels=1, rate=rate, input=True, frames_per_buffer=self.chunk, stream_callback = callback) """ Setting up the array that will handle the timeseries of audio data from our input """ self.audio = numpy.empty((self.buffersize),dtype="int16") self.inStream.start_stream() while True: try: self.ANY_FUNCTION() #any function to run parallel to the audio thread, running forever, until ctrl+C is pressed. except KeyboardInterrupt: self.inStream.stop_stream() self.inStream.close() p.terminate() print("* Killed Process") quit()

Este código creará una función de devolución de llamada, luego creará un objeto de transmisión, lo iniciará y luego repetirá cualquier función. Una secuencia separada transmite audio, y esa secuencia se cierra cuando se detiene el ciclo principal. self.audio se usa en cualquier función. También tuve problemas con el hilo que se ejecuta para siempre si no se termina.

Como Pyaudio ejecuta esta secuencia en una secuencia separada, y esto hizo que la secuencia de audio sea estable, el modo de Bloqueo pudo haber estado saturando según la velocidad o el tiempo del resto de los procesos en la secuencia de comandos.

Tenga en cuenta que el tamaño del fragmento es 2 ^ 12, pero los trozos más pequeños funcionan igual de bien. Hay otros parámetros que consideré y con los que jugué para asegurarme de que todos tuvieran sentido:

  • Tamaño del trozo más grande o más pequeño (sin efecto)
  • Número y formato de bits para las palabras en el búfer, firmado 16 bits en este caso.
  • firmado de variables (probado con patrones de saturación sin signo y obtenido)
  • Naturaleza de la entrada de micrófono, y selección como predeterminada en el sistema, ganancia, etc.

Espero que funcione para alguien!


Tuve el mismo problema en la pi de frambuesa realmente lenta, pero pude resolverla ( en la mayoría de los casos ) utilizando el módulo de array más rápido para almacenar los datos.

import array import pyaudio FORMAT = pyaudio.paInt16 CHANNELS = 1 INPUT_CHANNEL=2 RATE = 48000 CHUNK = 512 p = pyaudio.PyAudio() stream = p.open(format=FORMAT, channels=CHANNELS, rate=RATE, input=INPUT_CHANNEL, frames_per_buffer =CHUNK) print("* recording") try: data = array.array(''h'') for i in range(0, int(RATE / CHUNK * RECORD_SECONDS)): data.fromstring(stream.read(CHUNK)) finally: stream.stop_stream() stream.close() p.terminate() print("* done recording")

El contenido de los data es más bien binario después. Pero puedes usar numpy.array(data, dtype=''i'') para obtener una matriz nuper de intergers.


para mí esto ayudó: https://.com/a/46787874/5047984

Usé multiprocesamiento para escribir el archivo en paralelo a la grabación de audio. Este es mi código:

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/"


pyaudio.Stream.read() tiene un parámetro de palabra clave exception_on_overflow , establezca esto en False.

Para su código de muestra que se vería así:

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" all = [] for i in range(0, RATE / chunk * RECORD_SECONDS): data = stream.read(chunk, exception_on_overflow = False) all.append(data) print "* done recording" stream.close() p.terminate()

Consulte la documentación de PyAudio para más detalles.


FORMAT = pyaudio.paInt16

Asegúrese de establecer el formato correcto, mi micrófono interno se configuró en 24 bits (consulte la aplicación Audio-Midi-Setup).