树莓派如何同时录制两块音频卡音频并合并文件?
解决树莓派双USB音频卡同时录音并合并的问题
我正好碰到过类似的双音频设备录音需求,你的代码问题主要出在线程控制逻辑和单线程内顺序读取两个流的同步问题上,咱们一步步来解决:
首先,你原来的代码里,启动录音线程后没有触发停止信号,while self.going会一直循环下去;而且在同一个线程里依次读取两个流的话,很容易出现音频不同步或者缓冲区溢出的情况。最好的做法是给每个音频设备分配单独的录音线程,最后再合并两个线程录到的音频数据。
修正后的完整代码
import numpy as np import pyaudio import wave import threading import time # 录音参数 CHUNK = 512 FORMAT = pyaudio.paInt16 RATE = 44100 RECORD_SECONDS = 5 WAVE_OUTPUT_MONO = "/home/pi/merged_mono.wav" # 混合单声道输出 WAVE_OUTPUT_STEREO = "/home/pi/merged_stereo.wav" # 立体声输出 class DeviceRecorder(threading.Thread): def __init__(self, device_index): super().__init__() self.device_index = device_index self.frames = [] self.is_recording = False self.p = pyaudio.PyAudio() def run(self): # 打开对应设备的音频流 stream = self.p.open( format=FORMAT, channels=1, rate=RATE, input=True, frames_per_buffer=CHUNK, input_device_index=self.device_index, exception_on_overflow=False ) self.is_recording = True while self.is_recording: data = stream.read(CHUNK) self.frames.append(data) # 停止并关闭流 stream.stop_stream() stream.close() self.p.terminate() def stop(self): self.is_recording = False class MultiRecorder: def __init__(self, device_indices): self.recorders = [DeviceRecorder(idx) for idx in device_indices] def start_recording(self): for recorder in self.recorders: recorder.start() print("开始同时录音...") def stop_recording(self): for recorder in self.recorders: recorder.stop() recorder.join() # 等待线程结束 print("录音结束,开始合并音频...") def merge_audio(self, output_mode="mono"): # 将两个设备的音频数据解码为numpy数组 audio_data = [] for recorder in self.recorders: raw_data = b''.join(recorder.frames) decoded = np.frombuffer(raw_data, dtype=np.int16) audio_data.append(decoded) # 确保两个音频长度一致(取较短的那个) min_length = min(len(d) for d in audio_data) audio_data = [d[:min_length] for d in audio_data] if output_mode == "mono": # 混合成单声道(简单相加后限制音量防止爆音) merged = np.clip((audio_data[0] + audio_data[1]) / 2, -32768, 32767) merged = merged.astype(np.int16) self._save_wav(WAVE_OUTPUT_MONO, merged, channels=1) elif output_mode == "stereo": # 合成立体声(左声道来自设备1,右声道来自设备2) merged = np.column_stack(audio_data).flatten() merged = merged.astype(np.int16) self._save_wav(WAVE_OUTPUT_STEREO, merged, channels=2) def _save_wav(self, filename, data, channels): wf = wave.open(filename, 'wb') wf.setnchannels(channels) wf.setsampwidth(pyaudio.PyAudio().get_sample_size(FORMAT)) wf.setframerate(RATE) wf.writeframes(data.tobytes()) wf.close() print(f"音频文件已保存至: {filename}") # 先检测可用音频设备 p = pyaudio.PyAudio() print("可用音频设备列表:") for i in range(p.get_device_count()): info = p.get_device_info_by_index(i) print(f"索引 {i}: {info['name']}") p.terminate() # 主程序 if __name__ == "__main__": # 替换成你的两个音频设备索引 device_indices = [2, 3] recorder = MultiRecorder(device_indices) recorder.start_recording() time.sleep(RECORD_SECONDS) # 录制指定时长 recorder.stop_recording() # 生成混合单声道和立体声文件 recorder.merge_audio(output_mode="mono") recorder.merge_audio(output_mode="stereo")
关键改进点说明
- 独立线程录音:每个音频设备用单独的
DeviceRecorder线程处理,确保两个流的读取是并行的,避免了单线程顺序读取的同步问题 - 完善的线程控制:通过
is_recording标志控制录音启停,并用join()等待线程完全结束,不会出现无限循环的情况 - 灵活的音频合并:支持混合成单声道(适合需要合并音频内容的场景)或保存成立体声(保留两个设备的独立音频轨道)
- 溢出处理:开启
exception_on_overflow=False避免偶尔的缓冲区溢出导致程序崩溃
你原代码的问题分析
- 没有调用
stop_recording方法,导致self.going一直为True,while循环无法退出 - 单线程内顺序读取两个流,容易导致其中一个流的缓冲区溢出,影响录音同步性和质量
- 主线程在启动录音线程后直接继续执行,没有等待录音完成的逻辑,导致程序看似"无限运行"
内容的提问来源于stack exchange,提问作者Jubick
相关产品推荐
相关产品推荐

