Google Assistant SDKを使って音声認識を行う

## はじめに

[オープンストリーム Advent Calendar 2018](https://qiita.com/advent-calendar/2018/opst)の18日目です。
Google Assistant SDKを触った際に、Google Assistantの音声認識の精度が非常に良かったので
Google Assistant SDKの音声認識機能のみを使うことができないかどうか試してみました。

## やったこと

公式のサンプルプログラムを少し改造し、フロント側で喋った内容をサーバー側でGoogle Assistantを使って音声認識を行うアプリを作成してみました。

## 前提条件

* マイクが使用できる
* GCPアカウントを持っている
* Dockerがインストールされている

## 認証情報を作成する

Google Assistant SDKを使用するための認証情報を作成します。

### Actionsコンソールでプロジェクトを作成する
[Actionsコンソール](https://console.actions.google.com/)を開き、Add/import projectをクリックします。  

<img width="485" alt="001.png" src="https://qiita-image-store.s3.amazonaws.com/0/318588/4d67cd82-475f-a34b-bfa0-34f040675839.png">

初めてActions on Googleを利用する場合は下図の表示が出るので、必要な情報を入力します。

<img width="311" alt="002.png" src="https://qiita-image-store.s3.amazonaws.com/0/318588/6a6989d5-ef1f-843b-e950-48d30cbb17e8.png">

プロジェクト名を入力し、「CREATE PROJECT」をクリックします。

<img width="255" alt="003.png" src="https://qiita-image-store.s3.amazonaws.com/0/318588/f6fae0fe-99dd-f346-833c-11dd569ce98b.png">

作成したプロジェクトのカテゴリを選択します。

<img width="676" alt="004.png" src="https://qiita-image-store.s3.amazonaws.com/0/318588/8df3f910-08b9-1893-c446-f304c0c568e6.png">

カテゴリを選択するとプロジェクトが作成され、下記ページが表示されます。

<img width="956" alt="005.png" src="https://qiita-image-store.s3.amazonaws.com/0/318588/20592384-1e7b-d31e-2fbc-d0f77c2e9be2.png">

このページでデバイスモデルを作成するのですが、先にGoogle Assistant APIを有効にしてからでないとモデル作成後にダウンロードできる認証鍵ファイルでGoogle Assistant APIが使用できないので、このページを表示したまま次のステップに移ります。

### Google Assistant APIを有効にする
[Google Cloud Platform](https://console.developers.google.com/apis/api/embeddedassistant.googleapis.com/overview)を開き、Google Assistant APIを有効にします。  
この時、左上に表示されているプロジェクト名が、先程作成したプロジェクト名と一致するかどうかを確認します。一致する場合は「有効にする」をクリックします。

<img width="568" alt="006.png" src="https://qiita-image-store.s3.amazonaws.com/0/318588/67f36062-af94-3e5b-bcb4-0ff46f4023f8.png">


一致しない場合は左上のプロジェクト名をクリックし、正しいプロジェクトを選択します。

<img width="366" alt="007.png" src="https://qiita-image-store.s3.amazonaws.com/0/318588/b2ec7617-e8be-a0ef-d4df-e23cb08a2f81.png">

プロジェクトを変更すると、API検索画面が表示されるので、「assistant」と入力し、Google Assistant APIを検索し、APIを有効にします。  

<img width="725" alt="008.png" src="https://qiita-image-store.s3.amazonaws.com/0/318588/41b14809-891a-dff2-876b-b1931336814a.png">
<img width="501" alt="009.png" src="https://qiita-image-store.s3.amazonaws.com/0/318588/3f7ca25a-754b-0c7c-c07a-367db3972be1.png">
<img width="537" alt="010.png" src="https://qiita-image-store.s3.amazonaws.com/0/318588/0f75445b-4e01-832d-8c5a-98e42c51a629.png">

### OAuth同意画面を設定する

[Oauth同意画面](https://console.developers.google.com/apis/credentials/consent?authuser=2)を開き、アプリケーション名とサポートメールを設定し、ページの下にある「保存」をクリックします。  

<img width="538" alt="014.png" src="https://qiita-image-store.s3.amazonaws.com/0/318588/fb11a6b0-8bc9-207a-d84d-7102731a1cc9.png">

### デバイスモデルを作成する
「Actionsコンソールでプロジェクトを作成する」で作成したプロジェクトにデバイスモデルを追加します。
「REGISTER MODEL」をクリックします。  

<img width="956" alt="017.png" src="https://qiita-image-store.s3.amazonaws.com/0/318588/12a0c1a3-7436-b4fd-a26e-f00b142276de.png">

下図のように入力し、「REGISTER MODEL」をクリックします。また、この画面の「Model id」を後で使用するのでコピーしておいて下さい。

<img width="315" alt="011.png" src="https://qiita-image-store.s3.amazonaws.com/0/318588/66949bef-c361-7a43-5397-b204a52a94ca.png">

「Download Oauth 2.0 credentials」をクリックして認証鍵をダウンロードし、「Next」をクリックします。

<img width="312" alt="012.png" src="https://qiita-image-store.s3.amazonaws.com/0/318588/be5090fa-d335-02ba-6289-8797205b0c67.png">

特に何も設定せずに「SAVE TRAITS」をクリックします。  

<img width="315" alt="013.png" src="https://qiita-image-store.s3.amazonaws.com/0/318588/44302c77-f403-dd10-a088-e2373bc517ed.png">

## Google Assistant APIを利用して音声認識を行う

いよいよ、Google Assistant APIを使って音声認識を行っていきます。
しかし、この後もpythonやGoogle Assistant SDKのインストール等、面倒が多いので
Dockerファイルを作成しました。

    FROM debian:stretch

    RUN cd && \
        apt-get update && \
        apt-get install -yq python3-dev python3-venv git curl wget ffmpeg && \
        echo export LC_ALL=C.UTF-8 >>  .bashrc && \
        echo export LANG=C.UTF-8 >>  .bashrc && \
        echo source ~/.nvm/nvm.sh >> .bashrc && \
        git clone https://github.com/creationix/nvm.git ~/.nvm && \
        git clone https://github.com/googlesamples/assistant-sdk-python.git && \
        git clone https://github.com/shiraki-s/google-assistant-stt.git && \
        mkdir app && \
        cp google-assistant-stt/pushtalk.py app && \
        cp -r google-assistant-stt/server/* app && \
        cp assistant-sdk-python/google-assistant-sdk/googlesamples/assistant/grpc/assistant_helpers.py app && \
        cp assistant-sdk-python/google-assistant-sdk/googlesamples/assistant/grpc/audio_helpers.py app && \
        cp assistant-sdk-python/google-assistant-sdk/googlesamples/assistant/grpc/device_helpers.py app && \
        cp assistant-sdk-python/google-assistant-sdk/googlesamples/assistant/grpc/browser_helpers.py app

    RUN ["/bin/bash", "-c", " \
            source ~/.nvm/nvm.sh \
            && nvm install 8.9.4 \
            && cd \
            && python3 -m venv env \
            && env/bin/python -m pip install --upgrade pip setuptools wheel \
            && source env/bin/activate \
            && apt-get install -yq portaudio19-dev libffi-dev libssl-dev libmpg123-dev \
            && python -m pip install --upgrade google-assistant-library google-assistant-sdk[samples] \
            && cd app \
            && npm install \
        "]

### Imageをビルドする

    docker build . -t assistant-stt

### コンテナを作成する

コンテナ作成時に環境変数として先程コピーした「Model Id」を使用します。
Model Idは以下のようなフォーマットになっています。

\<Project名>-XXXXX-\<Product名>-XXXXXX

これを以下のようにして環境変数を設定して下さい。

DEVICE_ID = \<Project名>-XXXXX
MODEL_ID = \<Project名>-XXXXX-\<Product名>-XXXXXX


    docker run -p 8888:8888 -e PORT=8888 -e DEVICE_ID=<Project名>-XXXXX -e MODEL_ID=<Project名>-XXXXX -it assistant-stt bash

### 認証を行う

ホスト側からコンテナにダウンロードした認証鍵ファイルを転送します。

    $ docker cp <認証鍵のPath> <コンテナのID>:/root

コンテナ側で下記を実行します。

    $ cd 
    $ source env/bin/activate
    (env) $ google-oauthlib-tool --scope https://www.googleapis.com/auth/assistant-sdk-prototype \
          --scope https://www.googleapis.com/auth/gcm \
          --save --headless --client-secrets <認証鍵のPath>

以下のように表示されるので、URLをコピーし、ホスト側のブラウザで開きます。

    Please visit this URL to authorize this application: https://accounts.google.com.....
    Enter the authorization code:


認証鍵を作成したGoogleアカウントを選択します。

<img width="256" alt="018.png" src="https://qiita-image-store.s3.amazonaws.com/0/318588/4aea3df9-36a1-aeb0-3834-9b6f8a88b4ce.png">

許可をクリックします。

<img width="238" alt="015.png" src="https://qiita-image-store.s3.amazonaws.com/0/318588/4853f224-2464-b82a-8ae7-aae4c9a94d56.png">

表示されているコードをコピーします。

<img width="282" alt="016.png" src="https://qiita-image-store.s3.amazonaws.com/0/318588/ae8736ed-8b92-cf8a-2023-7b167361ff42.png">

コードをコンテナ側に張り付けてEnterを押します。

    Enter the authorization code:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX


### Node.jsサーバーを立ち上げる

コンテナ側で下記を実行します。

    (env) $ cd app
    (env) $ node index.js 

ブラウザからhttp://localhost:8888 に接続します。


### 実行結果

![stt.gif](https://qiita-image-store.s3.amazonaws.com/0/318588/81b199b4-4c7a-f9d3-92ef-7a2dc6724118.gif)

### 最後に

音声認識の実行速度等、改善点は多々ありますがGoogle Assistant SDKを使って音声認識ができました。  
最後まで読んでいただき、ありがとうございました。