openWakeWord
openWakeWord是一个开源的唤醒词库,可用于创建语音启用的应用程序和界面。它包含了预训练模型,适用于常见词语和短语,在实际环境中表现良好。
快速链接
更新
2024/02/11
- openWakeWord v0.6.0发布。有关新功能和变更的完整描述,请参阅发布说明。
2023/11/09
- 在
examples/web
下添加了示例脚本,演示如何将网页应用程序的音频流传输到openWakeWord。
2023/10/11
- 对训练新模型的流程进行了重大改进,包括一个Google Colab笔记本示例,演示如何在不到1小时内训练基本的唤醒词模型。
2023/06/15
- openWakeWord v0.5.0发布。有关新功能和变更的完整描述,请参阅发布说明。
演示
您可以通过HuggingFace Spaces在此处试用包含的预训练模型的在线演示!
请注意,在Spaces中,麦克风流的实时检测偶尔可能会出现异常行为。为了进行最可靠的测试,请按照下面的说明进行本地安装。
安装
安装openWakeWord非常简单,依赖项很少:
pip install openwakeword
在Linux系统上,onnxruntime包和tflite-runtime包都将作为依赖项安装,因为两种推理框架都受支持。在Windows上,由于缺乏对现代版本tflite的支持,只安装onnxruntime。
为了在Linux系统上(可选)使用Speex噪声抑制以提高在嘈杂环境中的性能,请安装Speex依赖项,然后安装预构建的Python包(在这里查看所有.whl版本的资源),根据您的Python版本和系统架构进行相应调整。
sudo apt-get install libspeexdsp-dev
pip install https://github.com/dscripka/openWakeWord/releases/download/v0.1.1/speexdsp_ns-0.1.2-cp38-cp38-linux_x86_64.whl
非常感谢TeaPoly提供的Speex噪声抑制库的Python封装。
使用
要进行快速本地测试,请克隆此仓库并使用包含的示例脚本尝试从本地麦克风进行流式检测。您可以从当前和过去的发布版本单独下载预训练模型,或者使用Python下载它们(见下文)。
将openWakeWord添加到您自己的Python代码中只需要几行:
import openwakeword
from openwakeword.model import Model
# 一次性下载所有预训练模型(或仅选择特定模型)
openwakeword.utils.download_models()
# 实例化模型
model = Model(
wakeword_models=["path/to/model.tflite"], # 也可以将此参数留空以加载所有包含的预训练模型
)
# 从文件、麦克风、网络流等获取包含16位16khz PCM音频数据的音频数据
# 为了获得最佳的效率和延迟,音频帧应该是80毫秒的倍数,更长的帧
# 会增加整体效率,但会牺牲检测延迟
frame = my_function_to_get_audio_frame()
# 获取该帧的预测结果
prediction = model.predict(frame)
此外,openWakeWord还提供其他有用的工具函数。例如:
# 获取单个WAV文件的预测结果(16位16khz PCM)
from openwakeword.model import Model
model = Model()
model.predict_clip("path/to/wav/file")
# 使用多进程获取大量文件的预测结果
from openwakeword.utils import bulk_predict
bulk_predict(
file_paths = ["path/to/wav/file/1", "path/to/wav/file/2"],
wakeword_models = ["hey jarvis"],
ncpu=2
)
有关类方法和工具函数的完整规范,请参阅openwakeword/utils.py
和openwakeword/model.py
。
使用建议
噪声抑制和语音活动检测(VAD)
虽然openWakeWord的默认设置在许多情况下都能很好地工作,但在某些部署场景中,可以通过调整openWakeWord中的参数来提高性能。
在支持的平台上(目前仅限X86和Arm64 Linux),可以通过在实例化openWakeWord模型时设置enable_speex_noise_suppression=True
来启用Speex噪声抑制。这可以在存在相对恒定的背景噪音时提高性能。
其次,openWakeWord包含了来自Silero的语音活动检测(VAD)模型,可以通过在实例化openWakeWord模型时将vad_threshold
参数设置为0到1之间的值来启用。这将只允许VAD模型同时具有高于指定阈值的分数时,openWakeWord才会产生正面预测,这可以显著减少非语音噪音存在时的误报激活。
激活的阈值分数
所有包含的openWakeWord模型都经过训练,可以在默认阈值0.5下很好地工作,但我们鼓励您通过测试来确定最适合您的环境和使用场景的阈值。对于某些部署,在实践中使用更低或更高的阈值可能会带来显著更好的性能。
用户特定模型
如果openWakeWord模型的基线性能不能满足特定应用的需求(特别是如果误报率高得令人无法接受),可以为特定声音训练自定义验证模型,作为预测的第二阶段过滤器(即,只允许可能由已知声音集合发出的激活通过)。这可以大大提高性能,但代价是使openWakeWord系统不太可能响应新的声音。
项目目标
openWakeWord有四个高级目标,这些目标结合起来(希望!)产生一个简单易用且可扩展的框架。
-
对于实际使用来说足够快,同时保持易用性和开发性。例如,Raspberry Pi 3的单个核心可以实时同时运行15-20个openWakeWord模型。然而,这些模型可能对于性能较弱的系统或微控制器来说仍然太大。像Picovoice Porcupine或Fluent Wakeword这样的商业选择可能更适合硬件资源受限的环境。
-
对于实际使用来说足够准确。包含的模型通常具有低于普通用户烦恼阈值的误报和漏报率。这显然是主观的,但在实践中,每小时<0.5次的误报率和<5%的漏报率通常是合理的。有关包含模型在实践中的预期表现的详细信息,请参阅性能与评估部分。
-
具有简单的模型架构和推理过程。模型以80毫秒的帧处理音频数据流,并为每一帧返回一个介于0和1之间的分数,表示检测到唤醒词/短语的置信度。所有模型还共享特征提取骨干网络,因此每个额外的模型对整体系统复杂性和资源需求的影响很小。
-
训练新模型时几乎不需要手动数据收集。包含的模型(有关更多详细信息,请参阅预训练模型部分)全部使用100%合成的文本转语音生成的语音进行训练。训练新模型就像为目标唤醒词/短语生成新的剪辑并在冻结的共享特征提取器之上训练一个小模型一样简单。有关更多详细信息,请参阅训练新模型部分。
未来的openWakeWord版本将致力于保持与这些目标一致,即使在添加新功能时也是如此。
预训练模型
openWakeWord附带了常用词语和短语的预训练模型。目前仅支持英语模型,但它们应该对不同类型的说话者口音和发音具有合理的鲁棒性。
下表列出了每个模型、它训练识别的词语/短语示例以及相关文档页面的附加详细信息。这些模型中的许多都针对同一词语/短语的多个变体进行了训练;请参阅每个模型的单独文档页面以查看所有支持的词语和短语变体。
模型 | 检测的语音 | 文档页面 |
---|---|---|
alexa | "alexa" | 文档 |
hey mycroft | "hey mycroft" | 文档 |
hey jarvis | "hey jarvis" | 文档 |
hey rhasspy | "hey rhasspy" | 待定 |
current weather | "what's the weather" | 文档 |
timers | "set a 10 minute timer" | 文档 |
基于性能测试中讨论的方法,每个包含的模型都旨在通过适当的阈值调整达到<5%的漏报率和<0.5/小时的误报率的目标性能标准。这些水平是主观的,但希望低于平均用户因系统经常错过预期激活和/或因在不希望的时间频繁激活而造成干扰而感到沮丧的烦恼阈值。例如,在这些性能水平下,用户可以预期模型处理几个小时的连续混合内容音频时最多只有几次误报,而在20次尝试中只有1次预期激活失败(在400次尝试中只有1次重试失败)。
如果您有希望在下一个版本中包含的新唤醒词或短语,请提出问题,我们将尽最大努力训练模型!这些请求和未来版本的重点将放在具有广泛通用性的词语和短语上,而不是高度特定的应用。
模型架构
openWakeword模型由三个独立的组件组成:
-
一个预处理函数,用于计算输入音频数据的梅尔频谱图。对于openWakeword,使用具有固定参数的Torch梅尔频谱图函数的ONNX实现,以实现跨设备的高效性能。
-
一个共享的特征提取骨干模型,将梅尔频谱图输入转换为通用语音嵌入。这个模型由Google以TFHub模块的形式提供,采用Apache-2.0许可。对于openWakeWord,这个模型被手动重新实现,以分离不同功能并允许对架构进行更多控制,而不是使用TFHub模块。该模型本身是一系列相对简单的卷积块,通过对大量数据进行广泛的预训练获得强大的性能。这个模型是openWakeWord的核心组件,即使在完全合成数据上训练时也能实现强大的性能。
-
一个跟随共享(且冻结)特征提取模型的分类模型。这个分类模型的结构是任意的,但实践中一个简单的全连接网络或两层RNN效果很好。
性能和评估
评估唤醒词/短语检测模型具有挑战性,通常很难评估在论文或其他项目中呈现的不同模型在部署时的表现,特别是在两个关键指标方面:误拒率和误接受率。为了明确定义:
误拒是指模型未能检测到用户的预期激活。
误接受是指模型在用户未打算激活时意外激活。
对于openWakeWord,评估遵循两个原则:
-
误拒率应该从代表真实录音环境的唤醒词/短语中确定,包括那些有背景噪音和混响的环境。这可以通过直接从这些环境收集数据,或使用数据增强方法模拟来实现。
-
误接受率应该从代表预期部署模型环境的音频中确定,而不仅仅是训练/评估数据。实际上,这意味着即使在连续数小时的语音和背景噪音中,模型也应该很少出现错误激活。
虽然存在其他唤醒词评估标准,但对于openWakeWord,决定采用自定义评估方法以更好地指示用户在实际部署中可以期待的性能。具体来说:
-
误拒率是通过将干净的唤醒词录音与现实信噪比(例如5-10 dB)的背景噪音混合,并使用房间冲激响应函数(RIRs)进行混响以更好地模拟远场音频,或从真实部署环境(例如,远场捕获和正常环境噪音)手动收集数据来计算的。
-
误接受率是通过使用Dinner Party Corpus数据集来确定的,该数据集代表了约5.5小时的远场语音、背景音乐和各种噪音。这个数据集为类似情况下可能发生的误激活次数设定了一个现实(虽然具有挑战性)的目标。
为了说明openWakeWord如何产生高效模型,下图显示了包含的"alexa"模型的误接受/误拒曲线,以及一个强大的商业竞争对手Picovoice Porcupine的性能。其他现有的开源唤醒词引擎(例如Snowboy、PocketSphinx等)未包括在内,因为它们要么不再维护,要么性能明显低于Porcupine。使用的正面测试样本来自Picovoice的存储库,这是他们免费提供给社区的一个出色资源。但是,请注意,与Picovoice的实现相比,测试数据的准备方式有所不同(有关更多详细信息,请参阅Alexa模型文档)。
至少对于这个测试数据和准备方法,openWakeWord生成的模型比Porcupine更准确。
作为第二个说明,下图显示了包含的"hey mycroft"模型的误接受/误拒率,以及自定义Picovoice Porcupine模型和Mycroft Precise的性能。在这种情况下,正面测试样本是从一位具有相对中性美国英语口音的男性发言者在真实家庭录音场景中手动收集的(有关更多详细信息,请参阅Hey Mycroft模型文档)。
再次,至少对于这个测试数据和准备方法,openWakeWord生成的模型至少与现有解决方案一样好。
然而,应该注意的是,这两个测试的样本量都很小,并且其他库的评估存在一些问题,这表明应谨慎解释这些结果。因此,唯一的声明是openWakeWord模型在广泛范围内与类似产品具有竞争力。强烈建议您测试openWakeWord,以确定它是否能满足您的用例需求。
最后,为了证明openWakeWord背后的核心方法(即预训练的语音嵌入和高质量合成语音)在更广泛的唤醒词/短语结构和长度范围内的有效性,下表显示了使用openWakeWord模型和数据集作者在相关论文中展示的基线方法在Fluent Speech Commands测试集上的性能。虽然两个模型都是在完全合成的数据上训练的,但由于数据合成和准备、训练和评估方法的根本不同,下面的数字可能无法直接比较。相反,重要的结论是openWakeWord是一种可行的口语理解(SLU)任务方法。
如果您知道应该添加到这些比较中的其他开源唤醒词/短语库,或对如何更普遍地改进评估有建议,请提出问题!我们渴望通过了解其他人如何解决这个问题来继续改进openWakeWord。
其他性能细节
模型鲁棒性
由于生成语音的变异性和Google广泛的预训练的结合,openWakeWord模型还展示了一些对实际应用有用的额外性能优势。在测试中,主要观察到三个方面。
-
训练的模型似乎对低声说出的唤醒词和短语反应相当好。这是一个有些令人惊讶的行为,因为用于生成训练数据的文本到语音模型通常不会创建具有类似低语声学特性的合成语音。
-
模型对以不同速度(在合理范围内)说出的唤醒词和短语也反应相对良好。
-
模型能够处理给定命令措辞的一些变化。这种行为并不完全出人意料,因为其他人在训练端到端口语理解系统时也报告了类似的好处。例如,包含的预训练天气模型通常仍能正确响应"今天天气怎么样"这样的短语,尽管没有直接训练这个短语(但与更接近训练数据的短语相比,误拒率可能会平均更高)。
背景噪音
虽然模型在训练时加入了背景噪音以提高鲁棒性,但在某些情况下,额外的噪音抑制可以改善性能。在初始化openWakeWord模型时设置enable_speex_noise_suppression=True参数将使用高效的Speex噪音抑制算法在预测之前预处理音频数据。这可以同时降低误拒率和误接受率,但强烈建议在真实部署环境中进行测试。
训练新模型
openWakeWord包含一个自动化工具,大大简化了训练自定义模型的过程。这可以通过两种方式使用:
-
一个简单的Google Colab笔记本,具有易于使用的界面和简单的端到端流程。这允许任何人非常快速地(<1小时)生成自定义模型,且不需要任何开发经验,但在某些部署场景中模型的性能可能较低。
-
一个更详细的笔记本(也在Google Colab上),描述了训练过程的更多细节,并允许更多定制。这可以产生高质量的模型,但需要更多的开发经验。
对于使用上述笔记本由Home Assistant社区训练的模型集合(非常感谢@fwartner),请参阅这个出色的存储库。
对于有兴趣了解模型训练背后基本概念的用户,还提供了一个更详细的教育性教程笔记本。然而,这个特定的笔记本并不适用于训练生产模型,建议使用上述自动化流程来实现这一目的。
从根本上说,新模型需要两个数据生成和收集步骤:
-
使用开源语音到文本系统为所需的唤醒词/短语生成新的训练数据(有关更多详细信息,请参阅合成数据生成)。这些模型和生成代码托管在一个单独的存储库中。所需的生成示例数量可能会有所不同,建议至少生成几千个,性能似乎随着数据集大小的增加而平滑提高。
-
收集负面数据(例如,不存在唤醒词/短语的音频)以帮助模型保持低误接受率。这也受益于规模,包含的模型都是使用约30,000小时的负面数据进行训练的,这些数据代表了语音、噪音和音乐。有关训练数据整理和准备的更多详细信息,请参阅各个模型的文档页面。
语言支持
目前,openWakeWord仅支持英语,主要是因为用于生成训练数据的预训练文本到语音模型都基于英语数据集。其他语言训练的语音到文本模型也可能效果良好,但非英语模型和数据集不太常见。
未来的发布路线图可能会包括非英语支持。特别是,Mycroft.AI的Mimic 3 TTS引擎可能有助于将一些支持扩展到其他语言。
常见问题
openWakeWord有Docker实现吗?
- 虽然没有官方的Docker实现,但@dalehumby创建了一个效果很好的实现!
openWakeWord能在浏览器中用JavaScript运行吗?
- 虽然ONNX运行时确实支持JavaScript,但openWakeWord模型所需的许多其他功能都需要移植。这目前不在roadmap上,但如果您对这个功能特别感兴趣,请提出issue或开始讨论。
- 作为一些应用的潜在解决方案,
examples/web
中的示例脚本演示了如何在浏览器中捕获音频并通过websockets流式传输到Python后端服务器上运行的openWakeWord。 - 其他可能的选择包括类似
pyodide
的项目(请参阅这里的相关issue)。
openWakeWord有C++版本吗?
- 虽然ONNX运行时也有C++ API,但没有完整openWakeWord库的官方C++实现。不过,@synesthesiam创建了一个基本功能实现的openWakeWord C++版本。
openWakeWord适合边缘设备和微控制器吗?
- openWakeWord通常体积小且高效,但可能不足以适合部署在超低功耗边缘设备上。例如,其他openWakeWord用户和贡献者的一些实验表明,即使使用量化的openWakeWord模型,在ESP32-S3上处理一个80毫秒的帧可能仍需要几秒钟。相反,我推荐@kahrendt开发的优秀microWakeWord库。它使用类似的纯合成训练数据方法,可以产生高质量的模型,效率足以在超低功耗边缘设备上运行。
为什么有三个独立的模型而不是一个?
- 将模型分开是一个有意识的选择,目的是提供灵活性并优化端到端预测过程的效率。例如,通过分开的梅尔频谱图、嵌入和预测模型,每个模型可以处理不同大小的音频输入,以优化整体延迟并在模型之间共享计算。当然,如果特定用例有这样的要求,也可以制作一个集成所有步骤的组合模型。
使用预训练模型时仍然有大量误激活,如何减少这些误激活?
- 首先,请查看使用建议并确保这些选项不能改善系统整体准确性。其次,如果可能的话,尝试自定义验证模型。如果这两种方法都无济于事,请提出一个issue,详细说明部署环境和您遇到的误激活类型。我们非常感谢关于如何改进基础预训练模型的反馈和建议!
致谢
自2023年1月发布openWakeWord以来,我非常感激开源社区的鼓励和积极响应。特别是,我想感谢以下个人和团体的反馈、合作和开发支持:
许可证
此存储库中的所有代码均采用Apache 2.0许可证。所有包含的预训练模型均采用知识共享署名-非商业性使用-相同方式共享4.0国际许可证,这是因为训练数据中包含了许可未知或限制性的数据集。如果您对许可更宽松的预训练模型感兴趣,请提出issue,我们将尝试在未来的版本中添加它们。