2012-05-24 10 views
21

मैं पाइथन में रीयल-टाइम प्लॉटिंग ध्वनि बनाने की कोशिश कर रहा हूं। मुझे अपने माइक्रोफोन से भाग लेने की जरूरत है।पायउडियो इनपुट अतिप्रवाह

PyAudio का उपयोग करना,

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() 

का उपयोग करने के बाद, मैं followin त्रुटि मिल रही है कोशिश:

* 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 

मैं इस बफर नहीं समझ सकता। मैं चाहता हूं कि ब्लॉकिंग आईओ मोड का उपयोग करें, इसलिए अगर भाग उपलब्ध नहीं हैं, तो मैं उन हिस्सों का इंतजार करना चाहता हूं। लेकिन जब मैं सेगमेंट या नींद (0.1) को छोड़कर कोशिश करता हूं, तो मैं क्लिक सुनता हूं, इसलिए यह वही नहीं है जो मैं चाहता हूं।

कृपया मेरे प्लोबलेम के लिए सबसे अच्छा समाधान सुझाएं?

+2

: यह मेरा कोड है। हो सकता है कि आप बफर में अधिक डेटा प्राप्त कर रहे हों, क्योंकि आप बाहर खींच रहे हैं क्योंकि चंक आकार इतना छोटा है कि पाइथन कोड नहीं रख रहा है। – Demolishun

+0

हाय। बस इस मुद्दे पर कोई अपडेट होने पर सोच रहा है? मुझे '[Errno इनपुट overflowed] -9981' त्रुटि मिल रही है। मैंने जिस प्रारूप का उपयोग कर रहा हूं, उसके लिए मैंने 'p.is_format_supported' सत्य किया है। –

उत्तर

8

जब मैं आपका कोड चलाता हूं तो मुझे वही त्रुटि मिलती है। मैंने अपने मैकबुक के आंतरिक माइक्रोफोन की डिफ़ॉल्ट ऑडियो डिवाइस की डिफ़ॉल्ट नमूना दर को देखा, यह 48000Hz 44100Hz नहीं था।

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

जब मैंने रेट को इस मूल्य में बदल दिया, तो यह काम किया।

+1

मुझे एक ही त्रुटि मिली, और आपका समाधान (48000 तक बढ़ रहा) काम किया। लेकिन मैं कोड समाप्त हो चुकी थी: यदि p.is_format_supported (44,100.0, # नमूना दर input_device = devinfo [ "अनुक्रमणिका"] input_channels, = devinfo [ 'maxInputChannels'], input_format = pyaudio.paInt16): प्रिंट 'आहा! ' ... और यह काम किया! इसलिए मैं उलझन में हूं कि समस्या क्या थी। कोई अंतर्दृष्टि? – user426364

+0

पोर्टौडियो को अपग्रेड करने का प्रयास करें, यह मेरे लिए कुछ दर समस्याएं तय करता है। मैंने "ब्रॉड इंस्टॉल पोर्टोडियो - हेड" का इस्तेमाल किया। – velotron

+0

यह मेरे लिए काम करता था, मुझे नहीं पता था कि साउंडकार्ड की डिफ़ॉल्ट नमूना दर 48khz थी, धन्यवाद! – Jeff

2
FORMAT = pyaudio.paInt16 

सही स्वरूप सेट करने के लिए सुनिश्चित करें, अपने आंतरिक माइक्रोफोन (ऑडियो-मिडी-सेटअप आवेदन देखें) 24 बिट करने के लिए स्थापित किया गया था।

5

ऐसा लगता है कि बहुत से लोग इस मुद्दे का सामना कर रहे हैं। मैंने इसमें थोड़ा सा खोला और मुझे लगता है कि इसका मतलब है कि पिछले कॉल के बीच stream.read() और इस वर्तमान कॉल के बीच, स्ट्रीम से डेटा खो गया था (यानी बफर इसे साफ़ करने से तेज़ी से भरा हुआ है)।

डॉक से Pa_ReadStream() के लिए (PortAudio समारोह है कि stream.read() अंत में बुला समाप्त होता है):

@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 तो pyaudio आवरण में एक IOError कारण बनता है)।

यदि आपके लिए प्रत्येक फ्रेम को कैप्चर नहीं करना ठीक है, तो आप इस त्रुटि को अनदेखा कर सकते हैं। यदि आपके पास हर फ्रेम के लिए यह बिल्कुल महत्वपूर्ण है, तो आपको अपने आवेदन की प्राथमिकता बढ़ाने के लिए एक रास्ता खोजना होगा। मैं पाइथन के साथ ऐसा करने के लिए एक पाइथोनिक तरीका जानने के लिए पर्याप्त परिचित नहीं हूं, लेकिन यह एक आसान nice कमांड की कोशिश करने के लायक है, या शेड्यूलिंग नीति को SCHED_DEADLINE में बदलना उचित है।

संपादित करें:

