将 WAV 文件字节转换为语音识别兼容格式

Converting WAV file bytes to speech recognition-compatible format

三天来,我一直在用一个 Python 自动化管道撞墙,该管道采用 .WAV 电子邮件附件的二进制字节数组(例如 b'RIFFm\xc1\x00\x00WAVEfmt [.. .]') 一个 phone 系统自动推送,通过一些文本到语音 API 像 speech_recognition 或一些未来的离线 Sphinx/Kaldi 实现推送它,并发回一个抄本.理想情况下,这一切都将在内存中处理,而无需在磁盘上创建文件,因为这似乎是多余的,但我正在尝试找出任何 Python 从我必须的音频数据到我可以发送的转录本的任何东西我不介意稍微清理一下文件。

我 运行 遇到的问题是我手动下载用于测试的 .WAV 文件附件和我通过电子邮件处理的二进制数据 API 与wave 依赖项,wave.open('ipsum.wav') 给出 Error: unknown format: 49 并使用 speech_recognition 库以 wave 未知格式错误转换为 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 结束。

使用在线文件转换工具将我拥有的本地文件手动转换为 .wavs 似乎以 speech_recognition 愿意使用的方式解决了这个问题,并且我已经设法获得了一份工作记录这个(成绩单对于文件来说太短了,但这是一个单独的分块问题)。所以问题似乎是 wave 对 phone 系统发送给我的文件的方式不满意 formatted/encoded/compressed 并且解决方案位于复制网络转换工具如何编码这些测试的某个地方文件。

我一直在摆弄 pydub.export() 函数,试图强制它转换成 wave 喜欢的东西(pydub 已经设法播放那些文件),但它似乎让我绕了一个圈,然后我又回到了我从上面讨论的错误回溯开始的地方。理想的解决方案可能在于使用一些工具来处理内存中电子邮件附件的字节数组,但是,我同样愿意接受任何 Pythonic 建议。

我可能会从 Google 的某处更改我使用的文本到语音框架,但到目前为止我的基本实现代码:

from exchangelib import Message
import io
import pydub
import speech_recognition as sr

r = sr.Recognizer()
def speech_to_text(Message):
    for attachment in Message.attachments:
        if attachment.content_type == 'audio/x-wav':
            content = attachment.content # Store attachment's binary data as a variable
            bytes = io.BytesIO(content) # Encode IO as bytes
            f= pydub.AudioSegment.from_file(bytes).export(attachment.name[:-4] +'.wav', format='wav') # Use bytes to create pydub's AudioSegment object
                                                                                                        # and export it as desired format
            with sr.AudioFile(f) as source: # Feed converted file into speech_recognition's AudioFile
                audio = r.record(source)
                transcript = r.recognize_google(audio)
                return transcript

如果你有任何好的资源或课程可以教我如何以 Pythonic 方式转换音频文件(我一直在努力解决非常实用的资源之间的主要差距,假设你的音频处理工作正常非常完美的理论讨论),我也很高兴听到他们的声音。

标准库 wave 模块仅支持 PCM 编码 this code:

if wFormatTag == WAVE_FORMAT_PCM:
    try:
        ...
    else:
raise Error('unknown format: %r' % (wFormatTag,))

您要处理的是 8,000 Hz GSM 06.10,或者更常见的是 GSM。您可以在 wiki.

上阅读有关不同编码方案的更多信息

来自soxi的证据:

soxi msg0000\ \(2\).WAV 

Input File     : 'msg0000 (2).WAV'
Channels       : 1
Sample Rate    : 8000
Precision      : 16-bit
Duration       : 00:00:07.96 = 63680 samples ~ 597 CDDA sectors
File Size      : 13.0k
Bit Rate       : 13.1k
Sample Encoding: GSM

解决方案

使用任何支持 GSM 编码的库。 soundfile 是个不错的选择;许多流行的音频模块在下面使用它。

import soundfile as sf

sf.read('msg0000 (2).WAV') 

输出:

(array([0.00024414, 0.        , 0.        , ..., 0.00048828, 0.00048828,
        0.00024414]),
 8000)