使用 Vosk 实现语音识别
在近两年里,如果说想要在本地部署离线语音识别模型,那么 Whisper 和 FunASR 肯定是首选项。所以为什么要使用 Vosk 呢?
优势
Vosk 是一个离线开源语音识别工具包,它的优点在于:
- 轻量:Vosk 提供轻量级的模型(小于 50MB 大小),可以用于低功耗平台(例如 Android、树莓派之类)
- 多编程语言、多平台支持:Python、Java、Node.js、C#、C++、Rust、Go 等
- 多语种支持:支持二十多种语言的识别(包括中文)
- 实时性:实时性语音识别场景下,vosk 的延迟非常低
简单来讲,你电脑中有 Python 环境,再下载一个 50 MB 的模型,就可以用 Vosk 实现一个正确率还可以接受的语言识别相关的项目。而像 Whisper 虽然识别效果好,但是对硬件要求很高,同时部署起来麻烦(例如需要配置 CUDA 环境),另外也不是很适用于实时性场景。
使用
这里以 Python 为例,首先安装 Vosk:pip3 install vosk pyaudio。
音频文件识别
以下代码实现对 test.wav 音频文件中语音内容的识别。
1 | import wave |
解释一下上述 Vosk 相关代码调用:
- 首先
SetLogLevel(-1)用来控制运行过程中日志打印,这里为了清晰的输出选择关闭日志。 - 之后初始化语音识别模型,这里通过指定模型路径的方式完成:
Model(model_path="/path/to/vosk-model-small-en-us-0.15"),模型的下载地址可以参考官网。 - 然后创建
KaldiRecognizer对象,SetWords(True)的作用是后续调用Result()和FinalResult()方法时将在输出中包含识别的单词及其时间戳,SetPartialWords(True)同理。 rec.AcceptWaveform(data)相关代码的逻辑是:如果AcceptWaveform()方法返回True,表明语音识别过程已经找到了一个或多个稳定的词语(比如,话语的间隙或者片段的终点),并且可以通过Result()方法获取完整的识别结果(返回识别的语句,可能包含了多个词语);如果返回False,表明语音识别过程还在继续,还没找到稳定的词语,可以通过PartialResult()方法获取部分识别结果(返回的只是当前识别的部分信息,可能只包含一个或者部分词语)。- 最后
rec.FinalResult()用来在每次完成一段完整的音频处理(如一句话或一段对话)时调用,用于获取该段音频的最后一部分识别结果。
麦克风输入
以下代码利用 PyAudio 实现从麦克风中获取音频输入,并利用 Vosk 完成语言识别。
1 | rec = KaldiRecognizer(model, 16000) |
补充
- 如果只想获得识别结果文本,可以将
rec.Result()改为json.loads(rec.Result())["text"],将rec.FinalResult()改为json.loads(rec.FinalResult())["text"]。但是注意rec.PartialResult()不存在text键。 KaldiRecognizer对象存在Reset()方法,调用它会重置识别器到初始状态,这意味着识别器会清除之前处理的所有音频数据和中间状态,使用Reset()方法可以在不创建新识别器的情况下开始新的一轮语音识别。KaldiRecognizer对象存在SetMaxAlternatives(num)方法,用来设置识别结果的最大候选项数量,之后Result()和FinalResult()方法将会在输出中包含最容易识别为正确结果的num个候选项。KaldiRecognizer对象可以使用SetGrammar(json.dumps(grammar_list))方法,可以用它来设置特定的语法集,这意味着它定义了语音识别应该识别的确切词或短语模式。通俗的来讲,可以把它看作是为识别器编写的一个“听力测试”,测试中只包括预先编写好的词汇和句型。这样识别器就可以忽略无关的语音,只专注于理解这个集合中的内容。