RaspberryPiでgoogle-home-notifierをインストールしてお好みの言葉を話してみる

RaspberryPiでgoogle-home-notifierをインストールしてお好みの言葉を話してみる

GoogleHomeMiniが年末に安売りになったので自分も購入し、天気やキッチンタイマーのようなものに使用していました。 とはいっても、3日ぐらいで飽きるので他の使い方がないのかなと思い、IFTTTからGoogleスプレッドシートへ記録なども行っていました。 IFTTTの連携は結構便利だなーとは思っているのですが言葉をいろいろ決めたりしないといけないので、制限がおおいなあというのが、 実際のところでした。そこで、RaspberryPiと連携し、話す言葉を変更できる連携に手をだしました。

このネタは2017年のアドベントカレンダーではさんざんやりつくされた感じはしたのですが、自分もその波に乗ってみました。 それでもつまずく自分…。今年もいろいろなトラップに引っかかる予感です。

今回紹介するgoogle-home-notifierは非常に簡単な呼び出しを行うだけで話すことができるのでとても便利です。 ただ、RaspberryPiのように常時起動の機器がないと実現ができないのは少しハードルはあるかなと思います。

githubを参考に

github.com

Node.jsの準備

google-home-notifierNode.jsのモジュールなので、新しめのNode.jsの設定をします。最近のバージョンは4.x系なので昔よりはマシになりましたが 最近のLTSあたりにしておくのが無難かなと思います。

過去のエントリーを参考にして設定します。

uepon.hatenadiary.com

やっててよかった備忘録。2018/01/08現在は以下のバージョンがLTSのようです。

$ node -v
v8.9.4

google-home-notifierのインストール

ググったのサイトをみていると

# 任意のフォルダに移動し
$ npm init
$ npm install google-home-notifier

こんな感じで問題ないようなことが書いてあるのですが。 Node.jsの初心者の私にはピンときていませんでした…。

あと、モジュールのインストールを行うとエラーが発生して、インストールが完了しませんでした。

公式のドキュメントにRaspberryPiの項目があるのでそれを見ると

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

Also install these packages:

sudo apt-get install git-core libnss-mdns libavahi-compat-libdnssd-dev

てな記載が。別途パッケージが必要なのね。(ちゃんとドキュメントを読みましょう) パッケージ名を確認するとavahiとかmdnsなライブラリが必要のようです。 (前半部分はNode.jsのインストールなので既に行っていることから省略でもも問題はありません)

インストールに必要な事前準備

以下でパッケージをインストールします。

【コマンド】

$ sudo apt-get install git-core libnss-mdns libavahi-compat-libdnssd-dev

【ログ】

$ sudo apt-get install git-core libnss-mdns libavahi-compat-libdnssd-dev
パッケージリストを読み込んでいます... 完了
依存関係ツリーを作成しています
状態情報を読み取っています... 完了
libnss-mdns はすでに最新バージョン (0.10-8) です。
libnss-mdns は手動でインストールしたと設定されました。
以下の追加パッケージがインストールされます:
  libavahi-client-dev libavahi-common-dev libavahi-compat-libdnssd1
  libdbus-1-dev
以下のパッケージが新たにインストールされます:
  git-core libavahi-client-dev libavahi-common-dev
  libavahi-compat-libdnssd-dev libavahi-compat-libdnssd1 libdbus-1-dev
