Python教程-Python语音识别
你是否曾经想过Google助手或Amazon Alexa是如何识别你所说的一切的?你一定会认为背后有一些复杂的智能技术在运作。除了在庞大的技术增长市场中取得巨大成功的语音识别系统之外,绝大多数手机设备都具备语音识别功能,通过一些内置应用程序或第三方应用程序实现。然而,并不是所有的语音识别系统都需要复杂的技术。事实上,大多数这种语音识别系统是通过Python包和库来构建和部署的。在某种程度上,Python已经证明它是可预见的未来的一个重要组成部分。原因非常明显。要在Python中整合语音识别,你需要一定程度的互动性和可访问性,以匹配技术。
可访问性的概念值得考虑,因为语音识别允许老年人、身体有障碍或视障人士与机器互动,并迅速解决他们的问题,而不是选择随机的图形用户界面应用程序。
在本文中,您将学习如何在Python中创建一个语音识别系统。为了更轻松地理解它是如何构建的,本文旨在教你如何以更少的努力和更多的热情构建该系统。但在进入项目之前,让我们先谈谈作为开发者需要了解的一些更重要的方面。
概述 - 它是如何工作的
在深入了解项目的细节和复杂性之前,您将首先建立一个对语音识别工作原理的整体了解。虽然您不需要任何先决条件就可以开始学习,但了解Python编程语言的基本原理是很有帮助的。
语音识别起源于贝尔实验室在1950年进行的研究,当时它只能处理单个说话者的语音并具有有限的词汇数据库。现代的语音识别应用程序自从古老的同行开始以来已经取得了长足的进步。
谈到语音的组成部分,第一部分是语音。它必须从声音转换为可以通过麦克风传输并转录为数字数据的信号。这是通过模拟到数字转换器来完成的。一旦数据被数字化,多个经过训练的模型可以轻松地将音频转录为文本。
现代语音识别器依赖于隐马尔可夫模型(Hidden Markov Model,HMM)这一不太为人所知的概念。该方法基于一种假设,即当语音信号持续存在一小段时间(比如五毫秒)时,它可以被称为一个静态过程,即一种基于不随时间而改变的统计数据的过程。
在典型的HMM中,语音的默认信号分割为约十毫秒,分成各种片段。每个片段的功率谱有助于信号绘制函数并生成后来映射到称为倒谱系数(cepstral coefficients)的实数向量的频率。映射向量的维数非常小,低至十,与一些精确系统可能有32或更多的维数相比。HMM生成的最终输出以向量序列的形式呈现。
向量组在使用语音的基本单位音素(phonemes)的帮助下,起到了将语音解码为文本的重要作用。音素的计算取决于训练,因为存在说话者差异,即使对于同一说话者,语音有时也不同。因此,为了应对这个问题,考虑了一个特殊的算法,它确定了生成音素序列的最相关单词。
刚刚学到的整个过程在计算方面相当昂贵。在现代语音识别系统中,神经网络用于转换特征和维度,从而减少对HMM的需求。此外,还使用声音活动检测器(Voice Activity Detectors,VAD)来减少可能包含一些语音的音频信号的一部分。它主要用于识别不必要的语音部分,以防止它们被考虑在内。
语音识别包
有一些语音识别包存在于PyPI(Python软件包索引链)中。其中一些包括:
- Assembly
- Apia
- SpeechRecognition
- Wit
- Watson-developer-cloud
上述包中,例如apiai和wit等包提供了类似自然语言处理的功能。它们内置的功能有助于识别说话者的意图,并超越通用的语音识别。其他包主要关注将语音转化为文本。
在上述提到的包中,SpeechRecognition包是脱颖而出的一个。
要识别语音,需要一些音频输入,而SpeechRecognition包可以轻松地检索这些类型的输入。它无需复杂的脚本来访问麦克风,然后从头开始处理音频。此包的另一个优点是它可以节省您的时间,只需几分钟就可以执行指令。
SpeechRecognition库就像是为语音而建的各种API的包装器。它非常灵活和敏捷。其中一个这样的API是Google Web Speech API,它支持硬编码的默认语音识别。
需要注意的是,这个包可能不包含所有当今可用的API。因此,您需要准确确定您需要构建的语音识别器的类型。
您可能已经从理论上了解了一些语音识别器的优点和缺点,以及语音识别器是如何工作的概述,接下来让我们通过以下的安装步骤,将SpeechRecognition包安装到本地环境中。
安装SpeechRecognition
SpeechRecognition包兼容各种版本的Python语言,如2.6、2.7和3.3+。如果您的Python版本较老,可能还需要进行其他安装。假设您的本地系统上已安装了Python 3.3+版本,您可以通过终端运行以下命令来进行安装:
$ pip install SpeechRecognition
安装完成后,您需要验证安装是否正确,可以使用以下代码进行验证:
>>> import speech_recognition as sr
gt;>> sr._version_'3.8.1'
SpeechRecognition在处理包中的音频文件时可能会表现得特别出色。然而,它可能还需要一些依赖项。因此,为了简化这个过程,PyAudio包可以帮助捕获来自麦克风的输入。
Recognizer类
SpeechRecognition的魔法发挥作用的地方在于Recognizer类的存在。Recognizer的主要目的是识别语音,包括不同语音的各种变化,然后从音频源获取功能并验证音频。要创建一个Recognizer,您需要创建它的实例。因此,在Python解释器中输入以下代码:
>>> r=sr.Recognizer()
有多种方法可以创建可以从音频源识别语音的Recognizer实例,其中一些列在下面。
recognize_bing(): Microsoft Bing Speech
recognize_google(): Google Web Speech API
recognize_google_cloud(): Google Cloud Speech - requires
installation of the google-cloud-speech package
recognize_houndify(): Houndify by SoundHound
recognize_ibm(): IBM Speech to Text
recognize_sphinx(): CMU Sphinx - requires installing PocketSphinx
recognize_wit(): Wit.ai
其中,recognize_sphinx()包旨在与CMU Sphinx Engine一起离线提供服务。其余的包需要互联网连接才能运作。
注意:必须小心SpeechRecognition中提供的默认密钥。它主要用于测试,并且出于安全原因,可能会被Google取消。因此,SpeechRecognition有一个API接口,可以将这些默认密钥转换成小心使用的密钥。
每个recognize_方法可能会引发一个名为speech_recognition.RequestError的异常。这可能是因为API无法访问,原因可能是由于安装损坏。对于上面列出的其他方法,如果达到其配额下的限制,或者服务器或互联网连接出现问题,也可能会生成RequestError。错误信息可能如下所示。
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: recognize_google() missing 1 required positional argument: 'audio_data'
使用音频文件
在使用Python中的SpeechRecognition包之前,您首先需要下载一个音频文件。SpeechRecognition使得通过将音频文件保存在当前运行Python解释器的目录中来处理音频文件变得非常容易。它通过使用AudioFile类来实现这一点。该类需要初始化并设置音频文件路径,以便上下文管理器提供了一个很好的界面来读取文件及其内容。
支持的文件类型
SpeechRecognition支持的文件格式类型如下:
- WAV:格式必须为PCM/LPCM
- AIFF
- AIFF-C
- FLAC:格式必须是原生FLAC
如果您有基于x-86的Windows、Linux或macOS系统,使用FLAC文件会更加方便。除了这些操作系统,您可能需要安装一个FLAC编码器,以便访问命令行工具。
使用record()捕获数据
record()函数用于使用Python解释器在文件中捕获数据。例如,文件名是"harvard.wav",那么可以使用以下方法来编码此方法:
>>> hardvard = sr.AudioFile('harvard.wav')
gt;>> with harvard as source:
Audio = r.record(source)
该代码将打开上下文管理器,以读取文件的内容,并将数据存储在名为source的AudioFile实例中。然后,record()方法记录文件中的实际数据。要验证数据是否已记录,可以使用以下代码。
>>> type(audio)
<class' speech_recognition.AudioData'>
或者,您也可以调用recognize_google()方法,以便识别音频。识别的速度可能取决于您的互联网速度,音频是如何捕获的,以及多少秒内显示结果。
>>> r.recognize_google(audio)
该代码将转录文件中的所有数据,并以文本格式显示识别的音频。
持续时间和段偏移的捕获
假设您只想捕获文件中的特定段的语音。通过使用识别关键字,后跟在一些秒后停止语音的参数,record()方法可以实现这一点。例如,您可能需要从"harvard.wav"文件中捕获前5秒的语音。可以使用以下方法:
>>> with harvard as source:
Audio = r.record(source, duration=5)
>> >r.recognize_google(audio)
当用在块内时,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包含音频的第三部分。还有一些情况,如果指定了持续时间,则可能停止录制,这通常会损害音频的透明度。此外,指定record()方法时,还可以使用offset关键字来设置特定的起始点。起始点表示在录制开始之前的秒数。因此,要使用以下方法来捕获音频文件的第二个短语,您可以根据需要使用5秒或3秒。
>>> with harvard as source:
... audio = r.record(source, offset=4, duration=3)
...
>>> r.recognize_google(audio)
持续时间和偏移关键字的重要性在于对包含音频的文件进行分段。如果您已经知道音频帧,您可能会迅速陷入质量较差的转录结果。为了可视化这种效果,使用以下代码来尝试。
>>> with harvard as source:
... audio = r.record(source, offset=4.7, duration=2.8)
...
>>> r.recognize_google(audio)
上面的代码片段表示,录制从4.7秒开始,将遗漏开头的短语。类似地,当录制结束时,捕获的短语将不匹配开头的部分。
导致遗漏短语的另一个原因是噪音。上述示例可能有效,因为它是干净的音频,但在现实世界中没有噪音的地方。
噪音对语音识别的影响
没有任何地方是无噪音的。所有的语音识别技术都是为了解决和消除噪音而开发的,噪音会损害应用程序的准确性。要了解噪音如何影响语音识别,您需要下载一个名为"jackhammer.wav"的文件,并确保将其保存在您的解释器的工作目录中。假设这个文件中有大声说出的短语"javatiku is the best java training site",您需要在后台将其转录。为了做到这一点,请考虑以下方法。
>>> jackhammer = sr.AudioFile('jackhammer.wav')
>>> with jackhammer as source:
... audio = r.record(source)
...
>>> r.recognize_google(audio)
要处理噪音,可以在上面的步骤之后使用Recognizer类的adjust_for_ambient_noise()方法。
>>> with jackhammer as source:
... r.adjust_for_ambient_noise(source)
... audio = r.record(source)
...
>>> r.recognize_google(audio)
上面的代码片段将返回你之前错过的整个音频文件。然而,在某些情况下,很难处理或去除噪音的影响,因为信号可能过于嘈杂。
因此,你可能需要采用一些其他技术来预处理音频以处理这种问题。为此,你可以使用音频编辑软件或类似 SciPy 的 Python 包。该包可以对音频文件进行预处理并滤除噪音。
另外,在处理嘈杂的文件时,建议使用实际的 API 响应,因为大多数 API 返回包含许多转录的 JSON 字符串。类似地,recognize_google() 方法通常会返回类似的转录文件,除非强制它返回完整的响应。这可以通过使用特定的参数和关键字实际实现,例如 show_all,它适用于 recognize_google() 方法。
>>> r.recognize_google(audio, show_all=True)
alternative': [
{'transcript': 'javatiku best is the programming site'},
{'transcript': 'the javatiku site is best programming'},
{'transcript': 'javatiku programming is the best site'},
{'transcript': 'the programming is javatiku best site'},
{'transcript': 'best is the programming site javatiku'},
'final': True}
在上述代码片段中,recognize_google() 方法返回一个带有 alternative 键的字典,该键指向上面显示的各种转录。尽管响应结构可能因 API 不同而有不同的形式,但这主要用于调试。
到目前为止,你可能已经学会了 Python 中语音识别及其包的基础知识。学习的下一阶段涉及通过从麦克风获取输入,使项目变得更加互动。
使用麦克风输入
你可以使用 SpeechRecognizer 包来访问麦克风,需要安装名为 PyAudio 的包。为此,请保存当前的更改并关闭解释器。然后,继续按照与 SpeechRecognizer 相同的过程安装 PyAudio。
$ pip install pyaudio
安装后,要测试它是否与你使用的 SpeechRecognizer 版本兼容,输入以下命令。
$ python -m speech_recognizer
完成此步骤后,确保默认麦克风已打开并取消静音。如果在安装和测试中没有遇到任何问题,你应该在终端上看到类似以下内容:
A moment of silence, please?
Set minimum energy threshold to 600.4452854381937
Say something!
尝试使用麦克风说话并测试 SpeechRecognizer 包如何转录你的讲话。
麦克风类
麦克风类用于创建系统实例以识别来自源的音频文件。要使用此类,需要打开另一个解释器会话并创建一个 Recognizer 类,如下所示。
>>> import speech_recognizer as sr
>>> r.=sr.Recognizer()
你需要使用系统的默认麦克风,而不是使用来自源的音频文件。你可以使用如下所示的方法来实现。
>>> mic = sr.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']
上述代码中定义的设备索引被称为索引,它包含系统上可用麦克风的名称列表。例如,在上述输出中,名称为 "front" 的麦克风位于列表中的索引 3 处。可以使用以下方法来完成这个操作。
>>> mic = sr.Microphone(device_index=3)
上面的代码只是一个示例,因此建议不要在解释器中运行它。对于大多数项目,应该使用系统的默认麦克风。
使用 listen() 捕获麦克风输入
在这里,你将学习的另一种方法是 listen() 方法,用于从麦克风捕获输入。由于已经创建了麦克风实例,现在是捕获一些输入的合适时机。与大多数 AudioFile 类一样,麦克风也被视为上下文管理器。它通过 Recognizer 类捕获输入,Recognizer 类具有一个块,接受它作为第一个参数,然后从源中记录输入,直到麦克风检测到静音。为了解决这个问题,让我们看看如何使用给定的代码来应用它。
>>> with mic as source:
... audio = r.listen(source)
...
一旦执行了上述代码块,你应该尝试对着麦克风说点什么并等待一段时间。一段时间后,解释器可能提示显示。一旦看到 ">>>" 作为返回提示,可以确保 Recognizer 能够识别你说的任何话。
如果 Recognizer 未能返回提示,可能会捕获到一些环境噪音。你可以通过按下 Ctrl+C 来中断它。
为了调整你的讲话中存在的噪音,你可能需要使用 Recognizer 类的 adjust_for_ambient_noise() 方法,与音频文件不同,麦克风输入是不可预测的,因此在侦听麦克风输入时始终执行这些操作是一个好主意。为了获得精确且无噪音的输出,可以尝试使用 listen() 方法,如下所示。
>>> with mic as source:
... r.adjust_for_ambient_noise(source)
... audio = r.listen(source)
...
当运行上述代码后,等待几秒钟,以便 adjust_for_ambient_noise() 方法执行任务。在编译和运行代码后,尝试对着麦克风说点什么,并等待解释器识别讲话。如果它能够识别并返回提示,那么一切正常。
你还可以使用 duration 关键字,尝试再次使用它来获取要识别的特定讲话帧。同时,SpeechRecognizer 文档建议如果 duration 关键字的持续时间为 0.5 或更短,应使用它。在某些情况下可能不使用 duration 关键字,并且在这种情况下通常使用默认值以获得更好的结果。此外,值得注意的是,最小值可能取决于麦克风环境的输入。因此,一秒的持续时间通常被认为是这种任务的最佳选择。
无法识别的语音
使用麦克风在解释器中创建了一些具体的代码,以捕获一些难以理解的噪音。可以肯定会遇到像这样的错误:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File
"/home/david/real_python/speech_recognition_primer/venv/lib/pyth
on3.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 代码库无法高级地转录这些短促的嘶哑声音或声音。也可能会出现解释器识别当前输入并显示与通过麦克风捕获的声音完全不同的情况。因此,拍手声、点击声或其他噪音可能引发异常或无正确输出,分别出现这些情况。
总结
在这篇关于 Python 语音识别的长教程中,你从零开始学习了调度的工作方式。你涵盖了从概念知识到实际经验,创建了一个实时而简单的 Python 语音识别器,可以听到你的语音并以文本格式在控制台上显示。你还学到了一些处理在使用 SpeechRecognizer 包时常见的问题的关键方法,以及如何纠正这些问题。由于 Python 是广泛使用的编程和脚本语言,因此它可以处理关键问题,只需几行简单和可读的代码,这些问题得到了很好的解决。