Python使用pyaudio/pyaudiowpatch录制音频失真问题求助
解决PyAudio/PyAudioWPatch录制桌面音频失真问题
核心原因分析
你遇到的"铁罐音质"失真,大概率是设备参数不匹配或音频流格式强制对齐错误导致的——Voicemeter会自动完成参数适配和音频重采样,而PyAudio需要严格遵循设备原生参数配置。
具体修复方案
1. 严格匹配设备原生参数
不要硬编码采样率、格式等参数,先获取目标设备的原生配置再打开流:
import pyaudiowpatch as py p = py.PyAudio() # 定位目标Stereo Mix设备 target_device = None for i in range(p.get_device_count()): device = p.get_device_info_by_index(i) if device['name'][:10].lower() == 'stereo mix' and device['hostApi'] == 2: target_device = device break if not target_device: print("未找到Stereo Mix设备") p.terminate() exit() # 用设备原生参数初始化输入流 inp = p.open( format=int(target_device['defaultSampleFormat']), channels=target_device['maxInputChannels'], rate=int(target_device['defaultSampleRate']), input=True, frames_per_buffer=2048, input_device_index=target_device['index'] ) # 输出设备同样使用原生参数 output_device = p.get_device_info_by_index(77) out = p.open( format=int(output_device['defaultSampleFormat']), channels=output_device['maxOutputChannels'], rate=int(output_device['defaultSampleRate']), output=True, frames_per_buffer=2048, output_device_index=output_device['index'] ) try: while True: data = inp.read(2048) out.write(data) except KeyboardInterrupt: inp.stop_stream() out.stop_stream() inp.close() out.close() p.terminate()
如果输入输出设备采样率不一致,必须添加实时重采样(直接强制同采样率会导致失真),可借助numpy或soundfile实现。
2. 调整缓冲区大小
过小的缓冲区会导致丢帧失真,过大则增加延迟,建议将frames_per_buffer调整为2048或4096。
3. 切换到SoundDevice库(推荐)
SoundDevice基于PortAudio开发,自动处理多数参数适配问题,代码更简洁:
import sounddevice as sd # 查找Stereo Mix设备索引 def find_stereo_mix(): for i, dev in enumerate(sd.query_devices()): if 'stereo mix' in dev['name'].lower() and dev['max_input_channels'] > 0: return i return None input_idx = find_stereo_mix() output_idx = 77 # 你的耳机设备索引 # 获取设备参数并统一采样率 input_params = sd.query_devices(input_idx, 'input') output_params = sd.query_devices(output_idx, 'output') sample_rate = min(int(input_params['default_samplerate']), int(output_params['default_samplerate'])) # 音频回调函数(可直接在此处加入socket传输逻辑) def audio_callback(indata, outdata, frames, time, status): if status: print(status) # 替换为你的socket发送代码:send_to_socket(indata.tobytes()) outdata[:] = indata # 启动音频流 with sd.Stream(device=(input_idx, output_idx), samplerate=sample_rate, channels=2, callback=audio_callback): print("录制中,按回车停止") input()
4. 检查系统音频设置
- 将Stereo Mix的音量调至80%左右,避免过载失真
- 关闭Windows系统的"响度均衡"等音频增强功能
无需额外工具的简化方案
使用PyAudioWPatch的WASAPI回环录制,自动适配系统参数:
import pyaudiowpatch as py with py.PyAudio() as p: loopback_dev = p.get_default_wasapi_loopback() with p.open( format=p.get_format_from_width(loopback_dev['defaultSampleWidth']), channels=loopback_dev['maxInputChannels'], rate=int(loopback_dev['defaultSampleRate']), input=True, input_device_index=loopback_dev['index'], frames_per_buffer=2048 ) as inp, p.open( format=p.get_format_from_width(loopback_dev['defaultSampleWidth']), channels=2, rate=int(loopback_dev['defaultSampleRate']), output=True, output_device_index=77, frames_per_buffer=2048 ) as out: print("录制中...按Ctrl+C停止") try: while True: data = inp.read(2048) out.write(data) except KeyboardInterrupt: pass
内容的提问来源于stack exchange,提问作者Lancseszter
相关产品推荐
相关产品推荐

