本文概述
你是否曾经想过如何在Python项目中添加语音识别?如果是这样, 请继续阅读!它比你想象的要容易。
诸如Amazon Alexa之类的语音支持产品取得了巨大的成功, 这远非一时的风尚。事实证明, 在可预见的将来, 一定程度的语音支持将成为家用技术的重要方面。如果你考虑一下, 其原因很明显。将语音识别功能集成到你的Python应用程序中, 可以提供很少有技术可以匹敌的交互性和可访问性。
仅可访问性改进值得考虑。语音识别功能使老年人以及肢体和视力障碍人士可以快速自然地与最新的产品和服务进行交互-无需GUI!
最重要的是, 在Python项目中包括语音识别非常简单。在本指南中, 你将了解操作方法。你将学到:
- 语音识别的工作原理
- PyPI提供哪些软件包;和
- 如何安装和使用SpeechRecognition包-一个功能齐全且易于使用的Python语音识别库。
最后, 你将把学到的知识应用到一个简单的“猜单词”游戏中, 并查看它们如何结合在一起。
免费红利:单击此处下载具有完整源代码的Python语音识别示例项目, 你可以将其用作自己的语音识别应用程序的基础。
移除广告
语音识别如何工作–概述
在开始使用Python进行语音识别的本质之前, 让我们先花点时间讨论一下语音识别的工作原理。进行全面的讨论将使你充满精力, 因此在这里我不会为你带来所有技术细节。实际上, 本节不是本教程其余部分的前提条件。如果你想直截了当, 请随时跳过。
语音识别源于1950年代初期在贝尔实验室进行的研究。早期的系统仅限于一个说话者, 并且词汇量大约只有十几个单词。自从古代的语音识别系统以来, 现代语音识别系统已经走了很长一段路。他们可以识别来自多个说话者的语音, 并具有多种语言的大量词汇。
语音识别的第一部分当然是语音。必须使用麦克风将语音从物理声音转换为电信号, 然后通过模数转换器转换为数字数据。数字化后, 可以使用多种模型将音频转录为文本。
大多数现代语音识别系统都依赖于所谓的隐马尔可夫模型(HMM)。这种方法的假设是, 在足够短的时间尺度(例如10毫秒)上查看语音信号时, 可以合理地将其近似为固定过程, 即统计属性不会随时间变化的过程。
在典型的HMM中, 语音信号被分为10毫秒的片段。每个片段的功率谱实质上是信号功率随频率变化的曲线图, 被映射到称为倒频谱系数的实数向量。此向量的维数通常很小, 有时低至10, 尽管更精确的系统可能具有32或更大的维数。 HMM的最终输出是这些向量的序列。
为了将语音解码为文本, 矢量组必须与一个或多个音素(一种基本的语音单位)相匹配。该计算需要训练, 因为一个音素的声音因扬声器的不同而不同, 甚至同一扬声器的一个发音到另一个也不同。然后应用特殊算法来确定产生给定音素序列的最可能单词(或多个单词)。
可以想象整个过程在计算上可能是昂贵的。在许多现代语音识别系统中, 神经网络用于通过HMM识别之前的特征转换和降维技术简化语音信号。语音活动检测器(VAD)也用于将音频信号减少到仅可能包含语音的部分。这样可以防止识别器浪费时间分析信号的不必要部分。
幸运的是, 作为Python程序员, 你不必为此担心。可通过API在线使用多种语音识别服务, 其中许多服务都提供Python SDK。
选择一个Python语音识别包
PyPI上存在一些用于语音识别的软件包。其中一些包括:
- api
- 集会
- 谷歌云语音
- 口袋狮身人面像
- 语音识别
- 沃森开发者云
- 白色
其中一些软件包(例如wit和apiai)提供了内置功能, 例如用于识别说话者意图的自然语言处理, 这超出了基本的语音识别能力。其他如google-cloud-speech则仅专注于语音到文本的转换。
就易用性而言, 有一种软件包非常出色:SpeechRecognition。
识别语音需要音频输入, 而SpeechRecognition使得检索此输入非常容易。无需构建用于访问麦克风和从头开始处理音频文件的脚本, SpeechRecognition只需几分钟即可启动并运行。
SpeechRecognition库充当几种流行语音API的包装, 因此非常灵活。其中之一(Google Web Speech API)支持一个默认API密钥, 该密钥被硬编码到SpeechRecognition库中。这意味着你无需注册服务就可以站起来。
SpeechRecognition包的灵活性和易用性使其成为任何Python项目的绝佳选择。但是, 不能保证支持它包装的每个API的每个功能。你将需要花费一些时间来研究可用的选项, 以找出SpeechRecognition在你的特定情况下是否可以工作。
因此, 既然你确信应该尝试语音识别, 那么下一步就是将其安装在你的环境中。
安装语音识别
SpeechRecognition与Python 2.6、2.7和3.3+兼容, 但是需要一些额外的Python 2安装步骤。在本教程中, 我假设你使用的是Python 3.3+。
你可以使用pip在终端上安装SpeechRecognition:
$ pip install SpeechRecognition
安装后, 你应该通过打开解释器会话并键入以下命令来验证安装:
>>>
>>> import speech_recognition as sr
>>> sr.__version__
'3.8.1'
注意:你获得的版本号可能会有所不同。在撰写本文时, 版本3.8.1是最新的。
继续进行此会议。稍后, 你将开始使用它。
如果你需要做的就是使用现有的音频文件, 那么语音识别即开即用。但是, 特定的用例需要一些依赖性。值得注意的是, 需要PyAudio软件包来捕获麦克风输入。
在进一步阅读时, 你将看到需要哪些依赖项。现在, 让我们深入了解该软件包的基础知识。
移除广告
识别器类
SpeechRecognition中的所有魔力都发生在Recognizer类中。
当然, Recognizer实例的主要目的是识别语音。每个实例都具有用于识别来自音频源的语音的各种设置和功能。
创建Recognizer实例很容易。在当前的解释器会话中, 键入:
>>>
>>> r = sr.Recognizer()
每个Recognizer实例都有七种使用各种API从音频源识别语音的方法。这些是:
- recognize_bing(): Microsoft Bing Speech
- accept_google():Google Web语音API
- ognize_google_cloud():Google Cloud Speech-需要安装google-cloud-speech软件包
- ognize_houndify():通过SoundHound进行猎犬化
- ognize_ibm():IBM语音转文本
- ognize_sphinx():CMU Sphinx-需要安装PocketSphinx
- accept_wit():Wit.ai
在这七个中, 只有Recognize_sphinx()与CMU Sphinx引擎脱机工作。其他六个都需要互联网连接。
关于每个API的功能和优点的完整讨论超出了本教程的范围。由于SpeechRecognition随附了Google Web Speech API的默认API密钥, 因此你可以立即开始使用它。因此, 我们将在本指南中使用Web Speech API。其他六个API都需要使用API密钥或用户名/密码组合进行身份验证。有关更多信息, 请查阅SpeechRecognition文档。
警告:SpeechRecognition提供的默认密钥仅用于测试目的, Google可以随时将其撤消。在生产中使用Google Web Speech API并不是一个好主意。即使使用有效的API密钥, 你每天也只能限制50个请求, 并且无法提高此配额。幸运的是, 每个API的SpeechRecognition界面几乎相同, 因此你今天所学的内容将很容易转化为真实项目。
如果API无法访问, 则每个Recognize _ *()方法都会引发Speech_recognition.RequestError异常。对于ognize_sphinx(), 这可能是由于缺少, 损坏或不兼容的Sphinx安装而发生的。对于其他六个方法, 如果满足配额限制, 服务器不可用或没有互联网连接, 则可能引发RequestError。
好的, 闲聊。让我们弄脏双手。继续, 尝试在你的解释器会话中调用ognize_google()。
>>>
>>> r.recognize_google()
发生了什么?
你可能会得到如下所示的内容:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: recognize_google() missing 1 required positional argument: 'audio_data'
你可能已经猜到会发生这种情况。怎么可能一无所获?
Recognizer类的所有七个Recognize _ *()方法都需要一个audio_data参数。在每种情况下, audio_data必须是SpeechRecognition的AudioData类的实例。
有两种创建AudioData实例的方法:从音频文件或麦克风录制的音频。音频文件入门起来比较容易一些, 所以让我们先来看一下。
处理音频文件
在继续之前, 你需要下载一个音频文件。我以前开始使用的那个文件“ harvard.wav”可以在这里找到。确保将其保存到运行Python解释器会话的目录中。
凭借其方便的AudioFile类, SpeechRecognition使处理音频文件变得容易。此类可以使用音频文件的路径进行初始化, 并提供上下文管理器界面来读取和使用文件的内容。
移除广告
支持的文件类型
目前, SpeechRecognition支持以下文件格式:
- WAV:必须为PCM / LPCM格式
- 联合会
- 联合会
- FLAC:必须为本地FLAC格式;不支持OGG-FLAC
如果你使用的是基于x-86的Linux, macOS或Windows, 则应该能够使用FLAC文件而不会出现问题。在其他平台上, 你将需要安装FLAC编码器并确保可以访问flac命令行工具。如果适用, 你可以在这里找到更多信息。
使用record()从文件中捕获数据
在解释器会话中键入以下内容, 以处理“ harvard.wav”文件的内容:
>>>
>>> harvard = sr.AudioFile('harvard.wav')
>>> with harvard as source:
... audio = r.record(source)
...
上下文管理器打开文件并读取其内容, 然后将数据存储在名为source的AudioFile实例中。然后record()方法将整个文件中的数据记录到AudioData实例中。你可以通过检查音频类型来确认这一点:
>>>
>>> type(audio)
<class 'speech_recognition.AudioData'>
现在, 你可以调用identify_google()尝试识别音频中的任何语音。根据你的Internet连接速度, 你可能需要等待几秒钟才能看到结果。
>>>
>>> r.recognize_google(audio)
'the stale smell of old beer lingers it takes heat
to bring out the odor a cold dip restores health and
zest a salt pickle taste fine with ham tacos al
Pastore are my favorite a zestful food is the hot
cross bun'
恭喜你!你刚刚转录了第一个音频文件!
如果你想知道“ harvard.wav”文件中的短语从何而来, 它们就是哈佛句子的示例。这些短语由IEEE于1965年发布, 用于电话线的语音清晰度测试。今天, 它们仍用于VoIP和蜂窝测试中。
哈佛句子由十个短语的72个列表组成。你可以在Open Speech Repository网站上找到这些短语的免费录音。提供英语, 汉语普通话, 法语和北印度语录音。他们提供了免费的免费材料来测试你的代码。
捕获具有偏移量和持续时间的线段
如果你只想捕获文件中语音的一部分怎么办? record()方法接受一个duration关键字参数, 该参数在指定的秒数后停止记录。
例如, 以下内容捕获文件前四秒内的所有语音:
>>>
>>> with harvard as source:
... audio = r.record(source, duration=4)
...
>>> r.recognize_google(audio)
'the stale smell of old beer lingers'
在with块中使用record()方法时, 它总是在文件流中向前移动。这意味着, 如果先录制一次四秒钟, 然后再录制四秒钟, 则第二次将返回前四秒之后的四秒音频。
>>>
>>> with harvard as source:
... audio1 = r.record(source, duration=4)
... audio2 = r.record(source, duration=4)
...
>>> r.recognize_google(audio1)
'the stale smell of old beer lingers'
>>> r.recognize_google(audio2)
'it takes heat to bring out the odor a cold dip'
请注意, audio2包含文件中第三个短语的一部分。指定持续时间时, 录制可能会停止中段, 甚至中单词, 这会损害转录的准确性。对此有更多的了解。
除了指定记录持续时间外, 还可以使用offset关键字参数为record()方法指定特定的起点。此值表示从文件开头开始记录之前要忽略的秒数。
要仅捕获文件中的第二个短语, 可以以四秒的偏移量开始并记录三秒钟。
>>>
>>> with harvard as source:
... audio = r.record(source, offset=4, duration=3)
...
>>> r.recognize_google(audio)
'it takes heat to bring out the odor'
如果你事先了解文件中语音的结构, 则offset和duration关键字参数对于分段音频文件很有用。但是, 匆忙使用它们会导致较差的转录。要查看此效果, 请在解释器中尝试以下操作:
>>>
>>> with harvard as source:
... audio = r.record(source, offset=4.7, duration=2.8)
...
>>> r.recognize_google(audio)
'Mesquite to bring out the odor Aiko'
通过在4.7秒开始录制, 你会错过“ it t”部分, 即短语“它需要加热才能散发出气味”的开头, 因此API仅获得了“吸收热量”, 与“ Mesquite”相匹配。 ”
同样, 在录制的结尾, 你捕获了“ a co”, 这是第三个短语“冷浸可以恢复健康和热情的开始”。 API将其与“ Aiko”匹配。
还有一个原因可能是你的转录不正确。噪声!上面的示例效果很好, 因为音频文件相当干净。在现实世界中, 除非你有机会事先处理音频文件, 否则不能指望音频没有噪音。
移除广告
噪声对语音识别的影响
噪音是生活的事实。所有音频记录中都有一定程度的噪声, 未处理的噪声会破坏语音识别应用程序的准确性。
要了解噪声如何影响语音识别, 请在此处下载“ jackhammer.wav”文件。与往常一样, 请确保将其保存到翻译会话的工作目录中。
该文件中带有“老啤酒残留的陈旧气味”一词, 在背景中用响亮的手提钻说出来。
当你尝试转录此文件时会发生什么?
>>>
>>> jackhammer = sr.AudioFile('jackhammer.wav')
>>> with jackhammer as source:
... audio = r.record(source)
...
>>> r.recognize_google(audio)
'the snail smell of old gear vendors'
滚开!
那么你如何处理呢?你可以尝试的一件事是使用Recognizer类的Adjust_for_ambient_noise()方法。
>>>
>>> with jackhammer as source:
... r.adjust_for_ambient_noise(source)
... audio = r.record(source)
...
>>> r.recognize_google(audio)
'still smell of old beer vendors'
这样可以使你更接近实际的词组, 但这仍然不是完美的。另外, 短语开头没有“ the”。这是为什么?
Adjust_for_ambient_noise()方法读取文件流的第一秒, 并将识别器校准为音频的噪声水平。因此, 在调用record()捕获数据之前要消耗掉流的那部分。
你可以使用duration关键字参数来调整Adjust_for_ambient_noise()用于分析的时间范围。此参数采用秒为单位的数值, 默认情况下设置为1。尝试将此值降低到0.5。
>>>
>>> with jackhammer as source:
... r.adjust_for_ambient_noise(source, duration=0.5)
... audio = r.record(source)
...
>>> r.recognize_google(audio)
'the snail smell like old Beer Mongers'
好吧, 这让你在短语的开头有了“ the”, 但现在你遇到了一些新问题!有时无法消除噪声的影响-信号太嘈杂而无法成功处理。该文件就是这种情况。
如果你发现自己经常遇到这些问题, 则可能必须对音频进行一些预处理。这可以通过音频编辑软件或可以将过滤器应用于文件的Python软件包(例如SciPy)来完成。有关此内容的详细讨论超出了本教程的范围, 如果你有兴趣, 请查阅Allen Downey的Think DSP书籍。现在, 请注意音频文件中的环境噪声可能会引起问题, 必须加以解决才能使语音识别的准确性最大化。
使用嘈杂的文件时, 查看实际的API响应可能会有所帮助。大多数API返回包含许多可能的转录的JSON字符串。除非你强迫它提供完整的响应, 否则identify_google()方法将始终返回最可能的转录。
你可以通过将Recognize_google()方法的show_all关键字参数设置为True来实现。
>>>
>>> r.recognize_google(audio, show_all=True)
{'alternative': [
{'transcript': 'the snail smell like old Beer Mongers'}, {'transcript': 'the still smell of old beer vendors'}, {'transcript': 'the snail smell like old beer vendors'}, {'transcript': 'the stale smell of old beer vendors'}, {'transcript': 'the snail smell like old beermongers'}, {'transcript': 'destihl smell of old beer vendors'}, {'transcript': 'the still smell like old beer vendors'}, {'transcript': 'bastille smell of old beer vendors'}, {'transcript': 'the still smell like old beermongers'}, {'transcript': 'the still smell of old beer venders'}, {'transcript': 'the still smelling old beer vendors'}, {'transcript': 'musty smell of old beer vendors'}, {'transcript': 'the still smell of old beer vendor'}
], 'final': True}
如你所见, Recognize_google()返回一个带有键“ alternative”的字典, 该字典指向可能的成绩单列表。该响应的结构可能因API而异, 并且主要用于调试。
到目前为止, 你已经对SpeechRecognition包的基础知识有了很好的了解。你已经了解了如何从音频文件创建AudioFile实例, 以及如何使用record()方法从文件中捕获数据。你了解了如何使用record()的offset和duration关键字参数来记录文件的记录段, 并体验了噪声可能对转录精度产生的不利影响。
现在是有趣的部分。通过接受麦克风的输入, 让我们从录制静态音频文件过渡到使你的项目具有交互性。
移除广告
使用麦克风
要使用SpeechRecognizer访问麦克风, 你必须安装PyAudio软件包。继续并关闭当前的口译会话, 然后执行此操作。
安装PyAudio
根据你的操作系统, 安装PyAudio的过程会有所不同。
Debian Linux
如果你使用的是基于Debian的Linux(例如Ubuntu), 则可以使用apt安装PyAudio:
$ sudo apt-get install python-pyaudio python3-pyaudio
安装后, 你可能仍需要运行pip install pyaudio, 尤其是在虚拟环境中工作时。
操作系统
对于macOS, 首先需要使用Homebrew安装PortAudio, 然后使用pip安装PyAudio:
$ brew install portaudio
$ pip install pyaudio
视窗
在Windows上, 你可以使用pip安装PyAudio:
$ pip install pyaudio
测试安装
安装PyAudio后, 你可以从控制台测试安装。
$ python -m speech_recognition
确保默认麦克风已打开且未静音。如果安装成功, 你应该会看到以下内容:
A moment of silence, please...
Set minimum energy threshold to 600.4452854381937
Say something!
注意:如果你使用的是Ubuntu, 并获得一些时髦的输出, 例如“ ALSA lib…Unknown PCM”, 请参阅此页面以获取禁止显示这些消息的提示。此输出来自随Ubuntu一起安装的ALSA软件包, 而不是SpeechRecognition或PyAudio。在现实中, 这些消息可能表明你的ALSA配置存在问题, 但是根据我的经验, 它们不会影响代码的功能。它们主要是令人讨厌的。
移除广告
麦克风类
打开另一个解释器会话, 并创建识别器类的实例。
>>>
>>> import speech_recognition as sr
>>> r = sr.Recognizer()
现在, 你将使用默认的系统麦克风, 而不是使用音频文件作为源。你可以通过创建Microphone类的实例来访问它。
>>>
>>> mic = sr.Microphone()
如果你的系统没有默认麦克风(例如RaspberryPi上的麦克风), 或者你要使用默认麦克风以外的其他麦克风, 则需要通过提供设备索引来指定要使用哪个麦克风。你可以通过调用Microphone类的list_microphone_names()静态方法来获取麦克风名称列表。
>>>
>>> sr.Microphone.list_microphone_names()
['HDA Intel PCH: ALC272 Analog (hw:0, 0)', 'HDA Intel PCH: HDMI 0 (hw:0, 3)', 'sysdefault', 'front', 'surround40', 'surround51', 'surround71', 'hdmi', 'pulse', 'dmix', 'default']
请注意, 你的输出可能与以上示例不同。
麦克风的设备索引是其名称在list_microphone_names()返回的列表中的索引。例如, 给定以上输出, 如果你要使用名为“ front”的麦克风, 该麦克风在列表中的索引为3, 则可以创建一个麦克风实例, 如下所示:
>>>
>>> # This is just an example; do not run
>>> mic = sr.Microphone(device_index=3)
不过, 对于大多数项目, 你可能需要使用默认的系统麦克风。
使用listen()捕获麦克风输入
现在你已经准备好使用麦克风实例, 是时候捕获一些输入了。
就像AudioFile类一样, Microphone是上下文管理器。你可以使用with块内Recognizer类的listen()方法捕获来自麦克风的输入。此方法将音频源作为其第一个参数, 并记录来自该源的输入, 直到检测到静音为止。
>>>
>>> with mic as source:
... audio = r.listen(source)
...
一旦执行with块, 请尝试对着麦克风说“你好”。请稍等片刻, 以再次显示解释器提示。返回“ >>>”提示后, 你就可以识别语音了。
>>>
>>> r.recognize_google(audio)
'hello'
如果提示从不消失, 则很可能是你的麦克风拾取了太多的环境噪声。你可以使用+ ctrl + c ++中断该过程以返回提示。
要处理环境噪声, 你需要使用Recognizer类的Adjust_for_ambient_noise()方法, 就像你尝试理解嘈杂的音频文件一样。由于来自麦克风的输入比来自音频文件的输入要难预测得多, 因此在你收听麦克风输入时随时执行此操作是一个好主意。
>>>
>>> with mic as source:
... r.adjust_for_ambient_noise(source)
... audio = r.listen(source)
...
运行完上面的代码后, 请等待一秒钟以使Adjust_for_ambient_noise()起作用, 然后尝试对着麦克风说“你好”。同样, 你将需要等待片刻, 以便口译员提示返回, 然后再尝试识别语音。
回想一下Adjust_for_ambient_noise()分析音频源一秒钟。如果这对你来说似乎太长了, 请随时使用duration关键字参数进行调整。
SpeechRecognition文档建议使用持续时间不少于0.5秒。在某些情况下, 你可能会发现持续时间长于默认值一秒会产生更好的结果。你所需的最小值取决于麦克风的周围环境。不幸的是, 这些信息在开发过程中通常是未知的。以我的经验, 一秒钟的默认持续时间对于大多数应用程序来说足够了。
移除广告
处理无法识别的语音
尝试在交织器中键入前面的代码示例, 并向麦克风发出一些难以理解的噪音。你应该得到如下响应:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/home/david/real_python/speech_recognition_primer/venv/lib/python3.5/site-packages/speech_recognition/__init__.py", line 858, in recognize_google
if not isinstance(actual_result, dict) or len(actual_result.get("alternative", [])) == 0: raise UnknownValueError()
speech_recognition.UnknownValueError
API无法将其与文本匹配的音频会引发UnknownValueError异常。你应该始终使用try和except块包装对API的调用, 以处理此异常。
注意:你可能需要付出比预期更多的努力才能引发异常。该API很难记录任何声音。对我来说, 即使是短暂的咕unt声也被转录为“如何”之类的词。咳嗽, 拍手和舌头咔嗒声会不断引发异常。
放在一起:“猜词”游戏
现在, 你已经了解了使用SpeechRecognition包识别语音的基本知识, 下面将让你使用新发现的知识, 并编写一个小型游戏, 该游戏从列表中选择一个随机单词, 并为用户提供了三种尝试猜单词的方法。
这是完整的脚本:
import random
import time
import speech_recognition as sr
def recognize_speech_from_mic(recognizer, microphone):
"""Transcribe speech from recorded from `microphone`.
Returns a dictionary with three keys:
"success": a boolean indicating whether or not the API request was
successful
"error": `None` if no error occured, otherwise a string containing
an error message if the API could not be reached or
speech was unrecognizable
"transcription": `None` if speech could not be transcribed, otherwise a string containing the transcribed text
"""
# check that recognizer and microphone arguments are appropriate type
if not isinstance(recognizer, sr.Recognizer):
raise TypeError("`recognizer` must be `Recognizer` instance")
if not isinstance(microphone, sr.Microphone):
raise TypeError("`microphone` must be `Microphone` instance")
# adjust the recognizer sensitivity to ambient noise and record audio
# from the microphone
with microphone as source:
recognizer.adjust_for_ambient_noise(source)
audio = recognizer.listen(source)
# set up the response object
response = {
"success": True, "error": None, "transcription": None
}
# try recognizing the speech in the recording
# if a RequestError or UnknownValueError exception is caught, # update the response object accordingly
try:
response["transcription"] = recognizer.recognize_google(audio)
except sr.RequestError:
# API was unreachable or unresponsive
response["success"] = False
response["error"] = "API unavailable"
except sr.UnknownValueError:
# speech was unintelligible
response["error"] = "Unable to recognize speech"
return response
if __name__ == "__main__":
# set the list of words, maxnumber of guesses, and prompt limit
WORDS = ["apple", "banana", "grape", "orange", "mango", "lemon"]
NUM_GUESSES = 3
PROMPT_LIMIT = 5
# create recognizer and mic instances
recognizer = sr.Recognizer()
microphone = sr.Microphone()
# get a random word from the list
word = random.choice(WORDS)
# format the instructions string
instructions = (
"I'm thinking of one of these words:\n"
"{words}\n"
"You have {n} tries to guess which one.\n"
).format(words=', '.join(WORDS), n=NUM_GUESSES)
# show instructions and wait 3 seconds before starting the game
print(instructions)
time.sleep(3)
for i in range(NUM_GUESSES):
# get the guess from the user
# if a transcription is returned, break out of the loop and
# continue
# if no transcription returned and API request failed, break
# loop and continue
# if API request succeeded but no transcription was returned, # re-prompt the user to say their guess again. Do this up
# to PROMPT_LIMIT times
for j in range(PROMPT_LIMIT):
print('Guess {}. Speak!'.format(i+1))
guess = recognize_speech_from_mic(recognizer, microphone)
if guess["transcription"]:
break
if not guess["success"]:
break
print("I didn't catch that. What did you say?\n")
# if there was an error, stop the game
if guess["error"]:
print("ERROR: {}".format(guess["error"]))
break
# show the user the transcription
print("You said: {}".format(guess["transcription"]))
# determine if guess is correct and if any attempts remain
guess_is_correct = guess["transcription"].lower() == word.lower()
user_has_more_attempts = i < NUM_GUESSES - 1
# determine if the user has won the game
# if not, repeat the loop if user has more attempts
# if no attempts left, the user loses the game
if guess_is_correct:
print("Correct! You win!".format(word))
break
elif user_has_more_attempts:
print("Incorrect. Try again.\n")
else:
print("Sorry, you lose!\nI was thinking of '{}'.".format(word))
break
让我们分解一下。
ognize_speech_from_mic()函数将Recognizer和Microphone实例作为参数, 并返回具有三个键的字典。第一个键“ success”是一个布尔值, 指示API请求是否成功。第二个键“错误”是“无”或错误消息, 指示API不可用或语音难以理解。最后, “转录”键包含麦克风记录的音频的转录。
该函数首先检查识别器和麦克风参数的类型是否正确, 如果其中一个无效, 则引发TypeError:
if not isinstance(recognizer, sr.Recognizer):
raise TypeError('`recognizer` must be `Recognizer` instance')
if not isinstance(microphone, sr.Microphone):
raise TypeError('`microphone` must be a `Microphone` instance')
然后, 使用listen()方法记录麦克风输入:
with microphone as source:
recognizer.adjust_for_ambient_noise(source)
audio = recognizer.listen(source)
每次调用identify_speech_from_mic()函数时, adjust_for_ambient_noise()方法用于校准识别器以更改噪声条件。
接下来, 调用invoke_google()来转录录音中的所有语音。 try … except块用于捕获RequestError和UnknownValueError异常并进行相应处理。 API请求的成功, 任何错误消息和转录的语音都存储在响应字典的成功, 错误和转录键中, 该键由Recognize_speech_from_mic()函数返回。
response = {
"success": True, "error": None, "transcription": None
}
try:
response["transcription"] = recognizer.recognize_google(audio)
except sr.RequestError:
# API was unreachable or unresponsive
response["success"] = False
response["error"] = "API unavailable"
except sr.UnknownValueError:
# speech was unintelligible
response["error"] = "Unable to recognize speech"
return response
你可以通过将上面的脚本保存到名为“ guessing_game.py”的文件并在解释器会话中运行以下命令来测试ognize_speech_from_mic()函数:
>>>
>>> import speech_recognition as sr
>>> from guessing_game import recognize_speech_from_mic
>>> r = sr.Recognizer()
>>> m = sr.Microphone()
>>> recognize_speech_from_mic(r, m)
{'success': True, 'error': None, 'transcription': 'hello'}
>>> # Your output will vary depending on what you say
游戏本身非常简单。首先, 声明单词列表, 允许的最大猜测数和提示限制:
WORDS = ['apple', 'banana', 'grape', 'orange', 'mango', 'lemon']
NUM_GUESSES = 3
PROMPT_LIMIT = 5
接下来, 创建一个Recognizer and Microphone实例, 并从WORDS中选择一个随机单词:
recognizer = sr.Recognizer()
microphone = sr.Microphone()
word = random.choice(WORDS)
在打印了一些指令并等待3三秒钟后, 将使用for循环来管理每个用户猜测所选单词的尝试。 for循环内的第一件事是另一个for循环, 该循环最多提示用户PROMPT_LIMIT次进行猜测, 每次尝试使用ognize_speech_from_mic()函数识别输入, 并将返回的字典存储到局部变量guess中。
如果猜测的“转录”键不是“无”, 则转录用户的语音, 并以中断方式终止内部循环。如果语音未转录, 并且“成功”键设置为False, 则发生API错误, 并且循环再次中断。否则, API请求成功, 但语音无法识别。将警告用户, 并重复for循环, 使用户有机会再次尝试当前尝试。
for j in range(PROMPT_LIMIT):
print('Guess {}. Speak!'.format(i+1))
guess = recognize_speech_from_mic(recognizer, microphone)
if guess["transcription"]:
break
if not guess["success"]:
break
print("I didn't catch that. What did you say?\n")
内部for循环终止后, 将检查guess词典是否有错误。如果发生任何错误, 将显示错误消息, 并且外部for循环以break终止, 这将终止程序执行。
if guess['error']:
print("ERROR: {}".format(guess["error"]))
break
如果没有任何错误, 会将抄写与随机选择的单词进行比较。字符串对象的lower()方法用于确保猜测与所选单词的更好匹配。 API可能会返回与单词“ apple”匹配的语音, 例如“ Apple”或“ apple”, 并且任何一个响应都应视为正确答案。
如果猜测正确, 则用户获胜并且游戏终止。如果用户不正确并且有任何剩余尝试, 则外部for循环将重复并检索新的猜测。否则, 用户将输掉游戏。
guess_is_correct = guess["transcription"].lower() == word.lower()
user_has_more_attempts = i < NUM_GUESSES - 1
if guess_is_correct:
print('Correct! You win!'.format(word))
break
elif user_has_more_attempts:
print('Incorrect. Try again.\n')
else:
print("Sorry, you lose!\nI was thinking of '{}'.".format(word))
break
运行时, 输出将如下所示:
I'm thinking of one of these words:
apple, banana, grape, orange, mango, lemon
You have 3 tries to guess which one.
Guess 1. Speak!
You said: banana
Incorrect. Try again.
Guess 2. Speak!
You said: lemon
Incorrect. Try again.
Guess 3. Speak!
You said: Orange
Correct! You win!
移除广告
回顾与其他资源
在本教程中, 你已经了解了如何安装SpeechRecognition程序包并使用其Recognizer类轻松地从文件(使用record())和麦克风输入(使用listen())中识别语音。你还看到了如何使用record()方法的offset和duration关键字参数来处理音频文件的片段。
你已经了解了噪声对转录准确性的影响, 并且学习了如何通过Adjust_for_ambient_noise()来调整Recognizer实例对环境噪声的敏感度。你还了解了Recognizer实例可能会抛出哪些异常(针对错误的API请求的RequestError和针对难以理解的语音的UnkownValueError)以及如何使用try … except块处理这些异常。
语音识别是一门很深的主题, 你在这里学到的知识几乎没有触及表面。如果你想了解更多信息, 这里有一些其他资源。
免费奖金:单击此处下载具有完整源代码的Python语音识别示例项目, 你可以将其用作自己的语音识别应用程序的基础。
有关SpeechRecognition包的更多信息:
- 图书馆参考
- 例子
- 故障排除页面
一些有趣的互联网资源:
- 麦克风背后:与计算机对话的科学。 Google制作的有关语音处理的短片。
- Huang, Baker和Reddy的语音识别的历史视角。 ACM通讯(2014)。本文对语音识别技术的发展进行了深入的学术研究。
- 克拉克·博伊德(Clark Boyd)在创业公司的语音识别技术的过去, 现在和未来。这篇博客文章概述了语音识别技术, 并对未来有所思考。
一些有关语音识别的好书:
- 机器中的声音:构建可理解语音的计算机, 皮拉契奇尼(Pieraccini), 麻省理工学院出版社(2012)。一本通俗易懂的一般听书, 内容涉及语音处理的历史以及现代进展。
- 语音识别基础, Rabiner和Juang, Prentice Hall(1993)。贝尔实验室的研究员Rabiner在设计一些最早的商业上可行的语音识别器时发挥了作用。这本书已经有20多年的历史了, 但是许多基本原理都保持不变。
- 自动语音识别:一种深度学习方法, 于和邓, 施普林格(2014)。 Yu和Deng是Microsoft的研究人员, 在语音处理领域都非常活跃。本书涵盖了许多现代方法和前沿研究, 但不适用于数学上微弱的人。
附录:识别英语以外的其他语言的语音
在本教程中, 我们一直以英语识别语音, 这是SpeechRecognition程序包中每种ognize _ *()方法的默认语言。但是, 绝对有可能识别其他语言的语音, 并且非常容易实现。
要识别其他语言的语音, 请将Recognize _ *()方法的language关键字参数设置为与所需语言相对应的字符串。大多数方法都接受BCP-47语言标签, 例如美国英语为“ en-US”, 法语为“ fr-FR”。例如, 以下内容可识别音频文件中的法语语音:
import speech_recognition as sr
r = sr.Recognizer()
with sr.AudioFile('path/to/audiofile.wav') as source:
audio = r.record(source)
r.recognize_google(audio, language='fr-FR')
仅以下方法接受language关键字参数:
- recognize_bing()
- recognize_google()
- recognize_google_cloud()
- recognize_ibm()
- recognize_sphinx()
要找出你所使用的API支持哪些语言标签, 你必须查阅相应的文档。可在此Stack Overflow答案中找到被Recognize_google()接受的标签列表。