sounddevice.PortAudioError: Error querying device -1

项目场景:

最近在做一个录音场景的项目,大概流程就是通过Python的sounddevice包去获取录音设备,然后拾取声音作为后续处理。
我的环境:
操作系统:Ubuntu-20.04
CPU:Intel 6700HQ
内存:8GB
声卡:100 Series/C230 Series Chipset Family HD Audio Controller


问题描述

在shell里直接操作是可以的,不报任何错误。当使用supervisor作为守护保活的时候,诡异的事情发生了。居然出现了找不到输入设备的诡异错误。
下面是错误发生时我抓取的声音设备:

   0 HDA Intel PCH: ALC662 rev3 Analog (hw:0,0), ALSA (0 in, 2 out)
   1 HDA Intel PCH: ALC662 re
<think>好的,用户现在遇到了使用sounddevice库的RawInputStream时出现的PortAudioError错误,错误代码是-9977。之前已经给他提供过关于InputStream的解决方案,现在需要针对RawInputStream的情况进行调整。首先,我需要回顾一下之前的对话,确保这次回答的一致性和准确性。 用户提到之前的引用中有一个错误是“Error querying device -1”,这可能与设备选择有关,但现在的问题是关于-9977的错误,也就是尝试在回调流中进行读取操作。用户现在具体使用的是RawInputStream,这可能意味着他们需要更低级别的控制,或者在使用方式上有一些不同。 我需要先确认RawInputStream和InputStream之间的区别。根据sounddevice的文档,RawInputStream提供的是未经处理的原始音频数据,而InputStream可能处理了一些格式转换。因此,在使用RawInputStream时,参数设置可能需要更精确,比如格式、数据类型等。 接下来,错误代码-9977的具体原因是在回调流中错误地调用了读取操作。在之前的回答中,已经提到了两种方法:正确使用回调函数或改用阻塞模式。但用户现在使用的是RawInputStream,可能需要更仔细地检查回调函数的实现和参数设置。 用户可能在代码中错误地在回调函数外部调用了read()方法,或者在回调函数内部进行了不恰当的操作。此外,设备参数是否正确,比如采样率、通道数、设备ID是否有效,都是需要检查的地方。 另外,用户可能在多次打开流后没有正确释放资源,导致设备不可用,这在引用[2]中提到过PyAudio的类似问题,虽然这里是sounddevice,但资源管理的问题可能是共通的。因此,需要确保使用with语句或正确关闭流来避免设备占用。 还要考虑是否在回调函数中进行了耗时操作,导致音频处理延迟,从而触发错误。需要提醒用户保持回调函数简洁,避免阻塞。 现在需要将这些问题整理成步骤,包括错误原因分析、参数检查、回调函数写法、资源管理等,并提供示例代码。同时,要确保用户正确设置dtype参数,因为RawInputStream可能需要明确指定数据类型,比如'int16'或'float32'。 另外,用户可能在多线程或异步环境中使用了流,导致冲突,需要提醒他们线程安全的问题。最后,对比典型错误和正确用法,帮助用户理解如何避免常见陷阱。</think>针对使用$sounddevice.RawInputStream$时出现的$PortAudioError$错误代码-9977的问题,以下是深度解决方案: ### 一、错误根源定位 错误代码$PaErrorCode -9977$直接对应**PortAudio API的paCanNotReadFromACallbackStream**,核心原因为: - 在**回调模式流**(callback stream)中非法调用$read()$方法 - 试图通过主线程主动获取数据而非通过回调函数 - 流参数与设备实际能力不匹配(特别是$dtype$和$blocksize$)[^1] ### 二、RawInputStream专用修复方案 #### 方案1:规范回调模式实现 ```python import sounddevice as sd import numpy as np # 必须明确指定dtype(如设备原生格式为int16) dtype = 'int16' # 常见设备原生格式 samplerate = 16000 channels = 1 def raw_callback(indata: np.ndarray, frames: int, time, status): """indata已经是原始二进制数据转换后的numpy数组""" # 此处直接处理原始音频数据(例如实时传输) print(f"收到原始数据块: {indata.shape}") # 关键参数必须准确匹配设备能力 with sd.RawInputStream( callback=raw_callback, dtype=dtype, samplerate=samplerate, channels=channels, blocksize=1024 # 必须明确设置且为2的幂 ) as stream: input("按Enter停止采集...") ``` #### 方案2:阻塞模式替代方案 ```python with sd.RawInputStream( dtype='int32', # 根据设备实际支持选择 samplerate=48000, blocksize=512 ) as stream: while True: raw_data, overflow = stream.read(stream.blocksize) # 直接处理raw_data字节数据 if overflow: print("警告:发生缓冲区溢出") ``` ### 三、参数验证流程 1. **设备能力检测**: ```python device_info = sd.query_devices(device=None) # 获取默认设备 print(f"支持格式: {device_info['formats']}") # 查看原生dtype print(f"最大输入通道: {device_info['max_input_channels']}") ``` 2. **参数兼容性检查**: - $dtype$必须与设备原生格式匹配(常见为$int16$、$int32$或$float32$) - $blocksize$必须为设备支持的分块大小(通常为256/512/1024) - $samplerate$需在设备支持的采样率列表中[^2] ### 四、高级调试技巧 | 现象 | 检查点 | 工具 | |------|--------|-----| | 持续报-9977 | 确认没有在`with`块内调用stream.read() | 代码审查 | | 数据异常 | 验证dtype是否与设备原生格式一致 | `sd.query_devices()` | | 随机崩溃 | 检查回调函数执行时间是否超过块间隔 | 性能分析器 | | 首次成功后续失败 | 确保流正确关闭(避免设备占用) | 资源监视器 | ### 五、典型错误场景修复 **错误代码示例**: ```python stream = sd.RawInputStream(callback=lambda: ...) data = stream.read() # 触发-9977错误 ``` **正确修改**: ```python with sd.RawInputStream(callback=proc_data): while True: pass # 通过回调自动处理 ``` ### 六、跨平台注意事项 在树莓派等嵌入式设备上需额外注意: 1. 使用`dtype='int16'`(多数USB声卡原生格式) 2. 降低采样率至16000Hz或以下 3. 增加`extra_settings=sd.AsioSettings(...)`(若使用专业声卡) --- **相关问题**: 1. 如何验证音频设备的原生数据格式? 2. 实时音频处理中如何避免回调函数延迟? 3. 树莓派上使用sounddevice有哪些特殊配置要求? 4. 如何将RawInputStream获取的字节数据转换为PCM波形数组?
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值