Google Home で Rebuild.fm や Backspace.fm を流す方法

Google Home mini を購入したので普段聞いている Podcast の Rebuild.fm や Backspace.fm を簡単に流せる仕組みを構築してみました。
我が家では Google Home mini をキッチンに設置しているので、料理や洗い物をする時に気軽にテック系ポッドキャストを最新やランダム再生できるようになってとても快適になりました。

#### 出来たこと
* Rebuild.fm の最新エピソードを「OK Google リビルド最新」で流す
* Rebuild.fm のランダムエピソードを「OK Google リビルドランダム」で流す
* 簡易なWebUIから任意のエピソードを指定して流す

※ Backspace.fm も同様

構成図
<img width="939" alt="スクリーンショット 2018-01-06 0.42.44.png" src="https://qiita-image-store.s3.amazonaws.com/0/4195/154b1a9c-d97b-065a-437a-cf3cffc8dbbd.png">


## ざっくり仕組み
ひとことで言うと、Goole Home で任意の音声ファイルを流せる google-home-notifier を改造して、podcast の mp3ファイルを再生可能としました。
※ 以下、google-home-notifier の改造版を google-home-podcast と呼ぶことにします。

Google Home からは IFTTT の Goolge assistant を使い、Webhooks 機能で google-home-podcast の API を叩く構成としました。

ただし、google-home-podcast では ngrok を使って外部にURLを公開しており、無料版だと起動の度に URL が変わってしまい不便なので、Google SpreadSheet に URLを記録する方法を使いつつ、Google Apps Script のWebアプリケーションの仕組みを利用して IFTTT の Webhooks から GAS 経由で google-home-notifier を叩く構成にしました。

最新エピソードの URL を取得する方法としては、どちらの Podcast も RSSフィードを提供してくれていたので、google-home-podcast で、 RSSからエピソードのURLを取得するようにしました。
エピソードリストは定期的に更新したいので node.js の Cronライブラリを使って定期収集するようにしました。
また、エピソードが再生の度に毎回最初から再生されるのは嫌なので、再生済み時刻の記録はローカルファイルへ json 形式で記録し、再生時にシークする仕組みとしました。


以下、上記システムの構築方法を述べます。
(かなりざっくりですみません)

### Google スプレッドシート の設定
以下を参考に、新規スプレッドシートの Key と認証Jsonファイルを取得します。

https://qiita.com/k_keisuke/items/3e67aa25a24f07656f47#google-home-notifier%E3%81%8B%E3%82%89google-spreadsheet%E3%81%ABurl%E3%82%92%E6%9B%B8%E3%81%8D%E5%87%BA%E3%81%99


### google-home-podcast の設置
google-home-podcast を動かすには、ローカルPCかラズパイなどの常時起動可能なサーバマシンが必要です。

以下のリポジトリからソースを clone してインストール＆起動します。
https://github.com/volpe28v/google-home-podcast.git

認証Jsonファイルを GoogleHome.json というファイル名にして google-home-podcast ディレクトリ直下に配置します。
起動時のパラメータに取得したスプレッドシートの Key と GoogleHome の IP を指定します。

```
$ npm install
$ SPREAD_KEY=<SpreadSheetKey> GOOGLEHOME_IP=<GoogleHomeIP> node example.js
```

起動すると、ngrok の URL がスプレッドシートに書き込まれるようになります。
このURLを使って Google Apps Script から google-home-podcast の API を叩くようにします。(後述)

また、毎日最新のRSS情報を自動取得して常に最新のエピソードリストを保持するようになります。

### Google Apps Script の設置
スプレッドシートに登録された ngrok の URL に対して API を呼び出すGASコードを記述します。
※コードは google-home-podcast の gas ディレクトリに同梱しています

GASの設定方法は以下が参考になります。
http://shinsuke789.hatenablog.jp/entry/2015/01/03/164203

後に、GASのメソッドを Webhook 可能にする為にWebアプリケーションとして公開するので、 doGet() を実装してしておきます。

