如何无损转换WAV与Numpy数组并适配OpenAI Whisper云端转录
问题解答
1. WAV与Numpy数组互转时音质损坏的解决方法
你遇到的噪音问题核心是数据类型转换未做正确幅度缩放,以及AudioSegment参数匹配错误。scipy.io.wavfile.read读取的16位深度音频会返回int16类型数组,直接转float32后数值范围仍为[-32768, 32767],AudioSegment会将这些字节当成原始采样数据处理,超出正常音频范围导致噪音。
正确转换流程:
- 读取后将
int16数组归一化到float32的[-1, 1]范围 - 转回WAV时,再将float32数组缩放回
int16的[-32768, 32767]范围 - 确保AudioSegment的
sample_width与数据类型匹配(float32的itemsize为4,int16为2)
修正后的代码示例:
import numpy as np from scipy.io import wavfile from pydub import AudioSegment path = r'input.wav' output_path = r'output.wav' # 读取音频 original_sample_rate, audio_data = wavfile.read(path) # int16转float32并归一化 if audio_data.dtype == np.int16: audio_float32 = audio_data.astype(np.float32) / 32767.0 else: audio_float32 = audio_data # 转回int16用于保存 audio_int16 = (audio_float32 * 32767.0).astype(np.int16) # 使用AudioSegment保存(用int16数据避免格式问题) audio_segment = AudioSegment( audio_int16.tobytes(), frame_rate=original_sample_rate, sample_width=audio_int16.dtype.itemsize, channels=1 ) audio_segment.export(output_path, format='wav')
2. 直接传递Numpy数组给OpenAI Whisper的transcribe方法
Whisper的transcribe方法支持直接传入Numpy数组,但对格式有严格要求:
- 必须是**单通道(mono)**音频
- 采样率必须为16kHz
- 数据类型为
float32,数值范围在**[-1, 1]**之间
只需将现有Numpy数组处理成符合要求的格式,即可直接传入,无需转bytes或本地文件。示例代码:
import numpy as np from scipy.io import wavfile import librosa import whisper speaking_model = whisper.load_model("base") path = r'input.wav' # 读取音频 original_sample_rate, audio_data = wavfile.read(path) # 转成float32并归一化 if audio_data.dtype == np.int16: audio_float32 = audio_data.astype(np.float32) / 32767.0 else: audio_float32 = audio_data # 转单通道(立体声取第一通道) if len(audio_float32.shape) > 1: audio_float32 = audio_float32[:, 0] # 重采样到16kHz(librosa音质优于scipy) if original_sample_rate != 16000: audio_float32 = librosa.resample(audio_float32, orig_sr=original_sample_rate, target_sr=16000) # 直接传递Numpy数组 result = speaking_model.transcribe(audio_float32) print(result["text"])
内容的提问来源于stack exchange,提问作者Ali isayev
相关产品推荐
相关产品推荐

