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

Linux下用Python+Numpy分析应用音频报错问题求助

Linux下用PyAudio+Numpy分析Firefox音频输出的问题解决

原问题代码

import pyaudio
import numpy as np

p = pyaudio.PyAudio()
BUFFER = 1024

for i in range(p.get_device_count()):
    info = p.get_device_info_by_index(i)
    if info['name'] == 'Firefox':
        break

stream = p.open(
    format=pyaudio.paInt16,
    channels=2,
    rate=int(info['defaultSampleRate']),
    input=True,
    input_device_index=info['index'],
    frames_per_buffer=BUFFER
)

while True:
    data = stream.read(BUFFER)
    audio_data = np.frombuffer(data, dtype=np.int16)
    print(audio_data)

遇到的错误

  1. 使用默认采样率时:

OSError: [Errno -9997] Invalid sample rate

  1. 强制设置rate=44100时:

malloc(): invalid size (unsorted)
[1] 576600 IOT instruction (core dumped)

问题分析

核心错误是混淆了音频输入/输出设备的用途:

  • Firefox的音频设备是输出设备,负责播放音频;而PyAudio的input=True参数仅用于读取输入设备(如麦克风)的音频数据。
  • 直接将输出设备当作输入设备打开,会导致设备参数不匹配(采样率无效),甚至触发PyAudio内部内存分配错误,最终引发核心转储。

解决方案

Linux下要捕获应用的音频输出,需通过PulseAudio创建虚拟回环设备,将应用的输出路由为可捕获的输入,再用PyAudio读取。

步骤1:创建虚拟音频回环设备

在终端执行以下命令:

# 创建虚拟输出设备
pactl load-module module-null-sink sink_name=VirtualSink sink_properties=device.description="Virtual_Sink"
# 将虚拟输出的音频转为输入监听设备
pactl load-module module-loopback source=VirtualSink.monitor

步骤2:将Firefox音频切换到虚拟设备

  • 图形化方式:打开pavucontrol(未安装则执行sudo apt install pavucontrol),在「播放」标签页找到Firefox,将其输出设备改为Virtual_Sink。
  • 命令行方式:
# 找到Firefox的音频流ID并切换输出设备
pactl move-sink-input $(pactl list short sink-inputs | grep firefox | awk '{print $1}') VirtualSink

步骤3:修改Python代码捕获虚拟输入

修改代码,读取虚拟监听设备的音频数据:

import pyaudio
import numpy as np

p = pyaudio.PyAudio()
BUFFER = 1024
TARGET_DEVICE = "Virtual_Sink.monitor"

# 查找虚拟监听设备
device_idx = None
sample_rate = None
for i in range(p.get_device_count()):
    dev_info = p.get_device_info_by_index(i)
    if dev_info['name'] == TARGET_DEVICE:
        device_idx = dev_info['index']
        sample_rate = int(dev_info['defaultSampleRate'])
        break

if not device_idx:
    print("未找到虚拟监听设备,请先执行虚拟设备创建命令")
    p.terminate()
    exit()

# 正确打开输入流
stream = p.open(
    format=pyaudio.paInt16,
    channels=2,
    rate=sample_rate,
    input=True,
    input_device_index=device_idx,
    frames_per_buffer=BUFFER
)

try:
    while True:
        data = stream.read(BUFFER)
        # 转换为双通道numpy数组(适合立体声分析)
        audio_arr = np.frombuffer(data, dtype=np.int16).reshape(-1, 2)
        # 这里可以添加自定义分析逻辑,比如计算实时音量、频谱等
        avg_volume = np.mean(np.abs(audio_arr))
        print(f"当前帧数据形状:{audio_arr.shape},平均音量:{avg_volume:.2f}")
except KeyboardInterrupt:
    print("\n程序终止")
finally:
    stream.stop_stream()
    stream.close()
    p.terminate()

补充说明

  • 系统重启后需重新加载虚拟音频模块,可将加载命令添加到启动脚本中实现自动加载。
  • 无图形界面环境下,可完全通过pactl命令行控制音频路由,适配服务器场景。

内容的提问来源于stack exchange,提问作者RobinFrcd

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.19 01:40:13