Python 音频响应录音
我在PyAudio网站上看到了录制固定长度录音的教程,但我想知道如何在非固定录音中也能做到这一点?基本上,我想创建开始和结束录音的按钮,但我还没有找到任何相关的东西。有什么想法吗?我不是在寻找替代库?最好的方法是使用非阻塞的录制方式,即您提供一个回调函数,从启动流的那一刻起就被调用,并且在停止流之前,每个处理的块/缓冲区都会被调用 例如,在该回调函数中,检查布尔值,如果为true,则将传入缓冲区写入数据结构,如果为false,则忽略传入缓冲区。例如,可以通过单击按钮来设置此布尔值 编辑:查看wire audio的示例: 流是用一个参数打开的Python 音频响应录音,python,user-interface,asynchronous,nonblocking,pyaudio,Python,User Interface,Asynchronous,Nonblocking,Pyaudio,我在PyAudio网站上看到了录制固定长度录音的教程,但我想知道如何在非固定录音中也能做到这一点?基本上,我想创建开始和结束录音的按钮,但我还没有找到任何相关的东西。有什么想法吗?我不是在寻找替代库?最好的方法是使用非阻塞的录制方式,即您提供一个回调函数,从启动流的那一刻起就被调用,并且在停止流之前,每个处理的块/缓冲区都会被调用 例如,在该回调函数中,检查布尔值,如果为true,则将传入缓冲区写入数据结构,如果为false,则忽略传入缓冲区。例如,可以通过单击按钮来设置此布尔值 编辑:查看wi
stream_callback=my_callback
其中my_回调是一个声明为
def my_callback(in_data, frame_count, time_info, status)
每当有新的缓冲区可用时,就会调用此函数<代码>输入数据包含要记录的输入。在本例中,In_data
与pyaudio.paContinue
一起以元组形式返回。这意味着输入设备的输入缓冲区被放入/复制回输出设备发送的输出缓冲区(它是同一个设备,所以它实际上将输入路由到输出线)。有关更多说明,请参阅api文档:
因此,在这个函数中,您可以执行以下操作(这是从我编写的一些代码中提取的,但并不完整:我使用了一些未描述的函数。此外,我在一个通道上播放正弦波,在另一个通道上以24位格式播放噪波):
然后,您可以在流打开/运行时,从代码的另一部分将record\u on
和playback\u on
设置为True
或False
,从而在不中断流的情况下独立启动或停止录制和播放。
我将in_data
复制到(threadsafe)队列
中,另一个线程使用该队列写入那里的磁盘,否则队列将在一段时间后变大
顺便说一句:pyaudio是基于portaudio的,它有更多的文档和有用的提示。例如():回调函数必须在显示新缓冲区之前完成,否则缓冲区将丢失。因此,在回调函数中写入文件通常不是一个好主意。(虽然写入文件会被缓冲,我不知道它最终写入磁盘时是否会阻塞)我不明白。你能进一步解释这个方法吗?我对C或C++不太熟悉。你真的能解释一些Python吗?这可能更简单吗?据我所知,不太简单。您可以使用非回调(阻塞)版本,但如果您不希望代码的其余部分冻结,则必须将其放在单独的线程中,这可能更复杂。回调版本也是与实时IO设备交互的标准方式。IO设备会导致操作系统/驱动程序中断,从而触发某些函数被调用(回调),对于最简单的情况,阻塞工作方式只是在此基础上构建的一种方便。这就是我用来模拟按钮按下的方式。见下文。
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
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()