PyAudio无法识别Focusrite 18i20多通道输入问题求助
环境配置
- Python版本:3.11.4
- PyAudio版本:0.2.11
- Torch版本:2.1.1+cu118
问题描述
已通过DAW确认Focusrite 18i20的8个麦克风通道均有音频输入,但Python脚本仅能将1、2通道的音频实时播放到笔记本立体声耳机接口,3-8通道完全无声。同时测试脚本录制的8通道WAV文件,在RX10/Pro Tools中打开后3-8通道仅显示静音。采用阻塞模式而非回调模式。
音频流设置代码
if read_from_file == True: wf = wave.open(audio_path, 'rb') stream = paudio.open( format=paudio.get_format_from_width(wf.getsampwidth()), channels=output_format, rate=wf.getframerate(), output=True) elif read_from_file == False: istream = paudio.open(format=format_audio, channels=channels, rate=sr, input=True, frames_per_buffer=input_chunk, input_device_index=input_device) stream = paudio.open(format=pyaudio.paInt16, channels=2, rate=sr, frames_per_buffer=input_chunk, output=True)
实时流播放代码
while len(data) > 0 and time.time() < end_time: if channels == 8: numpy_data = np.frombuffer(data, dtype=np.int16) stereo_data = mix_down_to_stereo(numpy_data) if normalize == False: data = stereo_data.astype(np.int16).tobytes() else: processed_data = compress_and_normalize(stereo_data, threshold=-0.1, ratio=4.0, normalize_scale=0.5) scaled_data = np.int16(processed_data * 32767) data = scaled_data.tobytes() stream.write(data) if read_from_file == True: data = wf.readframes(chunk) elif read_from_file == False: data = istream.read(input_chunk)
关闭音频流代码
if read_from_file == True: wf.close() stream.close() paudio.terminate()
测试录制脚本代码
import pyaudio import wave FORMAT = pyaudio.paInt16 CHANNELS = 8 RATE = 48000 CHUNK = 1024 RECORD_SECONDS = 5 FILENAME = "test_recording.wav" audio = pyaudio.PyAudio() # Start Recording stream = audio.open(format=FORMAT, channels=CHANNELS, rate=RATE, input=True, frames_per_buffer=CHUNK) frames = [] for i in range(0, int(RATE / CHUNK * RECORD_SECONDS)): data = stream.read(CHUNK) frames.append(data) # Stop Recording stream.stop_stream() stream.close() audio.terminate() # Save the recorded data as a WAV file wf = wave.open(FILENAME, 'wb') wf.setnchannels(CHANNELS) wf.setsampwidth(audio.get_sample_size(FORMAT)) wf.setframerate(RATE) wf.writeframes(b''.join(frames)) wf.close()
问题分析与解决方案
1. PyAudio对多通道的支持
PyAudio本身支持多通道输入输出,但实际能否获取所有通道数据,取决于音频硬件的驱动是否正确暴露这些通道给底层依赖的PortAudio库。
2. 3-8通道无声的核心原因
(1)输入设备通道映射问题
Focusrite 18i20这类专业音频接口,默认可能不会将所有通道都映射为系统默认输入设备的可用通道。即使脚本指定了channels=8,PyAudio可能实际只获取到前2通道的数据——因为PortAudio未正确识别接口的全部8个输入通道,或系统音频设置未启用这些通道。
(2)测试脚本的WAV文件格式问题
标准WAV文件的多通道存储分交错式和非交错式,PyAudio返回的多通道数据是交错式(每个采样帧按通道1→通道2→...→通道8循环存储),而部分DAW(如Pro Tools)对多通道WAV格式要求更严格,需要非交错式存储或特定通道标记才能识别全部通道。
(3)实时播放的通道处理逻辑
实时播放代码的输出流是channels=2的立体声,若mix_down_to_stereo函数未正确处理8通道的交错数据,会仅提取前2通道内容,导致3-8通道音频被丢弃。
3. 解决方案
(1)确认输入设备的通道可用性
运行以下代码,检查Focusrite设备的输入通道数是否被正确识别:
import pyaudio pa = pyaudio.PyAudio() for i in range(pa.get_device_count()): dev_info = pa.get_device_info_by_index(i) print(f"设备索引: {i}") print(f"设备名称: {dev_info['name']}") print(f"支持的输入通道数: {dev_info['maxInputChannels']}") print(f"支持的输出通道数: {dev_info['maxOutputChannels']}") print("-"*30) pa.terminate()
若maxInputChannels不是8,需调整系统设置:
- Windows:打开「声音设置」→「更多声音设置」→ 找到Focusrite设备→「属性」→「高级」,确认启用所有输入通道。
- macOS:打开「音频MIDI设置」→ 找到Focusrite设备→ 点击「配置输入」,启用8个输入通道。
(2)修复测试脚本的WAV写入逻辑
使用scipy.io.wavfile替代标准wave模块,更好处理多通道数据:
import pyaudio import numpy as np from scipy.io import wavfile FORMAT = pyaudio.paInt16 CHANNELS = 8 RATE = 48000 CHUNK = 1024 RECORD_SECONDS = 5 FILENAME = "test_recording.wav" audio = pyaudio.PyAudio() stream = audio.open(format=FORMAT, channels=CHANNELS, rate=RATE, input=True, frames_per_buffer=CHUNK) frames = [] for _ in range(0, int(RATE / CHUNK * RECORD_SECONDS)): data = stream.read(CHUNK) frames.append(data) stream.stop_stream() stream.close() audio.terminate() # 将字节数据转换为numpy数组并重塑为(采样数, 通道数)格式 audio_data = np.frombuffer(b''.join(frames), dtype=np.int16) audio_data = audio_data.reshape(-1, CHANNELS) # 写入WAV文件 wavfile.write(FILENAME, RATE, audio_data)
(3)修复实时播放的通道混音逻辑
确保mix_down_to_stereo正确处理8通道交错数据:
def mix_down_to_stereo(interleaved_data): # 将交错数据重塑为(帧数量, 8通道) multi_channel = interleaved_data.reshape(-1, 8) # 自定义3-8通道到立体声的混音规则(可调整权重) left = (multi_channel[:,0] + multi_channel[:,2] + multi_channel[:,4] + multi_channel[:,6]) / 4 right = (multi_channel[:,1] + multi_channel[:,3] + multi_channel[:,5] + multi_channel[:,7]) / 4 # 重新生成立体声交错数据 stereo_interleaved = np.column_stack((left, right)).flatten() return stereo_interleaved
内容的提问来源于stack exchange,提问作者Strigi

