在callback mod中使用pyaudio时出现线程问题

2024-04-25 06:50:29 发布

您现在位置:Python中文网/ 问答频道 /正文

我使用pyaudio录制音频,然后将其分块处理(例如,每5秒一次)。我在回调模式下使用pyaudio,其中有一个回调函数,每录制1500个音频样本就调用该函数,在该函数中,这些样本被添加到队列中。我还保存样本到一个wav文件,因为他们正在被记录,只是为了验证他们是预期的。在

q = Queue.Queue()
flag = False
waveFile = wave.open('recording.wav', 'wb')
waveFile.setnchannels(1)
waveFile.setsampwidth(2)
waveFile.setframerate(RATE)


def callback(in_data, frame_count, time_info, status):
    silent = is_silent(in_data)
    if silent == False:
        numpydata = np.fromstring(in_data, dtype=np.int16)
        waveFile.writeframes(in_data)
        q.put(numpydata)
        callback_flag = pyaudio.paContinue

    elif silent == True and flag == True:
        numpydata = np.fromstring(in_data, dtype=np.int16)
        if len(numpydata) != 0:
            waveFile.writeframes(in_data)
            q.put(numpydata)
        waveFile.close()
        callback_flag = pyaudio.paComplete
    else:
        callback_flag = pyaudio.paContinue

    return (in_data, callback_flag)

p=pyaudio.PyAudio() # start the PyAudio class
stream=p.open(format=pyaudio.paInt16,channels=1,rate=RATE,input=True,frames_per_buffer=1500, stream_callback = callback) #uses default input device

一旦队列不再是空的,我就进入一个while循环,该循环将队列中的数据添加到一个单独的缓冲区,然后在添加5秒音频时处理该缓冲区中的数据。在

^{pr2}$

我的问题是,我注意到音频信号中奇怪的意外故障,就好像程序暂时停止录制几个样本,然后又重新启动一样。我可以通过在Audacity中打开录制的wav文件并放大信号来看到这一点。我认为这是因为pyaudio在一个单独的线程中为每1500个样本调用回调函数,有时它可能会尝试调用回调函数,但上一个回调函数的线程仍然处于打开状态,该回调函数尚未完成,数据仍在添加到队列中等等(如果这是解释不连贯,我不太清楚该用什么术语)。在

有人知道我怎么解决这个问题吗?有没有一种方法可以同步它,使每个回调函数只在前一个回调函数完成处理后才被调用?在


Tags: 函数intruedata队列npcallback音频
1条回答
网友
1楼 · 发布于 2024-04-25 06:50:29

在回调函数中应该非常小心。最值得注意的是,你不应该读写其中的文件。 您提到您只为调试而编写文件,但这实际上可能会导致问题。在

另外,您应该始终检查回调函数的status参数。这会告诉你是否有超支或不足。 如果遇到超限或欠载,可以尝试增加块大小(和延迟),直到它们消失。在

下面是我制作的一个示例脚本,它记录到一个声音文件中:rec_unlimited.py。 下面是一个绘制输入信号的例子:plot_input.py。您可以将其调整为执行任何其他处理而不是打印。在

Is there a way of synchronizing it so that each callback function will only be called after the previous callback function has finished processing?

实际上已经是这样了,对回调函数的调用永远不会重叠。但是,如果一次调用回调函数的时间太长,那么将生成的输出数据发送到声卡就太晚了,并且必须丢弃这些音频数据,从而导致音频丢失。这被称为“输出不足”。 如果前一次调用回调函数花费的时间太长,那么将有太多可用的音频输入数据,其中一些数据将不得不丢弃,再次导致退出。这称为“输入溢出”。在

相关问题 更多 >