dingdang robot:一個開源的中文智能音箱項目

歡迎你們前往騰訊雲社區,獲取更多騰訊海量技術實踐乾貨哦~git

做者:潘偉洲github

免責說明:本文介紹的 dingdang-robot 與公司的叮噹助手沒有任何關係。服務器

這個項目其實來源於我生活中的一個需求:我天天晚上都會去廚房作一個麪包當明天的早餐,當我把用料按順序準備好放進麪包機時,我須要準確預定到明天早上我吃早餐的時間。然而,幾乎每次在這個時候我都沒有帶手機在身邊,而是都放在客廳裏充電,這時只能跑去客廳看時間。雖然廚房到客廳只有幾步之遙,但本身又是懶癌患者,天天都要這麼來回奔波就以爲很不方便。要解決這個問題固然有不少種方法,好比直接買個小時鐘放在廚房。不過我更但願「連看都不用看」,直接有人告訴我時間。因此,我須要一個像 Amazon Echo 那樣的智能音箱。微信

然而,不管是 Amazon Echo 、Google Home 仍是微軟 Cortana 音箱,在國內的使用都是個問題。雖然國內也有相似的智能音箱產品,但我沒有用過這些產品,不知道可定製性如何。好比,若是我須要開發個功能讓它告訴我某種麪包的配方是什麼,這些產品就不必定能作到了。考慮再三,我決定本身動手寫一個。整個項目用了差很少三個星期的業餘零碎時間。網絡

先放上項目主頁:http://dingdang.hahack.com框架

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

下面分享一下我在開發這個項目過程當中的心得。ide

硬件

首先要解決的是硬件問題。我選擇在 Raspberry Pi 上開發。因而我買了塊 Raspberry Pi 三代主板。麥克風和音響方面,出於美觀的目的,買了個自帶音響的 USB 全向會議麥克風。整套設備看起來就像這樣:工具

[圖片上傳失敗...(image-99d2ff-1512030430320)]測試

過了不久以爲這個麥克風自帶的音響音質太通常了,因此我又外接了一個小音箱。而後再插了一個攝像頭,用來實現拍照功能,又進化成了這樣:

[圖片上傳失敗...(image-6a565f-1512030430320)]

發佈了不到一個星期,respeaker 的商務經理看到了我這個項目,但願能提供硬件上的支持,因此我又玩上了各類 respeaker 的硬件(作爲回報,我也零報酬給他們帶去了 100 多個 respeaker-2mics-HAT 的銷量):

[圖片上傳失敗...(image-8f30c5-1512030430320)]

由於軟件自己是和硬件解耦的,並不依賴具體的硬件要求,因此不少用戶也本身作了硬件上的定製和嘗試(最後一張圖裏預裝了 dingdang-robot 的是熊,不是妹子 :-p):

[圖片上傳失敗...(image-b39a-1512030430320)]

硬件有了,接下來就得開始寫軟件了。主要的框架借鑑了 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 的選項。當內容過長時,改爲發送到用戶的郵箱或者微信。

[圖片上傳失敗...(image-11938c-1512030430320)]

到了九月份的時候,dingdang-robot 在離線喚醒方面又增長了 snowboy 引擎,在主動聆聽和語音合成方面又增長了阿里、科大訊飛的服務,不管是識別速度和合成音色的豐富程度又有了很大的進步。

[圖片上傳失敗...(image-1c1a35-1512030430320)]

技能插件

叮噹最好玩的部分固然就是玩插件了,經過寫插件可讓叮噹接入各類各樣的服務,完成各類各樣的事情。我在叮噹裏也內置了幾個插件。爲了方便用戶擴展,我定義了三個技能插件目錄:

  • $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 日(是的,我專門挑了個好日子),截至本文發表時,該項目的相關數據以下:

  • Github Stars:418,平均一個月 100 star
  • QQ羣用戶:340
  • pull requests:48
  • 項目主頁 PV:12,000+
  • 捐贈記錄:https://github.com/wzpan/dingdang-robot/wiki/donate-list

雖然數據並非特別亮眼,不過對於這樣的小衆項目,我已經比較滿意了。下面談談我的怎麼維護一個開源項目吧。

前期:作好框架

根據二八法則,項目的前期應該要把整個項目指望能達到的 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 變得更智能!

相關閱讀

CNN 在語音識別中的應用 加權有限狀態機在語音識別中的應用 揭祕騰訊雲Supermind智能網絡,百萬級設備的網絡高效運維


此文已由做者受權騰訊雲技術社區發佈,轉載請註明原文出處

相關文章
相關標籤/搜索