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

![top.png](https://qiita-image-store.s3.amazonaws.com/0/70925/2af6862a-0fbe-5964-d4a8-be6f2fe38016.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](https://github.com/noelportugal/google-home-notifier)をよくみると

>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` というファイルを作成して以下のコードを記述します。

```javascript: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のカードの右上「︙」をタップして「設定」の一番下の「情報」の項目に表示されています。

<img src="https://qiita-image-store.s3.amazonaws.com/0/70925/5358fa3b-318f-a703-3ead-bface1f382d2.png" width=100%>


# 実行
`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](https://qiita.com/taaaaaaak22/items/abfb9f2a672689c20505)

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

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

**変更前**

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

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

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

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

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

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

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

参考：[ラズパイにgoogle-home-notifierを入れようとしたけどつまづいた - Qiita](https://qiita.com/tkyko13/items/163e80d3b65543d6a9da)

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

参考：[Google Homeに話をさせる – 山本隆の開発日誌](https://www.gesource.jp/weblog/?p=8083)