アップグレード: 0 個、新規インストール: 6 個、削除: 0 個、保留: 3 個。
424 kB のアーカイブを取得する必要があります。
この操作後に追加で 1,285 kB のディスク容量が消費されます。
続行しますか? [Y/n] y
取得:1 http://mirrordirector.raspbian.org/raspbian stretch/main armhf git-core all 1:2.11.0-3+deb9u2 [1,410 B]
取得:2 http://ftp.jaist.ac.jp/pub/Linux/raspbian-archive/raspbian stretch/main armhf libavahi-common-dev armhf 0.6.32-2 [62.6 kB]
取得:3 http://ftp.jaist.ac.jp/pub/Linux/raspbian-archive/raspbian stretch/main armhf libdbus-1-dev armhf 1.10.24-0+deb9u1 [200 kB]
取得:4 http://ftp.jaist.ac.jp/pub/Linux/raspbian-archive/raspbian stretch/main armhf libavahi-client-dev armhf 0.6.32-2 [56.5 kB]
取得:5 http://ftp.jaist.ac.jp/pub/Linux/raspbian-archive/raspbian stretch/main armhf libavahi-compat-libdnssd1 armhf 0.6.32-2 [44.0 kB]
取得:6 http://ftp.jaist.ac.jp/pub/Linux/raspbian-archive/raspbian stretch/main armhf libavahi-compat-libdnssd-dev armhf 0.6.32-2 [58.8 kB]
424 kB を 4秒 で取得しました (102 kB/s)
以前に未選択のパッケージ git-core を選択しています。
(データベースを読み込んでいます ... 現在 124934 個のファイルとディレクトリがインストールされています。)
.../0-git-core_1%3a2.11.0-3+deb9u2_all.deb を展開する準備をしています ...
git-core (1:2.11.0-3+deb9u2) を展開しています...
以前に未選択のパッケージ libavahi-common-dev:armhf を選択しています。
.../1-libavahi-common-dev_0.6.32-2_armhf.deb を展開する準備をしています ...
libavahi-common-dev:armhf (0.6.32-2) を展開しています...
以前に未選択のパッケージ libdbus-1-dev:armhf を選択しています。
.../2-libdbus-1-dev_1.10.24-0+deb9u1_armhf.deb を展開する準備をしています ...
libdbus-1-dev:armhf (1.10.24-0+deb9u1) を展開しています...
以前に未選択のパッケージ libavahi-client-dev:armhf を選択しています。
.../3-libavahi-client-dev_0.6.32-2_armhf.deb を展開する準備をしています ...
libavahi-client-dev:armhf (0.6.32-2) を展開しています...
以前に未選択のパッケージ libavahi-compat-libdnssd1:armhf を選択しています。
.../4-libavahi-compat-libdnssd1_0.6.32-2_armhf.deb を展開する準備をしています ...
libavahi-compat-libdnssd1:armhf (0.6.32-2) を展開しています...
以前に未選択のパッケージ libavahi-compat-libdnssd-dev:armhf を選択しています。
.../5-libavahi-compat-libdnssd-dev_0.6.32-2_armhf.deb を展開する準備をしています ...
libavahi-compat-libdnssd-dev:armhf (0.6.32-2) を展開しています...
libdbus-1-dev:armhf (1.10.24-0+deb9u1) を設定しています ...
libavahi-common-dev:armhf (0.6.32-2) を設定しています ...
libavahi-client-dev:armhf (0.6.32-2) を設定しています ...
libavahi-compat-libdnssd1:armhf (0.6.32-2) を設定しています ...
libc-bin (2.24-11+deb9u1) のトリガを処理しています ...
git-core (1:2.11.0-3+deb9u2) を設定しています ...
libavahi-compat-libdnssd-dev:armhf (0.6.32-2) を設定しています ...

google-home-notifierのインストール

google-home-notifierのインストールはnpmで行います。

