dingdang-robot:一个开源的中文智能音箱项目

免责说明:本文介绍的 dingdang-robot 与公司的叮当助手没有任何关系。

这个项目其实来源于我生活中的一个需求:我每天晚上都会去厨房做一个面包当明天的早餐,当我把用料按顺序准备好放进面包机时,我需要准确预约到明天早上我吃早餐的时间。然而,几乎每次在这个时候我都没有带手机在身边,而是都放在客厅里充电,这时只能跑去客厅看时间。虽然厨房到客厅只有几步之遥,但自己又是懒癌患者,每天都要这么来回奔波就觉得很不方便。要解决这个问题当然有很多种方法,比如直接买个小时钟放在厨房。不过我更希望“连看都不用看”,直接有人告诉我时间。所以,我需要一个像 Amazon Echo 那样的智能音箱。

然而,不论是 Amazon Echo 、Google Home 还是微软 Cortana 音箱,在国内的使用都是个问题。虽然国内也有类似的智能音箱产品,但我没有用过这些产品,不知道可定制性如何。比如,如果我需要开发个功能让它告诉我某种面包的配方是什么,这些产品就不一定能做到了。考虑再三,我决定自己动手写一个。整个项目用了差不多三个星期的业余零碎时间。

先放上项目主页:http://dingdang.hahack.com

Demo:https://github.com/wzpan/dingdang-robot/wiki/demo

下面分享一下我在开发这个项目过程中的心得。

硬件

首先要解决的是硬件问题。我选择在 Raspberry Pi 上开发。于是我买了块 Raspberry Pi 三代主板。麦克风和音响方面,出于美观的目的,买了个自带音响的 USB 全向会议麦克风。整套设备看起来就像这样:

过了不久觉得这个麦克风自带的音响音质太一般了,所以我又外接了一个小音箱。然后再插了一个摄像头,用来实现拍照功能,又进化成了这样:

发布了不到一个星期,respeaker 的商务经理看到了我这个项目,希望能提供硬件上的支持,所以我又玩上了各种 respeaker 的硬件(做为回报,我也零报酬给他们带去了 100 多个 respeaker-2mics-HAT 的销量):

因为软件本身是和硬件解耦的,并不依赖具体的硬件要求,所以很多用户也自己做了硬件上的定制和尝试(最后一张图里预装了 dingdang-robot 的是熊,不是妹子 :-p):

硬件有了,接下来就得开始写软件了。主要的框架借鉴了 Jasper 项目,并加入了我自己的定制和想法。这里说说一些有意思的部分。

指令接收

智能音箱要解决的一个最重要的问题就是如何接收指令。这里头主要涉及两个问题:

  1. 被动唤醒(Passive Listening),即“什么时候开始听”。这个阶段只监听唤醒词。当听到唤醒词时,进入主动聆听。
  2. 主动聆听(Active Listening),即“什么时候结束听”。这个阶段主动聆听用户的任何语音指令,然后对听到的内容进行分析处理。

被动唤醒阶段的基本策略是:每次以 16000 的采样率录制 1024 个采样作为一个采样集,然后对采样集进行信号强度估计,当某个采样集信号强度大于一个阈值时,就认为可能接受到了指令。然后持续录制多 1 秒时间,再转交给语音识别模块。当语音识别模块认为是唤醒词时,进入主动聆听阶段。

主动聆听的策略与被动唤醒基本相似,每次以 16000 的采样率录制 1024 个采样作为一个采样集,然后对采样集进行信号强度估计,当某个采样集信号强度低于一个阈值约 1 秒的时间时,就认为用户已说完了指令。当然还要考虑环境吵杂,一直处于聆听的可能。因此可以再加一个超时保护,超过 12 秒就结束聆听。

语音处理

说说STT(语音识别,说成ASR也是一回事啦)引擎和TTS(语音转文本)引擎的选择。由于被动唤醒会试图识别所有听到的内容,出于隐私保护的目的,应该使用离线的语音识别引擎,因此我选择的是 PocketSphinx 。而对于主动聆听,由于是在唤醒阶段才会进行转换,进入主动聆听前会有蜂鸣提示,用户也会清楚此时叮当正在听他们说话,相对来说隐私泄露的可能性就比较低,因此我最初选择的是在线的百度 STT 语音识别服务,也省下了扩展语音识别模型的工夫,有利于更好地实现插件可扩展。TTS 引擎方面同样也先支持了百度的语音合成。

