亚马逊AWS官方博客

用 Amazon Lex 和 Raspberry Pi 构建语音套件

在本文中,我们将介绍如何使用广泛可用的组件将 Amazon Lex 嵌入自定义硬件中。我们将演示如何构建基于语音的简单 AI 套件并将其连接至 Amazon Lex。我们将使用 Raspberry Pi 和一些现成的组件,总成本不足 60 USD。在本文结束时,您将拥有一个与 Amazon Lex PostContent API 集成的联网硬件设备。我们还会演示两个示例自动程序 – 一个语音控制的机器人和一个语音控制的节拍器。

组件概览

您需要使用以下组件来构建 Amazon Lex 硬件套件。

  • Raspberry PI 3 B 型号,~35 USD,来自 Amazon
  • Kinobo – USB 2.0 迷你麦克风,~5 USD,来自 Amazon
  • Adafruit I2S 3W Stereo Speaker Bonnet 和扬声器,~12 USD,来自 adafruit
  • (可选) Qunqi 透明盒架,~20 USD,来自 Amazon

物理构造

Raspberry Pi

图 1. Raspberry PI B 型号

我们对此项目使用 Raspberry PI 3 B 型号产品。图 1 显示了安装在透明盒架中的 Raspberry Pi。透明盒架可以整齐地将 Pi、数字音频控制器 (DAC) 和扬声器装在一起,但它并不是必需的。

麦克风

安装 Kinobo USB 麦克风很简单,只需选取一个 USB 端口并插入即可!

图 2. Raspberry PI 3 B 型号与 Kinobo USB 麦克风

图 3. 安装完毕的 Raspberry PI 3 B 型号与 Kinobo USB 麦克风

数字音频控制器

Adafruit I2S 3W Stereo Speaker Bonnet 是一个 3W 立体声放大器和数字音频控制器 (DAC),无需额外电源即可直接从 Raspberry Pi 运行扬声器。该 Bonnet 作为装配完整的印刷电路板 (PCB) 提供,带有 2×20 排针和 2 个接线盒。

图 4. Adafruit I2S 3W Stereo Speaker Bonnet,2×20 排针和接线盒

在将排针连接到 PCB 时需要一些光束钎焊,这样便可将排针插入 Raspberry Pi 中。

图 5 和 6 显示已焊接排针和接线盒的 DAC。如果您不是专业焊工 (我们不是),请尝试去当地的创客工厂寻求帮助。

图 5. Adafruit I2S 3W Stereo Speaker Bonnet (DAC),底部

图 6. Adafruit I2S 3W Stereo Speaker Bonnet (DAC),顶部

图 7 显示安装在 Raspberry Pi 上的 DAC。

图 7. 安装在 Raspberry Pi 上的 DAC

扬声器

安装 DAC 后,可将随附的扬声器组合连接到中间的无焊接端子上。我们采取额外步骤将扬声器安装到透明盒架上面,方法是在架子上钻孔 (使用 Dremel) 来与每个扬声器中的安装孔匹配。

图 8. 连接至 JST 插孔且已安装的扬声器

成品

图 9 显示了已完成的套件。

图 9. 完整的 Amazon Lex AI 套件

安装和测试

OS

我们将 6 月 21 日的 Raspbian Jessie 镜像 2017-06-21-raspbian-jessie.img 用于此项目。最新版本应该也起作用。

  1. 从 RasberryPi.org 下载 Raspbian Jessie 的最新版本。
  2. 按照安装说明下载镜像并将其写入 SD 卡。
无外设设置 (可选)

我们想使用无外设 (不需要键盘、鼠标或显示器) 设置进行 Raspberry Pi 开发。要做的工作有点多,但一旦完成,便可从任意联网位置访问 Raspberry Pi。下面的可选说明介绍如何设置对 Raspberry Pi 的 SSH 和 VPC 访问,以启用无外设访问。如果要跳过这些说明,则可将键盘、鼠标和显示器直接连接到 Raspberry Pi 并跳至下一部分。

SSH (可选)

要启用 SSH,请将一个名为 ssh (没有任何扩展名) 的文件放在 SD 卡的引导分区中。可以在此处找到详细说明。

VNC (可选)

VNC 是一个图形化桌面共享系统,该系统允许您从一台计算机或移动设备 (正在运行 VNC 查看器) 中远程控制另一台计算机 (正在运行 VNC 服务器) 的桌面界面。使用 Raspberry Pi 时,有些任务 (如连接到 WIFI 网络) 使用 GUI 执行起来要容易得多。