今回作業するディレクトリはgooglehomeSampleとしました。適宜読み替えて作業をしてください。 任意のディレクトリとなっていますが、google-home-notifierというモジュール名と同じディレクトリ名にすると エラーになりますので気を付けてください。(自分はハマった

【コマンド】

$ mkdir googlehomeSample
$ cd googlehomeSample/
$ npm init
$ npm install google-home-notifier

公式ページではインストール前のnpm initについては言及がされていませんでしたが、事前にしておくと警告行が減ったので含めています。 npm initではパッケージバージョンの情報やライセンス情報の入力などを求められますが、そのままリターンしました。

【ログ】

$ mkdir googlehomeSample
$ cd googlehomeSample/

$ npm init
This utility will walk you through creating a package.json file.
It only covers the most common items, and tries to guess sensible defaults.

See `npm help json` for definitive documentation on these fields
and exactly what they do.

Use `npm install <pkg>` afterwards to install a package and
save it as a dependency in the package.json file.

Press ^C at any time to quit.
package name: (googlehomesample)
version: (1.0.0)
description:
entry point: (index.js)
test command:
git repository:
keywords:
author:
license: (ISC)
About to write to /home/pi/googlehomeSample/package.json:

{
  "name": "googlehomesample",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC"
}


Is this ok? (yes)

$ npm install google-home-notifier

> mdns@2.3.4 install /home/pi/googlehomeSample/node_modules/mdns
> node-gyp rebuild

make: ディレクトリ '/home/pi/googlehomeSample/node_modules/mdns/build' に入ります
  CXX(target) Release/obj.target/dns_sd_bindings/src/dns_sd.o
  CXX(target) Release/obj.target/dns_sd_bindings/src/dns_service_browse.o
  CXX(target) Release/obj.target/dns_sd_bindings/src/dns_service_enumerate_domains.o
  CXX(target) Release/obj.target/dns_sd_bindings/src/dns_service_get_addr_info.o
  CXX(target) Release/obj.target/dns_sd_bindings/src/dns_service_process_result.o
  CXX(target) Release/obj.target/dns_sd_bindings/src/dns_service_ref.o
  CXX(target) Release/obj.target/dns_sd_bindings/src/dns_service_ref_deallocate.o
  CXX(target) Release/obj.target/dns_sd_bindings/src/dns_service_ref_sock_fd.o
  CXX(target) Release/obj.target/dns_sd_bindings/src/dns_service_register.o
  CXX(target) Release/obj.target/dns_sd_bindings/src/dns_service_resolve.o
  CXX(target) Release/obj.target/dns_sd_bindings/src/dns_service_update_record.o
  CXX(target) Release/obj.target/dns_sd_bindings/src/mdns_utils.o
  CXX(target) Release/obj.target/dns_sd_bindings/src/network_interface.o
  CXX(target) Release/obj.target/dns_sd_bindings/src/socket_watcher.o
  CXX(target) Release/obj.target/dns_sd_bindings/src/txt_record_ref.o
  CXX(target) Release/obj.target/dns_sd_bindings/src/txt_record_create.o
  CXX(target) Release/obj.target/dns_sd_bindings/src/txt_record_deallocate.o
  CXX(target) Release/obj.target/dns_sd_bindings/src/txt_record_set_value.o
  CXX(target) Release/obj.target/dns_sd_bindings/src/txt_record_get_length.o
  CXX(target) Release/obj.target/dns_sd_bindings/src/txt_record_buffer_to_object.o
  SOLINK_MODULE(target) Release/obj.target/dns_sd_bindings.node
  COPY Release/dns_sd_bindings.node
make: ディレクトリ '/home/pi/googlehomeSample/node_modules/mdns/build' から出ま す

> ngrok@2.2.24 postinstall /home/pi/googlehomeSample/node_modules/ngrok
> node ./postinstall.js

ngrok - downloading binary https://bin.equinox.io/c/4VmDzA7iaHb/ngrok-stable-linux-arm.zip
ngrok - downloading progress: 5084312/5084312
ngrok - binary downloaded to /home/pi/.ngrok/aHR0cHM6Ly9iaW4uZXF1aW5veC5pby9jLzRWbUR6QTdpYUhiL25ncm9rLXN0YWJsZS1saW51eC1hcm0uemlw.zip
ngrok - unpacking binary
ngrok - binary unpacked to /home/pi/googlehomeSample/node_modules/ngrok/bin/ngrok
npm notice created a lockfile as package-lock.json. You should commit this file.
npm WARN googlehomesample@1.0.0 No description
npm WARN googlehomesample@1.0.0 No repository field.

+ google-home-notifier@1.2.0
added 138 packages in 170.896s

これでインストールができました。途中でngrokなどもビルドしているようなので少し時間はかかっています。

サンプルを動かす

サンプルは以下のようになっていますが、コアの要素だけを抽出し簡単にしてみました。

【オリジナルのサンプル】 github.com

【機能を絞ったサンプル】

var googlehome = require('google-home-notifier');
var language = 'ja';

googlehome.device('テスト', language);
googlehome.ip('192.168.0.2');// IPアドレスは自分の環境のGoogleHomeの設定に合わせてください

var text = 'こんにちは';

try {
        googlehome.notify(text, function(notifyRes) {
                console.log(notifyRes);
        });
} catch(err) {
        console.log(err);
}

基本的にはgooglehomeの設定(言語設定、IP設定など)を行い、notifyメソッドを実行すると、 いったん音がなり、テキストの読み上げが行われます。

deviceメソッドの第一引数は適当でいいようなのですが、たぶん事前設定した名前にすればIP設定しなくてもいいのかなとなんとなく思いました。(未確認)

警告が表示されますが、特に問題はないようです。 (内容はavahi関連の警告で、今回のコードではIP直接のアクセスだから問題ないのかなと思います。)

【実行のようす】

$ node test.js
*** WARNING *** The program 'node' uses the Apple Bonjour compatibility layer of Avahi.
*** WARNING *** Please fix your application to use the native API of Avahi!
*** WARNING *** For more information see <http://0pointer.de/avahi-compat?s=libdns_sd&e=node>
*** WARNING *** The program 'node' called 'DNSServiceRegister()' which is not supported (or only supported partially) in the Apple Bonjour compatibility layer of Avahi.
*** WARNING *** Please fix your application to use the native API of Avahi!
*** WARNING *** For more information see <http://0pointer.de/avahi-compat?s=libdns_sd&e=node&f=DNSServiceRegister>
Device notified

これで無事音声が出力されました。読み上げた音声はたどたどしい抑揚です。

では固定の文字列ではなくコマンドライン引数にしていした文字列を読み上げるコードに変更してみます。

var googlehome = require('google-home-notifier');
var language = 'ja';

googlehome.device('テスト', language);
googlehome.ip('192.168.0.2');// IPアドレスは自分の環境のGoogleHomeの設定に合わせてください

var text = 'こんにちは';

if(process.argv.length == 3){
        text = process.argv[2];
}

try {
        googlehome.notify(text, function(notifyRes) {
                console.log(notifyRes);
        });
} catch(err) {
        console.log(err);
}

省略した場合は「こんにちは」と出力し、引数に指定した場合には「引数に指定した言葉」を話します。

おわりに

話す言葉の制限がかなりあったGoogleHomeではありますが、これでかなり自由度が高くなりました。

RaspberryPi+OpenJTalk+Bluetoothスピーカーなどの組み合わせを、RaspberryPi+google-home-notifier+GoogleHomeに変更することも可能かなと思います。 数字の読み上げなどがどうなるのかはまだテストしていませんが、それなりに動いてくれるのでは?と思ってはいます。

cronやアラームシステムとの組合わせ、WebAPIとの連携なども簡単にできそうなのでなかなか魅力的な感じです。

それにしても、いつになったらAmazon Echoの招待が来るのだろうか…

/* -----codeの行番号----- */