在实际测试中,PocketSphinx 的识别出乎意料的好。由于我的离线指令集只有几个候选唤醒词,PocketSphinx 对这些唤醒词的识别非常灵敏,甚至有时候其他声音也可能被误当成唤醒词而唤醒叮当。但即使被意外唤醒了,不去理会叮当就可以了。

相比之下,百度的语音识别就比较迟钝了。有时候明明我发音很清晰了,还是会识别成另外的含义。通过在百度的语音识别平台上传自定义的语音识别词库 可以提高识别的准确率。另外,由于我用的是 Restful API,网速比较差的时候响应也比较慢。我在家用的是 10M 带宽的网络,反应速度还算可以接受。

下面这个视频是我与叮当对话的演示。我把唤醒词设置成了“小梅”:

http://www.miaopai.com/show/-yeEBNJlvrQ-UNZzaglxr2s9JQU8TZNy.htm

一个问题是当回答内容比较长(比如问叮当当天的新闻)时,合成语音的耗时会变得很长,给人的感受是叮当的响应很慢。所以我加了个 read_long_content 的选项。当内容过长时,改成发送到用户的邮箱或者微信。

到了九月份的时候,dingdang-robot 在离线唤醒方面又增加了 snowboy 引擎,在主动聆听和语音合成方面又增加了阿里、科大讯飞的服务,无论是识别速度和合成音色的丰富程度又有了很大的进步。

技能插件

叮当最好玩的部分当然就是玩插件了,通过写插件可以让叮当接入各种各样的服务,完成各种各样的事情。我在叮当里也内置了几个插件。为了方便用户扩展,我定义了三个技能插件目录:

  • $HOME/dingdang/client/plugins:官方插件,与 wzpan/dingdang-robot 同一仓库;
  • $HOME/.dingdang/contrib:用户贡献的第三方插件,单独维护一个 dingdang-robot/dingdang-contrib 仓库;
  • $HOME/.dingdang/custom:用户自定义插件,用于存放用户自己开发的,暂时不计划对外发布的插件。

如下是截至本文发布前 dingdang-robot 提供的插件,可以看出,其他用户贡献的插件已经达到了叮当自带的插件的两倍:

插件名

用途

是否用户贡献

Echo

简单的回声/传话功能。

Email

检查邮件功能。

Time

时间插件。询问叮当时间。

Camera

用于调起摄像头拍照(如果安装了摄像头的话)。

部分

SendQR

要求叮当发送微信登录二维码到用户邮箱(方便远程微信登录)。

Chatting

用于进入/退出闲聊模式的插件。

Unclear

用于机器人聊天兜底。

Hass

用于控制接入HomeAssistant的设备

NetEaseMusic

网易云音乐播放插件

Weather

天气查询插件

SpeakIP

播报主机IP地址插件

Reboot

重新启动操作系统(root用户)

WebServer

启动HTTP服务器插件

SendMessage

向微信好友发消息插件

ControMqtt

通过Mqtt协议与其他开发板通讯

WOL

通过WOL(Wake On Lan)实现语音开机

EmailMyPC

以邮件方式实现语音操控电脑

ToDo

简单的备忘插件

RaspberryPiStatus

简单的树莓派状态查询插件

HeadlineNews

新闻头条播报插件

Direction

出行路线规划插件

BaiduFM

百度FM音乐播放插件

音乐播放

既然是智能音箱,当然少不了播放音乐的功能。所以我额外写了个播放网易云音乐的插件 NetEaseMusic 。出于版权考虑,并不集成进官方插件中,而是放进 dingdang-contrib 里头。

这个插件的实现比较复杂。普通的插件接受到指令,响应完就退出了。而为了能支持各种指令控制音乐播放,这个插件在接收到播放控制指令后并不退出插件,而是进入一个播放器模式,这个模式主动聆听得到的指令只会在播放控制指令集中匹配,其他的插件指令都不起作用。只有当用户要求退出播放时才回到普通模式。NetEaseMusic 的播放控制指令如下:

指令

相同指令

用途

播放音乐

-

进入音乐播放模式。在音乐播放模式下,其他的插件功能将不可用。

下一首

切歌, 下一首歌, 下首歌

切换到下一首歌。如果没有下一首歌,就回到列表中第一首歌

上一首

上一首歌,上首歌

切换到上一首歌。如果没有上一首歌,就跳到列表中最后一首歌

大声点

大点声,大声

调高播放音量

小声点

小点声,小声

降低播放音量

随机播放

-

随机播放列表中的音乐

顺序播放