Raspberry Pi VNC 文档提供了用于为 Raspberry Pi 设置 VNC 服务器和查看器的不错指南。

网络配置

仅需连接以太网电缆便足以使 Raspberry Pi 联网。我们发现,使用 GUI (直接或通过 VPC) 将 Raspberry Pi 连接至无线网络是最快速的方法。联网后,可在 raspberry.local 中或通过 IP 地址使用您的 Raspberry Pi。

注意:我们发现 Fing 是确定 Raspberry Pi 的 IP 地址的最简单方法。

数字音频控制器

Adafruit 提供了有关安装和测试 I2S DAC 的详细说明。我们发现,Adafruit 说明中提到的安装说明效果更好。

开始使用 DAC 的最简单方法是使用一行式安装程序:

  1. 通过 ssh 进入您的 Raspberry Pi 并创建一个名为 lex 的新目录。
    mkdir lex && cd lex/ 
  2. 运行 phatdac 安装脚本。
    curl https://get.pimoroni.com/phatdac | bash
  3. 系统提示您继续时,请输入 y
  4. 如果系统提示您重新启动,请输入 y。如果需要重新启动,请在重新连接至 Raspberry Pi 之后重新运行脚本。
  5. 如果系统询问是否要立即测试系统,请输入 y

您应该听到每个立体声通道播放的音频样本。可在此处找到有关使用 DAC 的详细说明,包括手动安装选项:

麦克风

使用麦克风不需要进行任何安装。所有必需的 ALSA 库应该都已经安装完毕。可使用以下命令测试麦克风是否起作用。

sudo arecord -D plughw:1 -r 32000 -f S16_LE temp.wav 

说完后按 ctrl-C 终止脚本。您可以使用以下命令测试已录制的音频。

sudo aplay ./temp.wav

如果您在播放 temp.wav 时能听到录制的音频,则表明您已准备就绪,可以开始捕获音频并将其流式传输至 Amazon Lex。

Amazon Lex 集成

安装 Node.js

使用 apt-get 安装 Node 和 npm。在 Raspberry Pi 的终端窗口中键入以下命令:

sudo apt-get install -y nodejs npm

通过检查已安装版本验证 Node 和 npm 是否已正确安装。

npm -v && node -v

注意:如果与节点包之间存在命名冲突,则它将安装为 nodejs。可以手动创建指向 /usr/bin/node 的符号链接或在以下命令中使用 nodejs 代替 node。

安装开发工具包

安装适用于 Node.js 的 AWS 开发工具包的首选方式是使用 npm。在终端窗口中键入以下内容:

npm install aws-sdk

自动程序对话启动程序脚本

现在麦克风、扬声器均能正常使用,并且我们还安装了 Amazon Lex JavaScript 开发工具包,下面便可调用 PostContent 操作并与自动程序开始对话了。

Node 脚本可侦听音频输入、检测声音并开始将音频流式传输至 Amazon Lex。检测到静默后,该脚本将终止流并播放响应。随后该脚本将持续侦听和响应,直至对话状态变为“Fulfilled”。

// lex.js 
var AWS = require('aws-sdk'),
   fs = require('fs'),
   ts = require('tailstream'),
   exec = require('child_process').exec;

   var FULFILLED = 'Fulfilled',
   RESPONSE_FILE = 'response.mpeg',
   REMOVE_REQUEST_FILE = 'rm request.wav',
   SOX_COMMAND = 'sox -d -t wavpcm -c 1 -b 16 -r 16000 -e signed-integer --endian little - silence 1 0 1% 5 0.3t 2% > request.wav',
   streaming = false,
   inputStream,
   lexruntime = new AWS.LexRuntime({
     region: 'us-east-1',
     credentials: new AWS.Credentials(
       <KeyId>,
       <SecretKeyId>, null)
   });   

var setupStream = function() {
   streaming = true;
   inputStream = ts.createReadStream('./request.wav');
   var params = {
     botAlias: '$LATEST',
     botName: <BotName>,
     userId: 'lexHeadTesting',
     contentType: 'audio/l16; rate=16000; channels=1',
     inputStream: inputStream
   };

   lexruntime.postContent(params, function(err, data) {
     if (err) {
       console.log(err, err.stack);
       process.exit(1);
     } else {
       fs.writeFile(RESPONSE_FILE, data.audioStream, function(err) {
         if (err) {
           return console.log(err);
           process.exit(1);
         }
       });
       var playback = exec('sudo mpg321 ' + RESPONSE_FILE);
       playback.on('close', function(code) {
         exec('rm ' + RESPONSE_FILE);
         if (data.dialogState !== FULFILLED) {
           streaming = false;
           record();
         }
       });
     }
   });
 }

