音声メモをGoogleHomeで記録してMacのShellから遊ぶお話


1. はじめに

Livesense - 関 Advent Calendarの14日目を担当する @Otakumesi です。

AdventCalendarのお題が「関」なので、GoogleHomeとShellを繋げる("関"係させる)話をします。

みなさん、GoogleHomeを買いましたか?

自分は勢いで買ってしまいました。
GoogleHomeを買ったからには、遊んでみないわけにはいかないですよね。
ちなみに、最近の私のマイブームはsay "OK, Google"okgoogleコマンドとしてaliasの登録をしたり、Macのsayコマンドを使ってGoogleHomeに話しかけることです。

それでは、導入はここまでにして本題に入ります。

2. 今回やったこと

その場でなにかが思いついたものの「手元にパソコンやスマートフォンがなかった」なんて経験があると思います。
そういうときには、GoogleHomeに声をかけるだけでメモができれば、そしてそのメモをパソコンで参照ができれば楽だと思いませんでしょうか。

GoogleHomeを使って音声をメモって、そのメモをShellで取り出してクリップボードに突っ込む」ということをやってみました。

3. 使ったツール・サービス

4. GoogleHomeを通じて音声メモを保存する

まずは「OK, Google。メモして。明日は日曜日。」とGoogleHomeに話かけると、FirebaseのDBに「明日は日曜日。」というメッセージが記録をされていく仕組みを作ります。
GoogleHomeとFirebaseと繋げる仕組みには、IFTTTを利用していきます。

Firebaseの設定をする

Firebaseを使う

音声メモのメッセージを記録するDBとして、FirebaseのリアルタイムDBを使います。

Firebaseとは、Googleが提供しているmBaaSです。
開発に必要な様々なサービスを提供していますが、今回はリアルタイムDB利用します。

Fireabaseの利用を開始する

まず、Firebaseのプロジェクトを作成します。
https://console.firebase.google.com/ にアクセスをして「プロジェクトを追加」を選択しましょう。

下記のような画面が表示されますが、プロジェクト名やプロジェクトIDは自由につけてください。

リアルタイムDBを使う

プロジェクトを作成したら、左のメニューから「Database」を選んで利用を開始します。

利用開始後に表示されるページで、ページ内の「ルール」タブを選択して、DBの権限などの設定をします。

今回は作業を簡単にするためにセキュリティを考慮せずに、誰でも読み書きできるようにしてしまいます。
そのため、以下のように.read.writeの値をtrueを設定しましょう。
※この設定ではプロジェクトIDが漏れたら、第三者がこのDBに読み書きできてしまうので注意してください。

ルールの設定のサンプル
{
  "rules": {
    "message": {
      ".read": true,
      ".write": true
    }
  }
}

これでFirebaseの設定は完了しました。
次はGoogleHomeとFirebaseを繋げる手段を用意します。

IFTTTのAppletを作成する

IFTTTを使う

GoogleHomeからFirebaseに繋げる手段として、IFTTTを使います。
IFTTTはコレ(This)した時にアレ(That)するという形で様々なサービスを組み合わせることのできるWebサービスです。

IFTTTには、「GoogleHomeと連携するサービス」と「Webhookを投げるサービス」を提供されているため、この二つを組み合わせてAppletを作成します。
※IFTTTの使い方はこの記事が参考になります。

Appletの作成をし、トリガーの設定をする

https://ifttt.com/create を開いて「+this」をクリックしてトリガーを設定をします。

今回は「GoogleHomeに対して話しかける」ことをトリガーにするため、サービスの中から「GoogleAssistant」を探し出して選びましょう。
選択をするとさらに下記のような選択肢が表示されますが、Say a phrase with a text ingredientを利用します。

次の画面ではGoogleHomeがどういう言葉に反応して、どう答えて欲しいか、どう解釈してほしいかを設定します。

What do you want to say?に「メモして $」と入力します。
そうすると、GoogleHomeは「メモして」というキーワードに反応して、IFTTTとの連携を呼び出してくれるようになります。
また、$はワイルドカードのようなもので、「メモして」以降の言葉がここで認識されます。(後述するアクションで、$で受け取った値を利用します。)

(optional)となっているところを利用すると、「メモして」以外の言葉も同じくキーワードにすることができます。

What do you want the Asisstant to say in response?には、このトリガーが実行された後のGoogleHomeの返事を書きます。

最後に、Languageですが、これは言葉の通りに言語を選択しましょう。

