您的位置:首页 - 文章 -  - 正文

4.语音板使用snowboy唤醒引擎

0x00 snowboy唤醒引擎简介

snowboy 是一个开源的、轻量级语音唤醒引擎,通过它可以很轻松地创建属于自己的唤醒词。唤醒,是人机语音交互的起点。因为在将机器人唤醒前,人说话的声音是不进行处理的,只有在唤醒后,机器人才会将收听到的语音进行解析、处理、反馈。这里的唤醒动作,可以理解为机器人的名字。就跟现在市面上的“小爱同学”、“天猫精灵”一样,不过这些唤醒词都是经过商业化定制的,一般用户可没那么多钱进行定制商业化的唤醒词。这里的snowboy就提供了一种便捷的途径来帮我们做这件事,省去高昂的商业化唤醒词定制费,snowboy具备以下特点:

(1)高度可定制性:可自由、快速的训练属于自己的唤醒词

(2)始终倾听:无需联网,离线使用,保护隐私。精确度高,低延迟

(3)轻量可嵌入:硬件耗费资源非常低(树莓派CPU占用低于5%,内存消耗小)

唤醒引擎在树莓派平台上的资源消耗一览表

(4)开源跨平台:开放源代码,支持多种操作系统和硬件平台,可多编程语言开发

snowboy介绍

0x01 下载snowboy代码

我们这款语音板现在就可以使用snowboy这个唤醒引擎,首先来下载snowboy的源码,然后我们就可以在本地进行测试了,下载snowboy的github仓库命令如下:

git clone https://github.com/Kitt-AI/snowboy.git

下载好代码后,就可以来安装下运行需要的软件了。后面我会把这些缺少的软件都提前安装好在下一版的ROS镜像中,把语音开发环境都配置好,这样后面的同学再使用语音板的时候,就不用这么麻烦来安装这些软件包了,直接就能用snowboy唤醒。这里的安装命令如下:

sudo apt-get install python-pyaudio python3-pyaudio swig

接下来就是安装python版本的PortAudio,安装命令如下:

pip install pyaudio

上述操作过程可以参考如下的截图:

下载snowboy源码

在安装好这些软件后,接下来就可以来验证下是否可以正常录音了,只要语音板麦克风可以正常工作,可以录音了,我们才可以进行后面的操作。完整的测试录音命令如下:

rec test.wav

当在终端中输入完该命令后,就会自动开启录音,我们就可以对着麦克风说几句话。最终会保存到test.wav文件中,最后我们播放出来test.wav看看该文件是否正常,如果正常的话,那我们语音板就是进入正常工作状态了。要想播放一下wav文件,命令也很简单:

play test.wav

具体的测试过程,可以参考该视频:

录音测试

0x02 编译唤醒引擎动态库

在这里我们在使用唤醒引擎前,需要编译对应编程语言版本所使用的动态库。由于snowboy的唤醒引擎可以在多种语言环境中使用,我们这里选择python版本,也就是python2.7的版本。当然也可以编译python3的版本,这里编译对应语言版本动态库用到的工具就是swig,这个swig是由Simple Wrapper and Interface Generator的首字母组成,根据这个英文也大概了解swig是干嘛的了。简单来说,swig就是为了将我们使用C/C++编写的代码封装起来,然后可以给其他语言使用的一个工具。这里的snowboy唤醒引擎是使用C/C++开发的,所以python要想使用就需要做下转换了。

这里编译python版本的引擎库也很简单,整个操作过程如下图所示:

编译python版本的引擎库

当然,如果你想使用Python3版本的引擎库,这里就可以也可以编译,基本上编译过程是一样的,无非就是更换到Python3目录下执行编译命令。如下图所示:

编译Python3版本的动态库

0x03 测试唤醒python版本

当我们编译好python版本的唤醒引擎库以后,我们就可以来测试唤醒了,这次我们要切换到example目录下。我们可以直接使用下面的命令就可以来测试snowboy的唤醒了:

python demo.py ./resources/models/snowboy.umdl
开始snowboy唤醒测试

当启动后,我们就可以对着语音板喊“snowboy”了,这个喊还是稍微有点技巧的,避免中文式英语发音就行了。实在不行,你就看视频我是怎么喊的,具体的测试视频如下:

测试snowboy唤醒引擎-python板

这里需要注意,如果你打算使用Python3目录中的代码测试唤醒,启动命令要做一下修改,这里要是使用python3了:

python3 demo.py ./resources/models/snowboy.umdl

不过这里在执行的时候会提示一个小错误,我们需要修改一下才能继续运行,错误信息如下:

Traceback (most recent call last):
File "demo.py", line 1, in
import snowboydecoder
File "/home/corvin/snowboy/examples/Python3/snowboydecoder.py", line 5, in
from . import snowboydetect
ImportError: attempted relative import with no known parent package

这里的修改也很简单,我们就是要把snowboy/examples/Python3/snowboydecoder.py中第5行中的from . import snowboydetect修改为import snowboydetect就可以了。


0x04 自定义唤醒词

通过前面的视频我们可以得知,默认的唤醒词是“snowboy”,很多人可能发音也不标准导致体验不太好。那snowboy其实还提供一个可以自定义唤醒词的功能,这样我们就能很容易的来DIY自己专属的唤醒了。

这里制作自定义的唤醒词我们只需录制3个唤醒词的wav语音文件,然后将其通过post方式上传到snowboy的官网上训练即可,然后就可以立刻得到一个自己专属的唤醒引擎了。那接下来给大家介绍具体该如何操作,我们首先来录制3个包含有唤醒词的wav文件,完整的录制命令如下:

rec -r 16000 -c 1 -b 16 -e signed-integer 1.wav

在最后的1.wav就是最终生成的wav语音文件,我们可以将该命令依次运行三遍,这样我们就可以得到1.wav,2.wav,3.wav三个包含唤醒词的语音文件了。这里需要注意在录制wav文件的时候,这里录音过程不会自动结束,当我们说完唤醒词后,我们需要手动Ctrl+C来结束录制过程。

录制自定义唤醒词语音文件

当录制好三个唤醒词语音文件后,我们就来看看上传到snowboy服务器的python代码,具体代码如下:

 1import sys