-

顺序播放列表中的音乐

暂停播放

-

暂停音乐的播放

播放

继续

继续音乐的播放

榜单

-

播放推荐榜单

歌单

-

播放用户的歌单(如果有多张,将只播放第一张)

结束播放

退出播放,停止播放

退出音乐播放模式。

搜索

查找

搜索歌曲/歌手。将自动播放搜索结果。

什么歌

-

正在播放的是什么歌

实现这个插件的过程中还参考了 Vellow 的 MusicBox 项目以及 yaphone 的 RasWxNeteaseMusic 。为了方便重用,我把 MusicBox 的核心 API 抽离了出来封成了一个 MusicBoxApi 库 。比较坑爹的是就在我准备发布叮当的前几天,老的获取音乐地址的方式彻底不能用了,而新的接口批量获取的地址不知道为什么是乱序的,于是我只能在播放每首歌前都调用一下新版的获取地址的 POST 接口,又增加了一点响应时间。

下面这段音频是使用叮当控制音乐播放的演示:

http://onmw7y6f4.bkt.clouddn.com/%E6%92%AD%E6%94%BE%E9%9F%B3%E4%B9%90.mp3

完成了音乐播放功能后,叮当的好玩程度提高了很多。以前要听歌,至少得把电脑或者手机打开。现在只需要喊一声叫叮当播放歌曲就可以了。想换歌、搜索歌曲、调节音量都是说句话就搞定的事情,生活幸福指数大幅提升 ^_^

开源心得

dingdang-robot 的正式开源时间是今年的 5 月 20 日(是的,我专门挑了个好日子),截至本文发表时,该项目的相关数据如下:

虽然数据并不是特别亮眼,不过对于这样的小众项目,我已经比较满意了。下面谈谈个人怎么维护一个开源项目吧。

前期:做好框架

根据二八法则,项目的前期应该要把整个项目期望能达到的 80% 的基本要求完成。一个人的力量毕竟有限,要完成剩余的 20% 的功能可能要耗费非常多的精力,还不如先推出来,形成社区后再去尝试完成。

以 dingdang-robot 为例,其实智能音箱最重要的几个用途:音乐播放、闹钟提醒和智能家电控制只有音乐播放是我在首次发布的时候提供的(因为不能播放在线音乐的智能音箱实在不好意思叫智能音箱)。剩下的几个功能都是我提了 feature issues 大致提供了实现思路,然后由其他的开发者去完成的。

所以,对于一个比较大的项目,更重要的是在这个阶段界定好 80% 的目标,设计好项目的框架,确定 License,写好 README 和 CONTRIBUTION(代码审核、持续集成测试等)。

中期:推广 + 社区搭建

项目发布之后,推广和社区搭建是非常重要的,毕竟直接关系到项目的用户数量和这个项目的生命力。

推广方面,这个阶段我发布了三篇文章:

这三篇文章推到了开发者头条和树莓派实验室上,都取得了不错的点击率。

另外,如果你跟微博上一些大 V 关系不错,也可以尝试 @ 他们帮忙推广,当然前提是项目要足够拿得出手才行。

在这个阶段,项目的主页和文档也必须尽快搞好,良好的主页和文档是吸引用户付出精力去尝试你的项目的必要前提。如果像我一样想省点事,可以直接用 Github Pages 生成简单的项目主页,然后直接用 Github Wiki 维护文档。

社区的搭建也是非常关键的一环。可以考虑的渠道比如:

  • 即时通讯工具:如果项目主要针对国内用户,可以使用QQ群;如果针对国际用户,可以使用 slack 。
  • 论坛。即时通讯工具的最大问题就是存在时效性。类似的问题在群里刚回答完,新加入的用户又问了一遍,非常崩溃。所以搭建一个论坛,引导用户多去使用论坛交流就可以解决这样的问题。

以 dingdang-robot 为例,QQ群是很多人决定参与项目之前先加入的社区。刚开始群里才几个人的时候也是非常冷清尴尬,但后面随着人越来越多,群里变得非常热闹(甚至我不得不选择上班时间屏蔽该群)。而论坛最初是其中一个用户用 discuz! 搭建的,但邮箱认证没搞定,久而久之论坛里一堆的 spam 。趁着国庆我又用 discourse 重新搭了一个,加了严格的审核策略,正好用腾讯云的体验代金券。

市集模式合作阶段:促进合作,保持生命力

一旦用户数量足够多,参与贡献的人就会多了起来。这时候怎么调动大家参与贡献的热情就显得格为重要了。