アクションの設定をする

トリガーの作成が終わると、また選択画面に戻りるため「+that」を選択してアクションを設定します。
サービスの中から「Webhook」を選んで、「Make a web request」を利用します。

この画面ではGoogleHomeがトリガーを解釈した後に、どういうアクションをおこなうのかを設定します。

今回はFirebaseにメッセージを登録するため、URLにはFireabaseのURLを入力します。
さきほどのサンプル通りの設定であれば、URLはhttps://${FIREBASE_PROJECT_ID}.firebaseio.com/message.jsonで問題ないです。
${FIREBASE_PROJECT_ID}には設定したFirebaseのプロジェクトIDをいれてください。

MethodはFirebaseに書き込みをおこなうため、POSTに設定します。

Content Typeapplication/jsonにしましょう。

そして、さきほどのトリガー設定時に「メモして。 $」と入力しましたが、この$の部分を{{TextField}}として受け取ることができます。
そのため、Bodyでには以下のように記述をします。

Bodyのサンプル
{"text": "{{TextField}}"}

入力が終わったら「Create action」をクリックしましょう。

これでGoogleHomeに「メモして。XXXXX」と話しかければ、メッセージが{"text": "XXXXX"}という形式でFirebaseのDBに登録されるようになりました。

5. ShellからFirebaseのデータを利用する

ShellからFirebaseのデータを利用する

それでは、Shellからメッセージを利用してみます。

Firebaseはリソースのエンドポイントを叩くとJSONを返してくれます。
そのため、curlhttps://${FIREBASE_PROJECT_ID}.firebaseio.com/message.jsonに対してリクエストを投げれば、Firebaseにのmessageに保存されているメッセージを得ることができます。

$ curl https://${FIREBASE_PROJECT_ID}.firebaseio.com/message.json
{"-L0FKci4hltOsazXKs0k":{"text":"明日 は マック を 受け取り に 行く"},"-L0FQY-NR-KS2nlUBP9L":{"text":"明日 は 飲み 会
"},"-L0FQrMh_dGigSFCr4Wn":{"text":"滑 舌 悪い と 辛い"}}%    

JSONをパースする

しかし、得られる値はJSON形式のため、そのまま利用することはできません。
そのため、ShellでJSONを利用するために、jqを利用します。
jqについてはこの記事が参考になります。

jqを利用して、以下のようなコマンドを叩くとFirebaseに保存されたメッセージの一覧になって出力されます。

# curlの-sで進捗状況を非表示にする
$ curl -s 'https://${FIREBASE_PROJECT_ID}.firebaseio.com/message.json' | jq .[].text -r
明日 は マック を 受け取り に 行く:
明日 は 飲み 会
滑 舌 悪い と 辛い

.[]でキーに関係なくmessageの中身を配列として全て取り出し、それらを.texttext属性のみを返すようにフィルタしています。
そして、-rをつけて結果からダブルクオーテーションをなくしました。

これでFirebaseのメッセージを取得することができました。

メッセージの絞込みをする

とはいえ、このままではDBに登録したメッセージが羅列されているだけに過ぎません。
そこで、メッセージの絞込みをできるようにするため、pecoというツールを利用します。
pecoのについてこの記事が参考になります。

以下のコマンドを実行すると、下記のような画面で音声メモを絞り込んで探すことができます。
curl -s 'https://${FIREBASE_PROJECT_ID}.firebaseio.com/message.json' | jq .[].text -r | peco

これをgoogle-home-memoというaliasにしておくことで、下記のように使えます。

google-home-memoを利用する

この結果をパイプで渡すことで様々なことに使えます。

利用例(Mac)
google-home-memo | pbcopy # クリップボードに入れて使えます
google-home-memo | say    # Macが喋ってくれます

GoogleHomeの可能性の幅が広がりますね(?)

最後に

いかがだったでしょうか。
こんなアホらしいエントリを最後まで読んでいただきありがとうございました。

今回はGoogleHomeとFirebaseを繋げる手段としてIFTTTを使いましたが、この方法だとでは、FirebasのDBを公開な状態にしなければならず、良いやり方ではないと思います。
これを日常的に使ってみたいという物好きな方はDialogFlow経由で利用してみるのがいいかもしれません。

参考文献

新着メールを知らせてくれるGoogle Home
さまざまなサービスが連携できる「IFTTT(イフト)」の使い方
jq コマンドを使う日常のご紹介
pecoの基礎の基礎