Orange Pi Google Assistantのインストール

ARMv7l系列のCPUを搭載したコンピュータボードに対応したPythonによるGoogle Assistant SDKをOrange Pi PCにインストール、音声による検索、時刻確認、タイマーセットなどが実行できるシステムを構築します。ALSAによるスピーカとマイクの設定がポイントとなります。Raspberry Pi 2 または3へのインストールについては既に多くの情報源があり、そちらを参考にインストールして下さい。

■対象ハードとOS

Orange Pi PC: ARMBIAN 5.25 stable Ubuntu 16.04.2 LTS 3.4.113-sun8i (Ubuntuベース)

■事前準備

音声によるGoogleとのコミュニケーションを確立するため、事前にGoogle上での登録作業が必要となります。

Google Assistant SDKのページの、他のプラットフォームでの設定ページ Configure a Developer Project and Account Settings にアクセスします。

https://developers.google.com/assistant/sdk/prototype/getting-started-other-platforms/config-dev-project-and-account

次に Set activity controls for your account で指定されたアクティビティ管理ページActivity Controls pageで全てのアクティビティを有効にして下さい。

https://myaccount.google.com/activitycontrols

上記項目の1でプロジェクトを作成、項目2でプロジェクトへのAPIを有効にして、項目3でAPI認証情報を作成(アプリケーションの種類はその他を指定)・ダウンロード(client_secret_XXXXX.json)します。

■Python3開発環境のインストール

Python3仮想環境内にGoogle Assistant SDKをインストールするためのPython3開発環境をインストールします。

$ sudo apt-get update
$ sudo apt-get install python3 python3-dev python3-venv

ユーザデレクトリ内に仮想環境を構築します。(仮想環境構築場所は任意)

$ python3 -m venv env

上記で構築した仮想環境内のPython pip モジュールのアップデートとsetuptoolsモジュールのインストールをします。

$ env/bin/python -m pip install --upgrade pip setuptools

仮想環境での作業を有効化します。Pythonによるスクリプトは全て仮想環境内で実行されます。

仮想環境に入るとユーザ名の前に(env)が表示されます。

$ source env/bin/activate

(env) user@orangepipc:~$ …

仮想環境から抜ける場合は以下コマンドを実行して下さい。

(env)$ deactivate

■APIの認証(証明書発行)作業

API認証用Pythonモジュールをインストールします。

(env)$ pip install --upgrade google-auth-oauthlib[tool]

ダウンロードした認証情報 client_secret_XXXXX.json を指定(ファイル保存パスを指定)して証明書発行作業を行います。

(env)$ google-oauthlib-tool --client-secrets path/to/client_secret_XXXXX.json --scope https://www.googleapis.com/auth/assistant-sdk-prototype --save --headless

上記コマンドを実行すると証明書発行コードを入手するためのリンク先アドレスが表示されます。

Please visit this URL to authorize this application:https://accounts.google.com/o/oauth2/auth.........................

ブラウザにアドレスをコピー&ペーストし証明書発行用コードを入手するための手続きを行って下さい。

手続きが完了すると証明書発行用コードが表示されます。

以下のようにターミナル上に表示されている場所に発行用コードをコピー&ペーストして下さい。

Enter the authorization code:

認証が成功すると .config/google-oauthlib-tool/credentials.json 証明書ファイルが作成されます。

■Google Assistant SDK, Google Assistant Library のインストール

Githubの該当ページにアクセスします。

google-assistant-sdk をpipによりインストールします。

(env)$ pip install --upgrade google-assistant-sdk

Google Assistantの録音・再生に必要なライブラリとPythonサンプルコードをインストールします。

(env)$ sudo apt-get install portaudio19-dev libffi-dev libssl-dev
(env)$ pip install --upgrade google-assistant-sdk[samples]

google-assistant-library をpipによりインストールします。

(env)$ pip install --upgrade google-assistant-library

■ALSA設定ファイルの作成

Orange Pi PCにはマイクが実装されているため、これを利用するためのALSA設定ファイルを作成します。

