【问题标题】:PyAudio Responsive RecordingPyAudio 响应式录音
【发布时间】:2015-04-09 15:54:06
【问题描述】:

我在 PyAudio 网站上看到了录制固定长度录音的录音教程,但我想知道如何对非固定录音做同样的事情?基本上,我想创建按钮来开始和结束录制,但我还没有找到任何关于此事的信息。有什么想法,我不是在寻找替代库吗?

【问题讨论】:

    标签: python user-interface asynchronous nonblocking pyaudio


    【解决方案1】:

    最好是使用非阻塞的记录方式,即你提供一个回调函数,从你启动流的那一刻起就被调用,并为每个被处理的块/缓冲区持续调用,直到你停止流。

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

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

    stream_callback=my_callback
    

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

    def my_callback(in_data, frame_count, time_info, status)
    

    每次有新缓冲区可用时都会调用此函数。 in_data 包含您要记录的输入。在此示例中,in_datapyaudio.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
    

    然后,您可以在流打开/运行时从代码的另一部分将record_onplayback_on 设置为TrueFalse,从而在不中断流的情况下独立开始或停止录制和播放。 我将in_data 复制到(线程安全)queue 中,另一个线程使用该queue 写入磁盘,否则队列会在一段时间后变大。

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

    【讨论】:

    • 我没有关注你。你能进一步解释一下这个方法吗?
    • 我不熟悉 C 或 C++。你能解释一下 Python 吗?
    • 这可能更简单吗?
    • 据我所知不是真的。您可以使用非回调(阻塞)版本,但如果您不希望其余代码冻结,则必须将其放在单独的线程中,这可能更复杂。回调版本也是与实时 IO 设备交互的标准方式。 IO 设备会导致操作系统/驱动程序中断,从而触发某些函数被调用(回调),阻塞的工作方式只是在此基础上构建的一种便利,用于最简单的情况。
    • 这就是我用来模拟按钮按下的方法。见下文。
    【解决方案2】:
    import pyaudio
    import wave
    
    import pygame, sys
    from pygame.locals import *
    
    pygame.init()
    scr = pygame.display.set_mode((640, 480))
    recording = True
    
    CHUNK = 1024
    FORMAT = pyaudio.paInt16
    CHANNELS = 2
    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")
    
    frames = []
    
    while True:
        if recording:
            data = stream.read(CHUNK)
            frames.append(data)
    
        for event in pygame.event.get():
            if event.type == KEYDOWN and recording:
                print("* done recording")
    
                stream.stop_stream()
                stream.close()
                p.terminate()
    
                wf = wave.open(WAVE_OUTPUT_FILENAME, 'wb')
                wf.setnchannels(CHANNELS)
                wf.setsampwidth(p.get_sample_size(FORMAT))
                wf.setframerate(RATE)
                wf.writeframes(b''.join(frames))
                wf.close()
                recording = False
    
            if event.type == QUIT:
                pygame.quit(); sys.exit()
    

    【讨论】:

      猜你喜欢
      • 2020-12-19
      • 2015-12-05
      • 2016-02-23
      • 2016-06-30
      • 1970-01-01
      • 2012-10-11
      • 1970-01-01
      • 2019-08-01
      • 2020-09-14
      相关资源
      最近更新 更多