एक मुद्दा अभी है कि जब IOError फेंक दिया जाता है, आप सभी फ्रेम है कि कॉल में एकत्र खो देते हैं। इसके बजाय ओवरफ्लो को अनदेखा करें और हमारे पास जो भी है, उसे वापस लौटाएं, आप नीचे पैच को लागू कर सकते हैं, जिससे पोर्टऑडियो से आउटपुट अंडर्रोन और इनपुट ओवरफ्लो त्रुटियों को अनदेखा करने के लिए stream.read() का कारण बन जाएगा (लेकिन फिर भी एक अलग त्रुटि होने पर कुछ फेंक दें)। आपकी ज़रूरतों के आधार पर इस व्यवहार (फेंक/फेंक) अनुकूलन करने का एक बेहतर तरीका होगा।

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; 
3

मैंने ओएस एक्स 10 पर यह काम किया।का उपयोग करते समय

IOError: [Errno Input overflowed] -9981 

अतिप्रवाह पूरी तरह से हल किया गया था: 10, fft के और अधिक के साथ एक ही त्रुटि एक SYBA USB कार्ड (सी मीडिया चिपसेट) में माइक्रोफोन से ऑडियो पाने की कोशिश में है, और यह प्रक्रिया वास्तविक समय में मिल गया ।

""" 
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() 

इस कोड को एक कॉलबैक फ़ंक्शन पैदा करेगा: एक कॉलबैक मोड, अवरोधित करना मोड, के रूप में libbkmz द्वारा लिखित के बजाय (https://www.python.org/dev/peps/pep-0263/)

उस आधार पर, काम कर कोड के बिट इस तरह देखा , फिर एक स्ट्रीम ऑब्जेक्ट बनाएं, प्रारंभ करें यह और फिर किसी भी समारोह में पाश। एक अलग थ्रेड ऑडियो स्ट्रीम करता है, और मुख्य लूप बंद होने पर वह स्ट्रीम बंद होती है। self.audio किसी भी समारोह में प्रयोग किया जाता है। अगर समाप्त नहीं हुआ तो मुझे हमेशा के लिए चलने वाले थ्रेड के साथ समस्याएं भी थीं।

चूंकि प्यौडियो इस धारा को एक अलग थ्रेड में चलाता है, और इससे ऑडियो स्ट्रीम स्थिर हो जाती है, तो ब्लॉकिंग मोड स्क्रिप्ट में शेष प्रक्रियाओं की गति या समय के आधार पर संतृप्त हो सकता है।

ध्यान दें कि खंड आकार 2^12 है, लेकिन छोटे भाग भी काम करते हैं। अन्य पैरामीटर मैं माना और उनके द्वारा किए गए समझ बनाने के लिए के साथ चारों ओर खेला होते हैं:

  • हिस्सा आकार बड़ा या छोटा (कोई प्रभाव नहीं)
  • संख्या और बफर में शब्दों के लिए बिट्स के प्रारूप, 16 पर हस्ताक्षर किए इस मामले में थोड़ा सा।
  • चर के signedness (अहस्ताक्षरित साथ की कोशिश की और संतृप्ति पैटर्न मिल गया) प्रणाली में डिफ़ॉल्ट के रूप में
  • माइक इनपुट की प्रकृति, और चयन, आदि

आशा है कि किसी के लिए काम करता हासिल!

1

मैं वास्तव में धीमी गति से रास्पबेरी पाई पर एक ही मुद्दा था, लेकिन मैं इसे डेटा भंडारण के लिये तेजी से array मॉड्यूल का उपयोग करके (ज्यादातर मामलों के लिए) का समाधान करने में सक्षम था।

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

data की सामग्री बाद में बाइनरी है। लेकिन आप numpy.array(data, dtype='i') का उपयोग इंटरगर्स की एक संख्यात्मक सरणी प्राप्त करने के लिए कर सकते हैं।

1

मेरा other answer अधिकांश मामलों में समस्या हल हो गया। हालांकि कभी-कभी त्रुटि अभी भी होती है।

यही वजह है कि मैंने प्यूडियोज़ को तोड़ दिया और पायलसौडियो में स्विच किया। मेरा रस्सी अब आसानी से किसी भी ध्वनि रिकॉर्ड करता है।

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') 
10

pyaudio.Stream.read() कोई keyword पैरामीटर exception_on_overflow, गलत पर सेट है।

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() 

अधिक जानकारी के लिए PyAudio documentation देखें:

अपने नमूना कोड है कि कैसा दिखेगा के लिए

+4

मुझे मिलता है: TypeError: read() को एक अप्रत्याशित कीवर्ड तर्क 'upgrade_on_overflow' मिला –

0
मुझे इस के लिए

मदद की: https://stackoverflow.com/a/46787874/5047984

मैं बहु इस्तेमाल किया रिकॉर्डिंग ऑडियो के समानांतर में फ़ाइल लिखने के लिए। शायद आपके हिस्सा आकार बहुत छोटा है

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/" 
संबंधित मुद्दे