2import base64
3import requests
4
5
6def get_wave(fname):
7    with open(fname) as infile:
8        return base64.b64encode(infile.read())
9
10
11endpoint = "https://snowboy.kitt.ai/api/v1/train/"
12
13
14############# MODIFY THE FOLLOWING #############
15token = ""
16hotword_name = "???"
17language = "en"
18age_group = "20_29"
19gender = "M"
20microphone = "macbook microphone"
21############### END OF MODIFY ##################
22
23if __name__ == "__main__":
24    try:
25        [_, wav1, wav2, wav3, out] = sys.argv
26    except ValueError:
27        print "Usage: %s wave_file1 wave_file2 wave_file3 out_model_name" % sys.argv[0]
28        sys.exit()
29
30    data = {
31        "name": hotword_name,
32        "language": language,
33        "age_group": age_group,
34        "gender": gender,
35        "microphone": microphone,
36        "token": token,
37        "voice_samples": [
38            {"wave": get_wave(wav1)},
39            {"wave": get_wave(wav2)},
40            {"wave": get_wave(wav3)}
41        ]
42    }
43
44    response = requests.post(endpoint, json=data)
45    if response.ok:
46        with open(out, "w"as outfile:
47            outfile.write(response.content)
48        print "Saved model to '%s'." % out
49    else:
50        print "Request failed."
51        print response.text

这里代码的14-21行是需要我们修改的地方,我们需要修改的第一个参数就是token令牌,就是我们在snowboy官网注册的账户下的token。具体如下图所示:

获取token

第二个参数hotword_name="科文"就可以了,根据我们自己设置的唤醒词来。这里不在每个字段介绍了,其实这里各字段的意义官网上有介绍,我这里直接贴图给大家参考:

各字段的意义

所以根据我个人的信息来设置的话,最终上述完整的代码如下,当然大家需要根据自己的个人信息来做相应修改。例如你要是女生的话,肯定gender要选择F了。

 1# -*- coding:utf-8 -*-
2import sys
3import base64
4import requests
5
6def get_wave(fname):
7    with open(fname) as infile:
8        return base64.b64encode(infile.read())
9
10endpoint = "https://snowboy.kitt.ai/api/v1/train/"
11
12############# MODIFY THE FOLLOWING #############
13token = "41008e4bbb90d511506c73b7b0f1be311afff2a6"
14hotword_name = "科文"
15language = "zh"
16age_group = "30_39"
17gender = "M"
18microphone = "rpi 2-MIC AI Board"
19############### END OF MODIFY ##################
20
21if __name__ == "__main__":
22    try:
23        [_, wav1, wav2, wav3, out] = sys.argv
24    except ValueError:
25        print "Usage: %s wave_file1 wave_file2 wave_file3 out_model_name" % sys.argv[0]
26        sys.exit()
27
28    data = {
29        "name": hotword_name,
30        "language": language,
31        "age_group": age_group,
32        "gender": gender,
33        "microphone": microphone,
34        "token": token,
35        "voice_samples": [
36            {"wave": get_wave(wav1)},
37            {"wave": get_wave(wav2)},
38            {"wave": get_wave(wav3)}
39        ]
40    }
41
42    response = requests.post(endpoint, json=data)
43    if response.ok:
44        with open(out, "w"as outfile:
45            outfile.write(response.content)
46        print "Saved model to '%s'." % out
47    else:
48        print "Request failed."
49        print response.text

那接下来就可以执行该python代码来申请自定义的唤醒引擎了,我们将该源码文件命名为training.py,最后一个参数就是我们要生成的唤醒引擎文件,这里的文件是以pmdl文件结尾的,所以完整的命令如下:

python training.py 1.wav 2.wav 3.wav corvin.pmdl

当生成了该文件,我们就可以将得到的corvin.pmdl文件复制到我们snowboy下的resources/models目录中,这样我们就有自定义的唤醒引擎文件了。剩下的就是启动demo.py,然后加载我们自己生成的唤醒引擎文件来进行唤醒了。

训练唤醒引擎并测试

那我们自定义的唤醒引擎的效果怎么样的?这里可以通过观看视频来感受:

测试自定义唤醒引擎文件

完整看完上述视频的同学可能会发现,在刚开始的时候我喊“科文”唤醒基本上是正常的。但是当我喊相近的唤醒词,例如“科科”发现偶尔也是可以唤醒的。这就是因为我们唤醒引擎中设置的太敏感了,这样虽然能增加唤醒率,但是同时也会增加一定的误唤醒率。后面我将sensitivity从0.5改为0.4,发现再测试“科科”的时候,误唤醒就少多了,基本上没发现误唤醒了。当然这样可能也会影响一定程度上的正常唤醒,所以调整这个sensitivity值是个很难拿捏准的,不是说设置成0.4就对于所有唤醒词都是正确的。这个值一定要根据不同的唤醒和不同的唤醒词来做不同的调整,这样才能有最佳的唤醒效果。

detector = snowboydecoder.HotwordDetector(models, sensitivity=0.4)

0x05 参考资料

[1].树莓派使用snowboy配置语音唤醒. https://www.jianshu.com/p/a1c06020f5fd

[2].Snowboy官网. https://snowboy.kitt.ai/

[3].Snowboy github网址. https://github.com/Kitt-AI/snowboy

[4].Snowboy在线文档网址. http://docs.kitt.ai/snowboy/

[5].swig官网. http://www.swig.org/


0x06 问题反馈

大家在按照教程操作过程中有任何问题,可以直接在文章末尾给我留言,或者关注ROS小课堂的官方微信公众号,在公众号中给我发消息反馈问题也行。我基本上每天都会处理公众号中的留言!当然如果你要是顺便给ROS小课堂打个赏,我也会感激不尽的,打赏30块还会被邀请进ROS小课堂的微信群,与更多志同道合的小伙伴一起学习和交流!

评论:

2 条评论,访客:2 条,站长:0 条

0%好评

  • 好评:(0%)
  • 中评:(0%)
  • 差评:(0%)
  1. YaDajin
    YaDajin发布于: 

    make报错

    • admin
      admin发布于: 

      建议使用我们发布的树莓派镜像来进行实验,因为把缺少的软件包都安装好了,你make出错应该就是缺少软件包造成的

发表评论

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据