捕捉音频 - 树莓派
在本节课程中,您将编写代码在树莓派上捕捉音频。音频捕捉将通过一个按钮来控制。
硬件
树莓派需要一个按钮来控制音频捕捉。
您将使用的是一个 Grove 按钮。这是一个数字传感器,可以打开或关闭信号。这些按钮可以配置为在按下时发送高信号,未按下时发送低信号,或者按下时发送低信号,未按下时发送高信号。
如果您使用的是 ReSpeaker 2-Mics Pi HAT 作为麦克风,那么无需连接按钮,因为这个 HAT 已经自带一个按钮。直接跳到下一节。
连接按钮
按钮可以连接到 Grove 基座 HAT。
任务 - 连接按钮

将 Grove 电缆的一端插入按钮模块上的插座。它只能以一种方式插入。
在树莓派断电的情况下,将 Grove 电缆的另一端连接到 Grove 基座 HAT 上标记为 D5 的数字插座。这个插座位于 GPIO 引脚旁边的一排插座中,从左数第二个。

捕捉音频
您可以使用 Python 代码从麦克风捕捉音频。
任务 - 捕捉音频
启动树莓派并等待其启动完成。
启动 VS Code,可以直接在树莓派上运行,也可以通过 Remote SSH 扩展连接。
PyAudio Pip 包提供了录制和回放音频的功能。此包依赖于一些需要先安装的音频库。在终端中运行以下命令来安装这些库:
shsudo apt update sudo apt install libportaudio0 libportaudio2 libportaudiocpp0 portaudio19-dev libasound2-plugins --yes安装 PyAudio Pip 包。
shpip3 install pyaudio创建一个名为
smart-timer的新文件夹,并在此文件夹中添加一个名为app.py的文件。在文件顶部添加以下导入:
pythonimport io import pyaudio import time import wave from grove.factory import Factory这将导入
pyaudio模块、一些用于处理 WAV 文件的标准 Python 模块,以及grove.factory模块以导入用于创建按钮类的Factory。在此之后,添加代码以创建一个 Grove 按钮。
如果您使用的是 ReSpeaker 2-Mics Pi HAT,请使用以下代码:
python# The button on the ReSpeaker 2-Mics Pi HAT button = Factory.getButton("GPIO-LOW", 17)这将在端口 D17 上创建一个按钮,该端口连接到 ReSpeaker 2-Mics Pi HAT 上的按钮。此按钮设置为在按下时发送低信号。
如果您未使用 ReSpeaker 2-Mics Pi HAT,而是使用连接到基座 HAT 的 Grove 按钮,请使用以下代码:
pythonbutton = Factory.getButton("GPIO-HIGH", 5)这将在端口 D5 上创建一个按钮,该按钮设置为在按下时发送高信号。
在此之后,创建一个 PyAudio 类的实例来处理音频:
pythonaudio = pyaudio.PyAudio()声明麦克风和扬声器的硬件卡号。这将是您在本课程前面通过运行
arecord -l和aplay -l找到的卡号。pythonmicrophone_card_number = <microphone card number> speaker_card_number = <speaker card number>将
<microphone card number>替换为您的麦克风卡号。将
<speaker card number>替换为您的扬声器卡号,与您在alsa.conf文件中设置的卡号相同。在此之后,声明用于音频捕捉和回放的采样率。根据您使用的硬件,可能需要更改此值。
pythonrate = 48000 #48KHz如果稍后运行代码时出现采样率错误,请将此值更改为
44100或16000。值越高,音质越好。在此之后,创建一个名为
capture_audio的新函数。此函数将用于从麦克风捕捉音频:pythondef capture_audio():在此函数中,添加以下代码以捕捉音频:
pythonstream = audio.open(format = pyaudio.paInt16, rate = rate, channels = 1, input_device_index = microphone_card_number, input = True, frames_per_buffer = 4096) frames = [] while button.is_pressed(): frames.append(stream.read(4096)) stream.stop_stream() stream.close()此代码使用 PyAudio 对象打开一个音频输入流。该流将以 16KHz 的采样率从麦克风捕捉音频,并以 4096 字节大小的缓冲区捕捉。
然后代码在 Grove 按钮被按下时循环运行,每次将这些 4096 字节的缓冲区读取到一个数组中。
💁 您可以在 PyAudio 文档 中了解更多关于传递给
open方法的选项。一旦按钮被释放,流将停止并关闭。
在此函数的末尾添加以下代码:
pythonwav_buffer = io.BytesIO() with wave.open(wav_buffer, 'wb') as wavefile: wavefile.setnchannels(1) wavefile.setsampwidth(audio.get_sample_size(pyaudio.paInt16)) wavefile.setframerate(rate) wavefile.writeframes(b''.join(frames)) wav_buffer.seek(0) return wav_buffer此代码创建一个二进制缓冲区,并将所有捕捉到的音频以 WAV 文件 的形式写入其中。这是一种将未压缩音频写入文件的标准方式。然后返回此缓冲区。
添加以下
play_audio函数以回放音频缓冲区:pythondef play_audio(buffer): stream = audio.open(format = pyaudio.paInt16, rate = rate, channels = 1, output_device_index = speaker_card_number, output = True) with wave.open(buffer, 'rb') as wf: data = wf.readframes(4096) while len(data) > 0: stream.write(data) data = wf.readframes(4096) stream.close()此函数打开另一个音频流,这次是用于输出 - 播放音频。它使用与输入流相同的设置。缓冲区被作为 WAV 文件打开,并以 4096 字节块的形式写入输出流,从而播放音频。然后关闭流。
在
capture_audio函数下方添加以下代码,以循环检测按钮是否被按下。一旦按钮被按下,音频将被捕捉并播放。pythonwhile True: while not button.is_pressed(): time.sleep(.1) buffer = capture_audio() play_audio(buffer)运行代码。按下按钮并对着麦克风说话。完成后释放按钮,您将听到录音。
在创建 PyAudio 实例时,您可能会看到一些 ALSA 错误。这是由于树莓派上为您未使用的音频设备配置所致。可以忽略这些错误。
textpi@raspberrypi:~/smart-timer $ python3 app.py ALSA lib pcm.c:2565:(snd_pcm_open_noupdate) Unknown PCM cards.pcm.front ALSA lib pcm.c:2565:(snd_pcm_open_noupdate) Unknown PCM cards.pcm.rear ALSA lib pcm.c:2565:(snd_pcm_open_noupdate) Unknown PCM cards.pcm.center_lfe ALSA lib pcm.c:2565:(snd_pcm_open_noupdate) Unknown PCM cards.pcm.side如果您收到以下错误:
textOSError: [Errno -9997] Invalid sample rate请将
rate更改为 44100 或 16000。
💁 您可以在 code-record/pi 文件夹中找到此代码。
😀 您的音频录制程序成功了!