Python、speech_recognition 工具无法识别 .wav 文件

Python, speech_recognition tool does not recognize .wav file

我生成了一个 .wav 音频文件,其中包含一些语音和背景中的一些其他干扰语音。 此代码适用于我的测试 .wav 文件:

    import speech_recognition as sr

    r = sr.Recognizer()
    with sr.WavFile(wav_path) as source:
        audio = r.record(source)

    text = r.recognize_google(audio)

如果我使用我的 .wav 文件,我会收到以下错误:

ValueError: Audio file could not be read as PCM WAV, AIFF/AIFF-C, or Native FLAC; check if file is corrupted or in another format

如果我用声音文件保存这个 .wav 文件,情况会略有改善:

    import soundfile as sf        

    wav, samplerate = sf.read(wav_path)
    sf.write(saved_wav_path, original_wav, fs)

然后将新的 saved_wav_path 加载回第一个代码块,这次我得到:

if not isinstance(actual_result, dict) or len(actual_result.get("alternative", [])) == 0: raise UnknownValueError()

音频文件保存为

    wavfile.write(wav_path, fs, data)

其中 wav_path = 'data.wav'。有什么想法吗?

解决方案:

按以下方式保存音频数据会生成正确的 .wav 文件:

    import wavio
    wavio.write(wav_path, data, fs ,sampwidth=2)

通过简要查看 speech_recognition 包中的代码,它似乎使用 Python 标准库中的 wave 来读取 WAV 文件。 Python 的 wave 库不处理浮点 WAV 文件,因此您必须确保对以整数格式保存的文件使用 speech_recognition

SciPy 的函数 scipy.io.wavfile.write 将创建一个整数文件,如果您向它传递一个整数数组。所以如果 data 是一个浮点数 numpy 数组,你可以试试这个:

from scipy.io import wavfile

# Convert `data` to 32 bit integers:
y = (np.iinfo(np.int32).max * (data/np.abs(data).max())).astype(np.int32)

wavfile.write(wav_path, fs, y)

然后尝试使用 speech_recognition 读取该文件。

或者,您可以使用 wavio(我创建的一个小型库)将数据保存到 WAV 文件。它还使用 Python 的 wave 库来创建其输出,因此 speech_recognition 应该能够读取它创建的文件。

我无法从其文档中找出 wavio 的 sampwidth 应该是多少;但是,我添加了以下行 sounddevice.default.dtype='int32', 'int32',它允许 sounddevice、scipy.io.wavfile.write / soundfile 和 speech_recognizer 最终协同工作。对于输入和输出,声音设备的默认数据类型都是 float32。我尝试只更改输出,但没有用。奇怪的是,audacity 仍然认为输出文件是 float32。我并不是说这是一个更好的解决方案,但它确实适用于声音文件和 scipy.

我还注意到另一个奇怪的地方。当 sounddevice.default.dtype 保留为默认 [float32, float32] 时,我大胆地打开了生成的文件。我从 audacity 导出它,这个导出的 wav 可以与 speechrecognizer 一起使用。 Audacity 说它的导出是 float32 和相同的采样率,所以我不完全理解。我是一个菜鸟,但在十六进制编辑器中查看了两个文件,前 64 个十六进制值看起来相同,然后它们不同......所以看起来 header 是相同的。这两个看起来与我使用 int32 输出制作的文件非常不同,所以似乎还有另一个因素在起作用......