繁体   English   中英

PyAudio响应式录音

[英]PyAudio Responsive Recording

我已经在PyAudio网站上看到了有关录制固定长度录音的录制教程,但是我想知道如何处理非固定录音? 基本上,我想创建按钮来开始和结束录制,但是我对此没有任何发现。 有什么想法,我不是在寻找替代库吗?

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

在该回调函数中,您检查例如一个布尔值,如果为true,则将传入缓冲区写入数据结构;为false时,则忽略传入缓冲区。 例如,可以通过单击按钮来设置此布尔值。

编辑:看一下有线音频的示例: 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_data只是获取一个元组一起返回pyaudio.paContinue 这意味着将来自输入设备的传入缓冲区放入/复制回发送给输出设备的输出缓冲区(它是同一设备,因此其实际将输入路由到输出线)。 有关更多说明,请参见api文档: http : //people.csail.mit.edu/hubert/pyaudio/docs/#pyaudio.PyAudio.open

因此,在此功能中,您可以执行以下操作(这是我编写的某些代码的一部分,但并不完整:我使用了一些未描述的功能。此外,我在一个通道上播放正弦波,而在另一通道上播放24bit格式的噪声。):


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_onTrueFalse ,从你的代码的另一部分,而流是开/运行,导致录制和播放启动或不中断数据流独立停止。 我将in_data复制到一个(线程安全的) queue ,该线程被另一个线程用来在其中写入磁盘,否则该队列将在一段时间后变大。

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

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()

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM