分段故障:在无阻塞模式下进行pyaudio录制

时间:2018-04-04 15:28:13

标签: python python-3.x segmentation-fault pyaudio portaudio

我一直在尝试使用pyaudio录制音频,直到输入流中遇到静音。但运行时出现分段错误。我认为在我的树莓中安装pyaudio / portaudio有什么不对pi因为当我试图在pyaudio docs中运行示例时,pyaudio正常工作它没有任何问题。我试图用pdb调试它 gdb是结果:

    Recording: Setting up

    Thread 1 "python" received signal SIGSEGV, Segmentation fault.
    0x7652a298 in ?? ()
    from /usr/lib/python2.7/dist-packages/_portaudio.arm-linux-     gnueabihf.so
    (gdb) backtrace
    #0  0x7652a298 in ?? ()
     from /usr/lib/python2.7/dist-packages/_portaudio.arm-linux-  gnueabihf.so
     #1  0x764f47b0 in Pa_GetDeviceInfo ()
     from /usr/lib/arm-linux-gnueabihf/libportaudio.so.2
     #2  0x7effe2c4 in ?? ()
     Backtrace stopped: previous frame identical to this frame (corrupt   stack?)
     (gdb) 

pyaudio回调函数

def _callback(self, in_data, frame_count, time_info, status):  # pylint: disable=unused-argument

    debug = logging.getLogger('alexapi').getEffectiveLevel() == logging.DEBUG

    if not in_data:
        self._queue.put(False)
        return None, pyaudio.paAbort

    do_VAD = True
    if self._callback_data['force_record'] and not self._callback_data['force_record'][1]:
        do_VAD = False

    # do not count first 10 frames when doing VAD
    if do_VAD and (self._callback_data['frames'] < self._callback_data['throwaway_frames']):
        self._callback_data['frames'] += 1

    # now do VAD
    elif (self._callback_data['force_record'] and self._callback_data['force_record'][0]()) \
            or (do_VAD and (self._callback_data['thresholdSilenceMet'] is False)
                and ((time.time() - self._callback_data['start']) < self.MAX_RECORDING_LENGTH)):

        if do_VAD:

            if int(len(in_data) / 2) == self.VAD_PERIOD:
                isSpeech = self._vad.is_speech(in_data, self.VAD_SAMPLERATE)

                if not isSpeech:
                    self._callback_data['silenceRun'] += 1
                else:
                    self._callback_data['silenceRun'] = 0
                    self._callback_data['numSilenceRuns'] += 1

            # only count silence runs after the first one
            # (allow user to speak for total of max recording length if they haven't said anything yet)
            if (self._callback_data['numSilenceRuns'] != 0) \
                    and ((self._callback_data['silenceRun'] * self.VAD_FRAME_MS) > self.VAD_SILENCE_TIMEOUT):
                self._callback_data['thresholdSilenceMet'] = True

    else:
        self._queue.put(False)
        return None, pyaudio.paComplete

    self._queue.put(in_data)
    if debug:
        self._callback_data['audio'] += in_data

    return None, pyaudio.paContinue

pyaudio

def _callback(self, in_data, frame_count, time_info, status):  # pylint: disable=unused-argument

    debug = logging.getLogger('alexapi').getEffectiveLevel() == logging.DEBUG

    if not in_data:
        self._queue.put(False)
        return None, pyaudio.paAbort

    do_VAD = True
    if self._callback_data['force_record'] and not self._callback_data['force_record'][1]:
        do_VAD = False

    # do not count first 10 frames when doing VAD
    if do_VAD and (self._callback_data['frames'] < self._callback_data['throwaway_frames']):
        self._callback_data['frames'] += 1

    # now do VAD
    elif (self._callback_data['force_record'] and self._callback_data['force_record'][0]()) \
            or (do_VAD and (self._callback_data['thresholdSilenceMet'] is False)
                and ((time.time() - self._callback_data['start']) < self.MAX_RECORDING_LENGTH)):

        if do_VAD:

            if int(len(in_data) / 2) == self.VAD_PERIOD:
                isSpeech = self._vad.is_speech(in_data, self.VAD_SAMPLERATE)

                if not isSpeech:
                    self._callback_data['silenceRun'] += 1
                else:
                    self._callback_data['silenceRun'] = 0
                    self._callback_data['numSilenceRuns'] += 1

            # only count silence runs after the first one
            # (allow user to speak for total of max recording length if they haven't said anything yet)
            if (self._callback_data['numSilenceRuns'] != 0) \
                    and ((self._callback_data['silenceRun'] * self.VAD_FRAME_MS) > self.VAD_SILENCE_TIMEOUT):
                self._callback_data['thresholdSilenceMet'] = True

    else:
        self._queue.put(False)
        return None, pyaudio.paComplete

    self._queue.put(in_data)
    if debug:
        self._callback_data['audio'] += in_data

    return None, pyaudio.paContinue

这些实际上是我在互联网上找到的代码的改编。我仔细检查了我的设备索引和采样率它们没有任何问题 有人可以帮我解决一下吗? 完整代码为here

pdb结果

    > /usr/lib/python2.7/dist-packages/pyaudio.py(438)__init__()
   -> arguments['stream_callback'] = stream_callback
   (Pdb) step
    > /usr/lib/python2.7/dist-packages/pyaudio.py(441)__init__()
    -> self._stream = pa.open(**arguments)
   (Pdb) step
   Segmentation fault
    root@raspberrypi:/home/pi/Desktop# python -m pdb rp3test.py 

1 个答案:

答案 0 :(得分:0)

Idk可能只是pyaudio和everylibs中的一个错误,它使用了python声音设备等pyaudio。因为我用sounddevice库试了一下。最后使用了这段代码

def silence_listener(throwaway_frames,filename = "recording.wav"):
# Reenable reading microphone raw data
inp = alsaaudio.PCM(alsaaudio.PCM_CAPTURE, alsaaudio.PCM_NORMAL, alsa_card)
inp.setchannels(1)
inp.setrate(VAD_SAMPLERATE)
inp.setformat(alsaaudio.PCM_FORMAT_S16_LE)
inp.setperiodsize(VAD_PERIOD)
audio = ""


# Buffer as long as we haven't heard enough silence or the total size is within max size
thresholdSilenceMet = False
frames = 0
numSilenceRuns = 0
silenceRun = 0
start = time.time()

# do not count first 10 frames when doing VAD
while (frames < throwaway_frames): # VAD_THROWAWAY_FRAMES):
    l, data = inp.read()
    frames = frames + 1
    if l:
        audio += data
        isSpeech = vad.is_speech(data, VAD_SAMPLERATE)

# now do VAD
while (thresholdSilenceMet == False) and ((time.time() - start) < MAX_RECORDING_LENGTH):
    l, data = inp.read()
    if l:
        audio += data

        if (l == VAD_PERIOD):
            isSpeech = vad.is_speech(data, VAD_SAMPLERATE)

            if (isSpeech == False):
                silenceRun = silenceRun + 1
                #print "0"
            else:
                silenceRun = 0
                numSilenceRuns = numSilenceRuns + 1
                #print "1"

    # only count silence runs after the first one
    # (allow user to speak for total of max recording length if they haven't said anything yet)
    if (numSilenceRuns != 0) and ((silenceRun * VAD_FRAME_MS) > VAD_SILENCE_TIMEOUT):
        thresholdSilenceMet = True

if debug: print ("End recording")

rf = open(filename, 'w')
rf.write(audio)
rf.close()
inp.close()
return