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

4
我已经饱受折磨了三天,想实现一个Python自动化流程,它可以接收电话系统自动推送的.WAV电子邮件附件(例如b'RIFFm\xc1\x00\x00WAVEfmt[...]'),通过一些文本转语音API(如speech_recognition或一些未来的离线Sphinx/Kaldi实现),并发送回转录。理想情况下,这一切都应该在内存中处理,而不需要创建磁盘上的文件,因为这似乎是多余的,但我正在努力从我拥有的音频数据移动到我可以发送的转录,并且我不介意进行一些文件清理。
我遇到的问题是手动下载的.WAV文件附件和我通过电子邮件API处理的二进制数据与wave依赖项不兼容,使用wave.open('ipsum.wav')会出现错误unknown format:49,而使用speech_recognition库结束时,wave未知格式错误会转换为ValueError:Audio file could not be read as PCM WAV、AIFF/AIFF-C或Native FLAC;请检查文件是否损坏或处于另一种格式中。
手动将我拥有的本地文件转换为.wavs,使用在线文件转换工具似乎可以解决speech_recognition愿意使用的问题,我已经设法做到这一点(转录文件太短,但这是一个单独的分块问题)。因此,问题似乎在于wave无法与电话系统发送给我的文件的格式/编码/压缩方式相适应,解决方案存在于复制这个网络转换工具如何对这些测试文件进行编码。
我一直在尝试使用pydub的.export()函数来强制转换为wave喜欢的东西(pydub已经成功播放了那些文件),但它似乎让我陷入了一个循环,并且我回到了上面讨论的错误回溯。理想的解决方案可能在于某个工具,在内存中操作电子邮件附件的字节数组,但我再次开放任何Pythonic建议。
我可能会在以后改变我使用的文本到语音框架,从谷歌 somewhere down the line,但目前我的基本实现代码如下:
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的方式教我有关音频文件转换的知识(我一直在苦苦挣扎于极度偏重实际应用但又假定您的音频处理完美无缺和极度理论化的讨论之间的巨大鸿沟),我非常乐意听取。


据我所知,这里的主要问题是将WAV文件从您的系统传输到Python。您能否分享任何此类有问题的WAV文件的示例?这将使我们更容易地解决问题。 - Lukasz Tracewski
酷,当你有数据时通知我。如果在公开场合分享不是一个选项,可以使用我的电子邮件。干杯! - Lukasz Tracewski
@LukaszTracewski dropbox.com/s/asamm4tad3myyal/msg0000%20%282%29.WAV?dl=0 这个文件来自Grandstream的电话系统。我不确定具体型号,但看起来Dropbox有一些关于编解码器的好信息。 - wintermute000
谢谢!我的回答解决了你的问题吗? - Lukasz Tracewski
@LukaszTracewski 我还在努力解决它,但我已经有了一个相当好的想法。我目前正在攻击FFMPEG角度。 - wintermute000
ffmpeg 肯定可以将音频转换为 PCM 格式。但是,你询问了 Python 的解决方案,这就是我提供的。如果它不能解决你的问题,很高兴听到反馈。如果可以解决,你应该接受答案: https://stackoverflow.com/help/someone-answers - Lukasz Tracewski
1个回答

3

标准库的wave模块仅支持 PCM 编码,这可由此代码证明:

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

你所处理的是8,000 Hz GSM 06.10,或者更常见的GSM。你可以在维基百科上了解更多不同编码方案的信息。

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)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接