簡體   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