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)
遇到的错误
- 使用默认采样率时:
OSError: [Errno -9997] Invalid sample rate
- 强制设置
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
相关产品推荐
相关产品推荐