var record = function() {
   var recording = exec(SOX_COMMAND);
   recording.stderr.on('data', function(data) {
     console.log(data);
     if (!streaming) {
       setupStream();
     }
   });
   recording.on('close', function(code) {
     inputStream.done();
     exec(REMOVE_REQUEST_FILE);
   });
 }
record();

我们需要先安装一些依赖项,然后才能运行脚本。该脚本依赖于用于录制和播放的 fstailstreamchild_process npm 软件包以及 SoXmpg321 命令。

npm 软件包

从您的 ~/lex 目录中,使用以下命令安装 npm 依赖项。

npm install fs tailstream child_process 
SoX

SoX 可读取和写入大多数常见格式的音频文件并对其应用效果。它可以组合多个输入源、合成音频,在许多系统中还可以充当通用音频播放器或多音轨音频记录器。我们使用 SoX 来启动和停止音频捕获以及修剪 (移除开头和结尾的静默) 已捕获的音频。使用以下命令安装 SoX。

sudo apt-get install sox 

我们使用下面的 SoX 命令以 Amazon Lex 可识别的格式记录音频,更重要的是,我们使用此命令来执行静默检测和修剪。请注意,此命令仅供您参考。您并不一定必须执行此命令。

sox -d -t wavpcm -c 1 -b 16 -r 16000 -e signed-integer –endian little – silence 1 0 1% 4 0.3t 2%

该命令的第一部分指示,我们要将 PCM 编码 (有符号的 16 位 little endian) 的音频 (采样频率为 16000 Hz) 记录为 WAV 文件。

sox -d -t wavpcm -c 1 -b 16 -r 16000 -e signed-integer --endian little

第二部分指定我们希望在开始记录之前和之后处理静默检测的方式。

silence 1 0 1% 4 0.3t 2% 

第一个三元组值用于删除开头的静默 (如果有),直至声音中的 0 秒数高于 1%。% 是一个阈值,用于指示应视为静默的样本值。第二个三元组用于在至少有 4 个 .3 秒的静默实例低于 2% 时停止记录。

mpg321

一旦从 Amazon Lex 获取成功响应,我们便可以使用 mpg321 播放音频。mpg321 是一个非常常用的命令行 mp3 播放器。使用以下命令安装 mpg321。

sudo apt-get install mpg321 

测试

现在,我们已经安装完依赖项,可以测试我们的 Amazon Lex 对话脚本了。从 ~/lex 目录中,用上面的脚本内容创建一个名为 lex.js 的文件。

注意:确保使用您的凭证自动程序名称更新示例脚本。

完成后,保存脚本并用以下命令执行脚本。

node lex.js 

如果一切正常,您应在终端中看到 SoX 命令的输出。对着自动程序大声说话,并倾听 Amazon Lex 的回应。脚本将继续,直至对话状态为 Fulfilled。如果您没有自动程序,请参阅有关构建自动程序的 Amazon Lex 文档。为了获得灵感,请查看“那么我能用它做些什么呢?”部分,其中包含不同自动程序集成的视频。

热词

此时,我们已经具有正常的音频捕获和播放功能,还有一个 Node 脚本可用于编排基于 Amazon Lex PostContent 操作的对话。为完成此项目,我们将添加热词检测,这样便可通过大声说出热词来调用套件。对于此项目,我们将第三方库 (Snowboy) 用于热词检测。Snowboy 是一个可自定义的“热词”检测引擎,它在本地运行并且开箱便与 Raspberry Pi 兼容。

安装

按照下面的说明或更详细的 Snowboy 快速启动说明操作。

在 ~/lex 目录中,创建一个名为“snowboy”的新目录并将 Snowboy 二进制文件下载到该目录中。

mkdir snowboy && cd ~/lex/snowboy && wget https://s3-us-west-2.amazonaws.com/snowboy/snowboy-releases/rpi-arm-raspbian-8.0-1.2.0.tar.bz2 

解压缩 Snowboy tar-ball。

tar -xvf ./rpi-arm-raspbian-8.0-1.2.0.tar.bz2 cd rpi-arm-raspbian-8.0-1.2.0 

安装 Snowboy 依赖项。

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

安装 pyaudio。

pip install pyaudio 

您还需要安装 libatlas-base-dev。(此步骤与 Snowboy 说明不同。)

sudo apt-get install libatlas-base-dev 

测试