```javascript

function doGet(e)
{
  // podcast再生用
  notify2GoogleHome(e.parameter);
  return HtmlService.createHtmlOutputFromFile('index');
}

function notify2GoogleHome(parameter) {
  var url = getNgrokUrl() + parameter.action;
  UrlFetchApp.fetch(url);
}

function getNgrokUrl() {
  if (getNgrokUrl.instance) { return getNgrokUrl.instance; }
  var ngrokSheetId = "スプレッドシートのKey";
  var url = SpreadsheetApp.openById(ngrokSheetId).getSheetByName("YYYY").getDataRange().getValues()[0][0]; // YYYYはワークシート名
  return url;
}
```

### Webアプリケーションの公開
Google Apps Script のAPIを IFTTT の webhook から叩けるように Webアプリケーションとして公開します。

以下を参考に Webアプリケーションを公開しました。
https://dozensmembers.wordpress.com/2014/04/28/google-apps-script-as-a-webhooks-receiver/

### IFTTT の設定
次に、上記Webアプリケーションの Get を叩く IFTTT のアプレットを追加します。

* This として、Google Assistant で「Say a simple phrase」の「What do you want to say?」 に「リビルド最新」などと設定
* That として、Webhooks で「URL」に WebアプリケーションのURLとパラメータを設定

```
https://script.google.com/macros/s/xxxxxxx/exec?action=/google-home-rebuild-latest
```

同様に「リビルドランダム」や「バックスペース最新」「バックスペースランダム」もアプレットを追加する。（個別に追加しないといけないのが面倒。。)
それぞれ、URLのパラメータの action= 以降の部分を以下のように変更する。

```
/google-home-rebuild-random
/google-home-backspace-latest
/google-home-backspace-random
```

### 再生状況のモニタリング
ここまでで、テックなポッドキャストを Goolge Home に話しかけるだけで好きな時にランダムで聞けたりするので十分楽しいのですが、今聞いているエピソードのタイトルや各エピソードの進捗を確認できる簡単なUIを追加しました。

<img width="1215" alt="スクリーンショット 2018-01-10 23.30.12.png" src="https://qiita-image-store.s3.amazonaws.com/0/4195/9da81f4b-3a45-ffc5-bafb-af44b39474a2.png">


google-home-podcast を起動後、 http://localhost:8091 でアクセス可能です。
UIからはエピソード名をクリックすると再生開始することができます。
再生中のエピソードのタイトル名をクリックでエピソードの詳細Webページを開きます。

### RSS更新時にエピソードリストを取得する
毎日自動でRSSから最新エピソードのURLを取得していますが、RSSの更新に合わせて最速で取得する設定も可能です。

IFTTTのアプレットと google-home-podcast の google-home-rebuild-update API を利用します。

* This として、「RSS feed」で「New feed item」の「Feed URL」に以下を設定

```
http://feeds.rebuild.fm/rebuildfm
```
* That として、「Web hooks」で「URL」 に以下を設定

```
https://script.google.com/macros/s/xxxxxxx/exec?action=/google-home-rebuild-update
```

Backspace.fm ではそれぞれ以下になります。

```
http://feeds.backspace.fm/backspacefm
https://script.google.com/macros/s/xxxxxxx/exec?action=/google-home-backspace-update
```

## やってみた感想
Google Home からテキストをしゃべらせる方法を探しているうちに google-home-notifier に出会い、お気に入りの Rebuild.fm や Backspace.fm とかも再生できるかも！？と思い立ってチャレンジしてみました。

仕組みを構築する中で、IFTTT や ngrok や Googleスプレッドシート、GASなどのとても便利なツール群に初めて触れることが出来たのが大きな収穫でした。色々な技術を組み合わせて一つの事を実現するのは楽しいですね。

また、Google Home からの Podcast再生を実現してみると、コンソールに再生時間を出力するだけでは物足りず、どのエピソードがどのくらい再生したのかが知りたくなったので、WebのUI(vue.js + socket.io)を突貫で作成してみましたが、副作用としてUIから任意のエピソードを再生出来るようになってとても便利になりました。(本末転倒な感じはありますが)

この仕組みを使うと、URLを持つ音声ファイルは基本的に何でも再生できることがわかったので、今後も色々応用できそうで楽しみです。