为了达到这个目的,项目作者本身首先当然要以身作则,体现出充足码力。该你承担的部分积极实现,该 code review 的时候赶紧 review,该发布新版本的时候保证发布。然后在社区里头多多抛出可能的 idea 和实现方案,这时候往往就会有人愿意参与贡献。

我比较喜欢的形式是在项目的 Github issue 页里提出需求,然后过不久就可以看到有人参与贡献了(比如 #28, #29#39)。对于参与贡献的用户,要不吝致谢,让他们的名字出现在 changelog 中。

除了这种市集模式的合作方式之外,未来我可能会考虑其他新颖的促进合作的方式,比如在线直播写插件、发布新版本,线下 Hackathon 等。

总结和后续

对于有 Coding 能力的 Hacker 而言,自己动手做一个智能音箱,不仅可以当做业余练手项目,还可以自由地定制硬件模块,并实现自己需要的各种功能,这远比直接购买一个 Amazon Echo 有趣得多。

更重要的,我更希望能有其他有兴趣的朋友参与进来,一同开发完善这个智能音箱项目。我相信,这种个性化服务的产品本身就应该是完全可定制的。而您的加入可以使 dingdang-robot 变得更智能!

原创声明,本文系作者授权云+社区-专栏发表,未经许可,不得转载。

如有侵权,请联系 yunjia_community@tencent.com 删除。

编辑于

刘裕忠的专栏

1 篇文章4 人订阅

我来说两句

2 条评论
登录 后参与评论

相关文章

来自专栏惶心 - 技术博客

用一年的时间,去遇见

白色而透明的屏幕里,像素点时刻变换着颜色。你看不见的黑暗里,只有风扇快速转动,发出微弱的响声。

1179
来自专栏phodal

为什么程序员们愿意在 GitHub 上开源自己的成果给别人免费使用和学习?

911
来自专栏FreeBuf

Twitter的野心:我们终将弃用密码

国外最流行的微博平台Twitter正在策划一项很大胆的项目:试图率先在Twitter上结束我们所习惯的密码时代。 其实,早在一年前,Twitter的高级产品经...

1795
来自专栏互联网杂技

超赞!2016年7月新鲜出炉的设计圈实用干货大合集

又到了新的一轮的设计圈干货大合集发布的时间了!这次的合集也是干货云集,囊括了笔记类工具,营销工具,生产力工具,CSS框架,UIKit,远程协作工具,配色工具,以...

3417
来自专栏Wordpress专用主机|主题模板|必备插件

WORDPRESS专用主机推荐 自带CDN+SSL性价比高才是王道

对于很多Wordpress爱好者来讲,一台合适的高性价比的WP专用主机才是一个完美的开始。接下来,就直接进入本文的主题吧。让我们来看看国外五大Wordpress...

3285
来自专栏守候书阁

2018前端值得关注的技术

2017悄然过去,2018已经来到。人在进步,技术在发展。2018年前端有哪些领域,技术值得关注,哪些技术会兴起,哪些技术会没落。下面就我个人的判断进行一个预测...

53515
来自专栏无原型不设计

相当便利的UI交互演示工具

做为一个移动端的互联网产品设计师,天天心心念的就是如何做出一款款能让用户爱不释手的应用,想来轻松,做起来点点滴滴都是功能、美观和用户体验的契合难题,在一个个经典...

2995
来自专栏FreeBuf

没时间了,赶紧上车!教你如何在一小时之内加密你的整个数字生活

写在前面的话 Andy Grove曾经担任过英特尔公司的首席执行官,他参与了英特尔公司的创建并主导了公司在1980年-2000年间的成功发展。他是一位匈牙利出生...

2999
来自专栏CSDN技术头条

WWDC的Keynote,开发者们需要关注什么?

北京时间6月14日凌晨1点,2016年苹果WWDC(开发者大会)在美国旧金山的比尔·格雷厄姆市政礼堂举办,此次大会以“四大OS”为主题,虽然没有期待的硬件发布,...

19610
来自专栏顶级程序员

厉害了!小学生用大数据研究苏轼,结论出人意料;Google开源Abseil;使用弱凭证 npm包易受入侵;RStudio 1.1

0、厉害了骚年!小学生用大数据研究苏轼,结论出人意料 ‍ ? 苏轼的诗词大部分人都读过,一些名篇名句也都能脱口而出。但是,苏轼诗词里面用得最多的一个词是什么...

3414

扫码关注云+社区