You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.25 14:30:25