PyAudio录制麦克风与系统声音:线程代码整合失败求助
解决PyAudio线程中同时录制扬声器与麦克风并实时混音的问题
看起来你已经搞懂了单独录制和后期混音的逻辑,但把这套逻辑放到线程化的recorder类里时,核心问题在于原来的单流录制逻辑没有适配双流同步读取+实时混音,而是沿用了先分别存储所有帧再后期处理的方式,这不仅容易导致内存占用过高,更关键的是两个流的读取可能不同步,最终导致混音后的音频出现错位或者异常。
下面是修正后的完整recorder类代码,我会在后面解释关键改动点:
import pyaudio import wave import threading import numpy as np CHUNK = 1024 FORMAT = pyaudio.paInt16 RATE = 44100 class recorder: def __init__(self): self.going = False self.process = None # 预定义设备索引(根据你的设备列表) self.speaker_device_idx = 2 # 立体声混音设备 self.mic_device_idx = 1 # 麦克风设备 def record(self, filename): # 检查是否已有录制线程在运行 if self.process and self.process.is_alive(): self.stop_recording() self.filename = filename self.process = threading.Thread(target=self._record) self.process.start() def _record(self): p = pyaudio.PyAudio() frames = [] # 打开扬声器混音流(立体声) speaker_stream = p.open( format=FORMAT, channels=2, rate=RATE, input=True, frames_per_buffer=CHUNK, input_device_index=self.speaker_device_idx, as_loopback=True ) # 打开麦克风流(单声道) mic_stream = p.open( format=FORMAT, channels=1, rate=RATE, input=True, frames_per_buffer=CHUNK, input_device_index=self.mic_device_idx ) print("* 开始录制(扬声器+麦克风)") self.going = True while self.going: try: # 同步读取两个流的chunk数据,避免缓冲区溢出中断 speaker_data = speaker_stream.read(CHUNK, exception_on_overflow=False) mic_data = mic_stream.read(CHUNK, exception_on_overflow=False) # 解码为numpy数组 speaker_decoded = np.frombuffer(speaker_data, dtype=np.int16) mic_decoded = np.frombuffer(mic_data, dtype=np.int16) # 分离扬声器左右声道并合并为单声道(避免音量过高) speaker_mono = (speaker_decoded[::2] + speaker_decoded[1::2]) // 2 # 混音并限制音量范围,防止音频失真 mixed = np.clip(speaker_mono + mic_decoded, -32767, 32766) # 重新编码为字节数据 mixed_data = mixed.tobytes() # 将混音后的chunk加入帧列表 frames.append(mixed_data) except Exception as e: print(f"录制过程中出错: {e}") break print("* 录制结束") # 关闭流并终止PyAudio speaker_stream.stop_stream() speaker_stream.close() mic_stream.stop_stream() mic_stream.close() p.terminate() # 保存混音后的音频文件 wf = wave.open(self.filename, 'wb') wf.setnchannels(1) # 最终输出单声道 wf.setsampwidth(p.get_sample_size(FORMAT)) wf.setframerate(RATE) wf.writeframes(b''.join(frames)) wf.close() def stop_recording(self): self.going = False if self.process: self.process.join()
关键改动说明:
- 双流同步读取:在录制循环中,每次同时读取扬声器流和麦克风流的chunk数据,确保两者的时间轴完全同步,避免后期混音时出现音频错位。
- 实时混音:不再分别存储两个流的所有帧,而是每读取一块数据就立即完成混音处理,大大降低内存占用,同时保证实时性。
- 异常处理:添加
exception_on_overflow=False和全局异常捕获,避免因系统负载导致的缓冲区溢出中断录制。 - 线程安全优化:在
stop_recording中调用process.join(),确保录制线程完全终止后再进行后续操作。 - 音量控制:对扬声器左右声道做平均合并,再和麦克风音频叠加后用
np.clip限制输出范围,防止音量过高导致的音频失真。
测试注意事项:
- 确保你的立体声混音设备已经在系统中启用并设置为可用状态。
- 如果出现音频卡顿或者不同步,可以尝试调整
CHUNK的大小(比如改为2048),平衡延迟和稳定性。 - 若设备索引有变动,直接修改
__init__中的speaker_device_idx和mic_device_idx即可。
内容的提问来源于stack exchange,提问作者Gabriel




