PyAudio响应录音

Mal*_*imi 2 python user-interface asynchronous nonblocking pyaudio

我在PyAudio网站上看到了录制固定长度录音的录音教程,但是我想知道如何用非固定录音做同样的事情?基本上,我想创建按钮来开始和结束录制,但我没有找到任何关于此事的内容.任何想法,我不是在寻找替代图书馆?

Emi*_*ags 6

最好的方法是使用非阻塞的记录方式,即提供一个回调函数,该函数从您启动流的那一刻开始调用,并且在您停止流之前不断调用每个被处理的块/缓冲区.

在该回调函数中,例如,检查布尔值,当它为真时,将传入缓冲区写入数据结构,当它为假时,忽略传入缓冲区.例如,可以通过单击按钮来设置此布尔值.

编辑:看一下有线音频的例子:http://people.csail.mit.edu/hubert/pyaudio/#wire-callback-example 用一个参数打开流

stream_callback=my_callback
Run Code Online (Sandbox Code Playgroud)

其中my_callback是声明为的常规函数

def my_callback(in_data, frame_count, time_info, status)
Run Code Online (Sandbox Code Playgroud)

每次有新缓冲区可用时,都会调用此函数.in_data包含您要记录的输入.在这个例子中,in_data只是与元组一起返回pyaudio.paContinue.这意味着来自输入设备的传入缓冲区被放入/复制回输出缓冲区发送到输出设备(其设备相同,因此其实际路由输入到输出也称为线路).有关更多解释,请参阅api文档:http://people.csail.mit.edu/hubert/pyaudio/docs/#pyaudio.PyAudio.open

所以在这个函数中你可以做类似的事情(这是我编写的一些代码的摘录,这些代码并不完整:我使用了一些未描述的函数.另外我在一个通道上播放正弦波,另一个以24位格式播放噪声.):


record_on = False
playback_on = False

recorded_frames = queue.Queue()

def callback_play_sine(in_data, frame_count, time_info, status):
    if record_on:
        global recorded_frames
        recorded_frames.put(in_data)

    if playback_on:
        left_channel_data = mysine.next_block(frame_count) * MAX_INT24 * gain
        right_channel_data = ((np.random.rand(frame_count) * 2) - 1) * MAX_INT24 * gain
        data = interleave_channels(max_nr_of_channels, (left_output_channel, left_channel_data), (right_output_channel, right_channel_data))
        data = convert_int32_to_24bit_bytestream(data)
    else:
        data = np.zeros(frame_count*max_nr_of_channels).tostring()

    if stop_callback:
        callback_flag = pyaudio.paComplete
    else:
        callback_flag = pyaudio.paContinue

    return data, callback_flag
Run Code Online (Sandbox Code Playgroud)

然后,您可以设置record_onplayback_onTrueFalse从你的代码的另一部分,而流开启/运行,导致录制和播放启动或不中断数据流独立停止.我复制了in_data一个(threadsafe)queue,另一个线程使用它来写入磁盘,否则队列会在一段时间后变大.

BTW:pyaudio基于portaudio,它有更多的文档和有用的提示.例如(http://portaudio.com/docs/v19-doxydocs/writing_a_callback.html):回调函数必须在呈现新缓冲区之前完成,否则缓冲区将丢失.因此,写回调函数内的文件通常不是一个好主意.(虽然写入文件得到缓冲,但我不知道它最终是否会在写入磁盘时阻塞)