ユーザのホームディレクトリ直下に .asoundrc ファイルを作成します。内容は以下の通りです。
(/etc/asound.confで設定している場合には必要ありません。ユーザレベルの設定である.asoundrcとシステムレベルの設定である/etc/asound.confとの内容重複は避けて下さい。)

 pcm.!default {
   type asym
   playback.pcm "plug:softvol"
   capture.pcm "plug:dsnooper"
 }
 pcm.dmixer {
      type dmix
      ipc_key 321456 #any unique value
      ipc_key_add_uid true
      slave {
		pcm "hw:0,0"
      }
      bindings {
          0 0
          1 1
      }
 }
 pcm.dsnooper {
      type dsnoop
      ipc_key 821456
      slave {
		pcm "hw:0,0"
		channels 2
      }
      bindings {     モノラルサウンドを左右のスピーカから出力するために必要な設定です。
          0 0
          1 1
      }
 }
 pcm.softvol {
      type softvol
      slave { pcm "dmixer" }
      control {
          name "Master"
          card 0
      }
 }
 ctl.softvol {
   type hw
   card 0
 }
 ctl.!default {
   type hw
   card 0
 }

■Google AssistantのPythonサンプルコードの実行

インストールしたGoogle Assistant SDKのPythonサンプルコードを実行します。

(env$) googlesamples-assistant-hotword

または、Google Assistant Library をインストールした際のデモ用Pythonコードを実行します。

(env)$ google-assistant-demo

"OK Google"または"Hey Google"のホットワードをマイクで検知するかどうかターミナルで確認して下さい。

(env)$ googlesamples-assistant-hotword
ON_MUTED_CHANGED:
  {'is_muted': False}
ON_START_FINISHED

ホットワードを検知すると以下表示されます。

ON_CONVERSATION_TURN_STARTED

キーワード"weather"をボイス入力した場合は、天気情報がスピーカーから出力されます。

ON_END_OF_UTTERANCE
ON_RECOGNIZING_SPEECH_FINISHED:
  {'text': 'weather'}
ON_RESPONDING_STARTED:
  {'is_error_response': False}
ON_RESPONDING_FINISHED
ON_CONVERSATION_TURN_FINISHED:
  {'with_follow_on_turn': False}

■gRPC APIによるGoogle Assistant

gRPC APIを利用する場合には、以下pipによりインストールして下さい。

(env)$ pip install --upgrade google-assistant-grpc

gRPC APIによるGoogle Assistantサンプルコードは、google-assistant-sdkのサンプルコードインストールの際に既にインストールされています。

(env)$ googlesamples-assistant-pushtotalk

.asoundrcの設定はhotword、demoコードと同じです。

googlesamples-assistant-pushtotalkサンプルコードは、一回のリクエスト毎にターミナルによるキー入力が求められるので、これを機器本体に取付けたスイッチによる入力毎に音声サービスをリクエストするように変更します。スイッチを押すと待機状態が解除されLEDが点灯、音声入力、googleからの返答後LEDが消灯して待機状態に戻ります。

sysfsによるGPIO制御を利用します。

import sysライブラリを追加します。

import json
import logging
import os.path
import sys

サンプルコードの以下の箇所にdef read_button(), def write_led(value)を追加します。

ASSISTANT_API_ENDPOINT = 'embeddedassistant.googleapis.com'
END_OF_UTTERANCE = embedded_assistant_pb2.ConverseResponse.END_OF_UTTERANCE
DIALOG_FOLLOW_ON = embedded_assistant_pb2.ConverseResult.DIALOG_FOLLOW_ON
CLOSE_MICROPHONE = embedded_assistant_pb2.ConverseResult.CLOSE_MICROPHONE
DEFAULT_GRPC_DEADLINE = 60 * 3 + 5

def read_button():
    fp1 = open("/sys/class/gpio/gpio6/value","r")
    value = fp1.read()
    return int(value)
    fp1.close()

def write_led(value):
    fp2 =  open("/sys/class/gpio/gpio10/value","w")
    fp2.write(str(value))
    fp2.close()

次に以下の箇所を変更します。read_button()の戻り値の型はintにする必要があります(def read_button()でintに指定)

while True:
            if wait_for_user_trigger:
                while True:                
                    #print(read_button())
                    button_status = read_button()
                    if button_status == 1:
                        break
            write_led(1)
                #click.pause(info='Press Enter to send a new request...')
            continue_conversation = assistant.converse()
            # wait for user trigger if there is no follow-up turn in
            # the conversation.
            wait_for_user_trigger = not continue_conversation
            write_led(0)
            # If we only want one conversation, break.
            if once and (not continue_conversation):
                break