Twilioで自分だけのコンシェルジュ作ってみた

# はじめに
はじめまして、ykyukiと申します。
TwilioとGoogle アシスタントをつなげると面白そうだったので作ってみました。

# できたもの
<iframe width="560" height="315" src="https://www.youtube.com/embed/mkmG5Ni__cc" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>

# 作り方
## 注意
Google Assistant APIは開発中のデバイスまたはソフトウェアのみで利用できるAPIです。
電話番号を公開するなどして、不特定多数の人が使えるようにしないでください。
規約: https://developers.google.com/assistant/sdk/terms-of-service

## GitHub
https://github.com/ykyuki/Phone-Concierge
READMEにもだいたい同じことが載ってます。

## 必要なもの
* Twilioアカウント(トライアルでも動きます)
* Googleアカウント

```
$ cat /etc/lsb-release 
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=22.04
DISTRIB_CODENAME=jammy
DISTRIB_DESCRIPTION="Ubuntu 22.04.1 LTS"
```

## Twilio側の準備
[これ](https://github.com/TwilioDevEd/voice-javascript-sdk-quickstart-node#gather-config-values)を参考に.envを作ります。
API Keyはコンソール右上の「Account」→「API keys & tokens」にあります。
(最初見つからなかった...)

## Google Assistant側の準備

1. [これ](https://developers.google.com/assistant/sdk/guides/service/python/embed/config-dev-project-and-account)を参考にプロジェクトを作り、OAuth同意画面を設定します。
テストユーザーに自分を追加しておくのをお忘れなく
2. [認証情報](https://console.cloud.google.com/apis/credentials)のタブで認証情報を作成します。
「+認証情報の作成」→「OAuth クライアント ID」から

| 項目名 | 値 |  |
| -------- | -------- | -------- |
| アプリケーションの種類 | ウェブアプリケーション | |
| 名前 | (お好きに) | |
| 承認済みのリダイレクト URI | 適当なURL | 入力しないと認証に失敗します |

3. jsonファイルをkey.jsonという名前でmic-speaker.jsと同じ場所に保存します。
この場合はsrc/ですね。

## お決まりのやつ
```
$ npm install
$ npm start
```

## TwiML appの設定
1. なんらかの方法([ngrok](https://ngrok.com/)など)で3000番ポートを公開します。
後で使うのでブラウザで開いておきます。(**Chrome推奨** Firefoxだと出力先デバイスの変更ができないみたいです)
2. 作成したTwiMLの設定画面を開き、「Voice Configuration」→「Request URL」をhttps://example.com/voice のように/voiceをつけて入力し、保存します。
※「Save」ボタンを押さないと保存されないので注意！
3. 着信に使いたい番号の設定画面を開きます。
左メニュー 「リージョン」→「Phone Numbers」→「Manage」→「Active Numbers」から使いたい番号を選択
4. 「Voice & Fax」を下記のように設定します。

| 項目名 | 値 |
| -------- | -------- |
| CONFIGURE WITH | TwiML App |
| TWIML APP | (作成したTwiML Appを選択) |

※「Save」ボタンを押さな(ry

詳しくは[ここ](https://github.com/TwilioDevEd/voice-javascript-sdk-quickstart-node#local-development)の7番以降を参考にしてください。

## 仮想オーディオの設定
PalseAudio 音量調節がインストールされていない場合はインストールします。
```
$ sudo apt install pavucontrol
```
仮想オーディオデバイスを作ります。
```
$ npm run-script make-vas
```
※仮想オーディオデバイスの削除はnpm run-script remove-vas

頑張って下記のように設定します
| ソース | デバイス | 設定場所 |
| -------- | -------- | -------- |
| このプログラムの入力(マイク) | Monitor of VoiceOutput | pavucontrolの録音タブ | 
| このプログラムの出力 | AssistantOutput | OSの設定 |
| ブラウザの入力(マイク) | Monitor of AssistantOutput | pavucontrolの録音タブ |
| ブラウザの出力 | VoiceOutput | ブラウザ上で(Speaker Devicesを変更) | 

※pavucontrolの録音タブは実行中のプログラムしか表示されないので注意してください。

# リスペクトさせていただいたもの
[TwilioDevEd/voice-javascript-sdk-quickstart-node](https://github.com/TwilioDevEd/voice-javascript-sdk-quickstart-node#local-development)
全部というか(ほぼ)そのまま使ってます。

[endoplasmic/google-assistant](https://github.com/endoplasmic/google-assistant)
examples/mic-speaker.jsとライブラリ本体を使ってます。

# 今後やりたいこと
* 仮想オーディオデバイスを使わずに動作
[WebSocketで音声データを直接受け取れるみたいです](https://www.twilio.com/docs/voice/tutorials/consume-real-time-media-stream-using-websockets-python-and-flask)
* 応答の高速化
* ウェイクワード(OK Googleなど)対応
ウェイクワードエンジンを使えばできそうです