分段错误:在非阻塞模式下录制pyaudio

3

我一直在尝试使用pyaudio录制音频,直到输入流中遇到静音为止。但是在运行时出现了分段错误。我认为我的树莓派安装的pyaudio/portaudio没有任何问题,因为当我尝试运行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

这些实际上是我在互联网某处找到的代码的改编。我仔细检查了我的设备索引和采样率,没有问题。有人能帮我整理一下吗?完整的代码在这里

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

我不知道,可能只是pyaudio和使用pyaudio的所有库(如python sounddevice)中的一个bug。因为我尝试了使用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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接