本文为我的 源代码阅读专栏 第一个工程的代码阅读——wukong-robot 一个优秀的开源智能音箱项目。本文解析的源代码文件为snowboy文件夹中的文件
snowboy介绍
Snowboy是一款基于神经网络的可定制的唤醒词检测引擎。Snowboy本身是用C++完成,通过swig封装,可在多种操作系统和多语言上使用。wukong-robot项目snowboy文件夹中的snowboydetect.py文件就是使用swig封装的python接口。本文主要研究Snowboy在wukong-robot项目中的使用。对Snowboy本身并不做太多研究,对Snowboy有兴趣的同学可以参考Snowboy官方网站和github
snowboy文件夹
snowboy文件夹包含以下内容:
- resources。资源文件夹
- snowboydetect.py。swig封装的python接口
- snowboydecoder.py。 对snowboy库进行封装的源码文件
下面主要针对snowboydecoder.py文件进行研究。
snowboydecoder.py 包含全局变量:
- logger。日志记录
- TOP_DIR
- RESOURCE_FILE
- DETECT_DING。定义声音文件
- DETECT_DONG。定义声音文件
- ERROR_HANDLER_FUNC。定义asound库出错后的回调接口
- c_error_handler。asound库出错后的回调
函数: - py_error_handler。asound库出错后实际执行的函数
- no_alsa_error。asound库出错回调管理器
- play_audio_file。播放声音文件
类: - RingBuffer。环形缓冲区。实现多次部分写入,一次全部读出
- ActiveListener。激活并开始循环热词监测。
- HotwordDetector。检测麦克风是否有自定义的热词。
ActiveListener
ActiveListener是对snowboy库的封装,以更方便地使用热词唤醒功能
ActiveListener生成对象时,会将热词模型文件列表传入snowboy库。热词模型文件可通过调用snowboy.kitt.ai
网络接口生成
ActiveListener对象生成后,就可以通过listen方法进行热词监听了。listen方法主要做了以下几件事情:
- 打开录音设备,以持续地将录到的声音存储在前面定义的RingBuffer对象中
- 在设定的循环次数
recording_timeout
和设定的安静次数silent_count_threshold
内循环读取RingBuffer对象中的值,然后调用snowboy库的RunDetection接口进行热词唤醒检测。 - 检测次数到或检测到热词后退出listen方法
- 在退出listen方法之前,保存从ActiveListener对象创建到本次记录完成的声音到以时间命名的wav文件中
HotwordDetector
HotwordDetector是对snowboy库的封装。跟ActiveListener相比可设定的参数更多,如输入声音增益,每一个唤醒词的灵敏度等;可在检测到热词后马上调用回调函数,增加反应的实时性;在检测到唤醒词后经过一定延时才进行下一次热词检测
HotwordDetector生成对象时,会将热词模型文件列表、每一个唤醒词的灵敏度传入snowboy库。同时设置snowboy库的输入声音增益
HotwordDetector对象生成后,就可以通过start方法进行热词监听了。start方法主要做了以下几件事情:
- 打开录音设备,以持续地将录到的声音存储在前面定义的RingBuffer对象中
- 针对每一个唤醒词注册唤醒后的回调函数
- 在内部不断的循环中进行热词检测
- 检测到热词后调用本热词对应的回调函数
- 检测到热词后在设定的循环次数
recording_timeout
和设定的安静次数silent_count_threshold
达到再开始下一次检测 - 在开始下一次检测之前,保存本次热词检测记录的声音到以时间命名的wav文件中
HotwordDetector对象还提供了terminate方法来强制停止start方法的循环过程
用到的技术点
- collections。collections.deque是适合高效插入和删除的双向列表。
- @contextmanager。上下文管理装饰器。用以管理资源。接受一个generator,用yield语句把with … as var把变量输出出去
参考
考虑到项目源代码可能会被作者更新,致使代码与我的总结文档不一致,下面列表中会提供原始代码链接和冻结代码链接。冻结代码链到我自己fork的工程中,大家如果需要找原始源码,可以点击原始代码链接