Node.js
GoogleHome

google-home-notifierを使ってラズパイからGoogle Homeをしゃべらせる

top.png

google-home-notifier

https://github.com/noelportugal/google-home-notifier
Node.jsを使ってGoogle Homeに任意の音声や音楽を再生させることができるライブラリです。今回はこれをRaspberry Pi 3(ラズパイ)にインストールして使ってみます。

準備と環境

ラズパイは予めネットワークの設定が済ませてあり、Node.js、npmがインストールされている前提で進めます。今回試した環境は以下の通りです。

node v8.9.1
npm 5.5.1

ここで重要なのがnodeのバージョンです。今回はnode v8.9.1を使いましたが、node v10.0.0では npm install でエラーが生じました。もしかするとv9.x系のバージョンでもエラーが発生するかもしれません。ライブラリのREADMEをよくみると

Raspberry Pi
If you are running from Raspberry Pi make sure you have the following before nunning "npm install": Use the latest nodejs dist.

curl -sL https://deb.nodesource.com/setup_7.x | sudo -E bash -
sudo apt-get install nodejs

とあり、最新のnodeバージョンを使用する旨が記載されています。上記のコマンドではv7.x系が指定されているので、v7.x系〜v8.x系であれば動作するのかもしれません。もしインストールがうまくいかない場合は、 node -v でバージョンを確認し、nvmやnodebrewを使ってnodeのバージョンを切り替えると良いでしょう。

インストール

ターミナルで以下のコマンドを入力します。

git clone https://github.com/noelportugal/google-home-notifier
cd google-home-notifier
sudo apt-get install git-core libnss-mdns libavahi-compat-libdnssd-dev
npm install

サンプルコード

同じフォルダ内に新規に app.js というファイルを作成して以下のコードを記述します。

app.js
const googlehome = require('./google-home-notifier')
const language = 'ja';

// googlehome.device('Google-Home-xxxx-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx', language);
googlehome.ip('192.168.1.20', language);

googlehome.notify('こんにちは。私はグーグルホームです。', res => {
    console.log(res);
});


// googlehome.play('http://example/sample.mp3', res => {
//     console.log(res);
// });

ip()の引数にはGoogle HomeのIPアドレスと言語を指定します。Google HomeのIPアドレスはスマートフォンのGoogle Homeアプリから「デバイス」を選択し、Google Homeのカードの右上「︙」をタップして「設定」の一番下の「情報」の項目に表示されています。

実行

app.js を保存したら、ターミナルから以下のコマンドを入力します。

node app.js

実行するとGoogle Homeから「ディロン♪」「こんにちは。私はグーグルホームです。」と聞こえるか確認してみてください。notify()の引数の文字列を変更することで任意のメッセージを送ることができます。

結果

google-home-notifierを使った発声は標準のGoogle Homeからの発声とは異なり、発声スピードが遅く、日本語の発音も不自然に聞こえたかと思います。これはgoogle-home-nootifierが内部的にGoogleのText-To-Speech APIを使った実装になっているからのようです。

もし、好きな音声で発声させるようにしたい場合は、あらかじめ録音しておいた音声ファイルをネットワーク上に配置し、play()関数の引数にファイルのURLを渡すことで任意の音声ファイルを再生することができます。以下の記事にラズパイ上に音声ファイルを返すAPIをexpressで実装した事例が紹介されています。

参考:帰宅したらGoogleHomeから好きな音声で「おかえり」って言ってもらいます - Qiita

play()関数を使うと音声だけでなく、WAVやMP3形式の音楽ファイルも再生することができます。さらに、決め打ちの音声ファイルだけでなく、外部サービスと連携して動的に音声ファイルを生成したい場合はHOYA株式会社のVoiceText Web APIを使うとより自然に人の声に近い発声をさせることができます。VoiceText Web APIは非商用かつ二次利用しなければ無料で使えるようです。

補足1

上にあげたサンプルコード上ではコメントアウトしてありますが、device('{名前}')でGoogle Homeの名前を指定することも可能です。しかし、ここでいう名前はGoogle Homeアプリで設定した名前ではなくGoogle Homeが固有にもつIDです。IPアドレスではなく、device('{名前}')でGoogle Homeを指定できるようにするには、READMEに書いてあるように、 フォルダ内にあるnode_modules/mdns/lib/browser.js を以下のように編集します。

変更前

Browser.defaultResolverSequence = [
  rst.DNSServiceResolve(), 'DNSServiceGetAddrInfo' in dns_sd ? rst.DNSServiceGetAddrInfo() : rst.getaddrinfo()
, rst.makeAddressesUnique()
];

変更後 (横スクロールすると変更点が見えます)

Browser.defaultResolverSequence = [
  rst.DNSServiceResolve(), 'DNSServiceGetAddrInfo' in dns_sd ? rst.DNSServiceGetAddrInfo() : rst.getaddrinfo({families:[4]})
, rst.makeAddressesUnique()
];

変更後、app.jsgooglehome.device() のコメントアウトを外して一度実行してみます。そうするとターミナル上に

Device "Google-Home-xxxx-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" at 192.168.1.20:8009

と表示されます。ここで表示された Google-Home-xxxx... をコピーし、device()の引数に記述することでdevice名で指定することが可能になります。うまく動作したらip()でIPアドレスで指定した方はコメントアウトして構いません。

補足2

package.jsonmdnsmdns-js に変更後、npm install し、 google-home-notifier.jsの require('mdns ') を require('mdns-js') に修正することでインストールと動作を可能にすることができます。この場合は、mdnsで名前解決できないのでdevice()は使えずip()による指定でしか動作させることはできませんでした。nodeのバージョンが変えられない場合は、こちらの方法がおすすめです。

参考:ラズパイにgoogle-home-notifierを入れようとしたけどつまづいた - Qiita

補足3

どうしてもgoogle-home-notifierがうまく動作しない場合は、castv2-clientを使って同じようにGoogle Homeにしゃべらせることができるようです。

参考:Google Homeに話をさせる – 山本隆の開発日誌