安装完成后,您将能够运行 Snowboy 测试脚本。确定您位于以下目录中:~/lex/snowboy/rpi-arm-raspbian-8.0-1.2.0。

python demo.py resources/snowboy.umdl 

当脚本报告它正在倾听时,大声说出热词“Snowboy”。您应该会听到一声提示音,指示已识别该热词。

创建自定义热词 (可选)

在下一部分中,我们将修改 Snowboy 演示脚本,以运行 lex.js 自动程序调用程序。如果要使用自定义热词,可从 Snowboy 控制面板中生成并下载个人热词模型。在此演示中,我们为“botbot”和“metronome”创建了一个“热词”模型。

整合在一起

现在我们已经准备就绪,可以设置热词循环了。下面的代码对 Snowboy 二进制文件中包含的 demo.py 文件略微做了改动。开始后,该代码将侦听热词,听到热词后停止热词检测器,执行 Lex 自动程序调用程序脚本,并在自动程序调用程序脚本完成后自行重新启动。

import snowboydecoder 
import os 
import sys 
import signal 
import subprocess
   
interrupted = False
   
def signal_handler(signal, frame):
     global interrupted
     interrupted = True
     
def interrupt_callback():
     global interrupted
     return interrupted
   
def on_hot_word():
 	detector.terminate()
 	pro = subprocess.Popen(["node", "../../lex.js"]).wait()
 	print("Restarting...")
 	os.execv(sys.executable, ['python'] + sys.argv)
   
if len(sys.argv) == 1:
     print("Error: need to specify model name")
     print("Usage: python demo.py your.model")
     sys.exit(-1)
   
model = sys.argv[1]
   
# capture SIGINT signal, e.g., Ctrl+C signal.signal(signal.SIGINT, signal_handler)
   
detector = snowboydecoder.HotwordDetector(model, sensitivity=0.5)
print('Listening... Press Ctrl+C to exit')
   
# main loop 
detector.start(detected_callback=on_hot_word,
                interrupt_check=interrupt_callback,
                sleep_time=0.03)
   
detector.terminate()

在 ~/lex/snowboy/rpi-arm-raspbian-8.0-1.2.0 目录中创建一个名为 lex-wake.py 的新文件,将以上代码复制到该文件中并保存文件。您可以使用以下命令对其进行测试。

python lex-wake.py Botbot.pmdl 

注意:我们的个人热词模型为“Botbot.pmdl”,您可以使用自己的热词模型 (如果已创建) 或包含的 Snowboy 模型“resources/snowboy.umdl”。

您应该可以看到热词循环启动。大声说出热词。在您的自动程序已被调用并且对话状态变为“Fulfilled”之后,热词循环将再次开始侦听。

祝贺您,您已创建了自己的 AI 套件!请查看下面的“那么我能用它做些什么呢?”部分,获取新套件激动人心的用法示例,其中包括语音控制的机器人、会说话的门铃、节拍器等。

启动时运行 (可选)

要在系统启动时开始侦听热词,请编辑 /etc/rc.local 文件以包含您的热词脚本。

python ~/lex/snowboy/rpi-arm-raspbian-8.0-1.2.0/lex-wake.py Botbot.pmdl & 

参考

完整参考代码

https://github.com/awslabs/aws-lex-ai-kit

那么我能用它做些什么呢?

您可以将其连接至任何 Amazon Lex 自动程序 – 我们很乐愿听到您用它构建了什么!我们将该语音套件连接至两个自动程序,创建了一个语音控制的 GoPiGo 机器人和一个语音控制的节拍器。

语音控制的机器人

在此示例中,有两个主要意图:行驶和转向,其中包含用于方向、距离和单位的槽位。将通过一个 Lambda 函数来处理执行情况,该函数可更新 IoT 设备影子,然后机器人将会移动。

语音控制的节拍器

在此示例中,我们将 Intent 参数直接返回给语音套件。该 Intent 只有一个槽位 Tempo。返回速度值后,我们将用请求的速度启动节拍器,并使用板载扬声器播放一声嘀嗒声。

我们很乐意听到您对本文的想法,回答您的任何问题以及/或了解您创建的语音套件音频项目。您可在下面的评论区向我们提供反馈。


补充阅读

了解如何在浏览器中捕获语音输入并将其发送给 Amazon Lex


作者简介

Andrew Lafranchise 是 AWS 深度学习团队的高级软件开发工程师。他使用不同技术来改进 Lex 开发人员体验。在业余时间,他除了陪伴家人,还开发了一个能与他 3 岁大的双胞胎女儿互动的 Lex 自动程序。