Python
lambda
Alexa
GoogleAssistant
スマートスピーカー

GoogleアシスタントをAlexa Skillにして「アレクサ、オーケーグーグルで天気を調べて」をGoogleアシスタントの声で応答する

前回「GoogleアシスタントをAlexa Skillにして「アレクサ、オーケーグーグルで天気を調べて」を実現する」という投稿をしました。

少し改良し、Googleアシスタントの声で応答を返すように改良しました。

こんな感じです。

処理の流れ

  1. Echoに話しかける
  2. Skill Kit(AWS Lambda)にリクエストが来る
    1. Googleアシスタントにリクエストを投げる
    2. Googleアシスタントからレスポンス(音声・テキスト)が返却される
    3. 音声を一度tmp領域にファイル出力する
    4. ffmpegでAlexaのフォーマットに変換する
    5. 変換した音声ファイルをS3にアップロードする(バケットはパブリック公開しておく)
    6. S3にアップロードした音声ファイルのURLをaudioタグに入れたSSMLレスポンスを返却する
  3. EchoがGoogleアシスタントの声で返事をする

長くなりそうなので、要点だけ解説します。
ソースコードはこちら

Googleアシスタントからのレスポンスをファイルに出力する

Googleアシスタントのレスポンス中のresp.audio_out.audio_dataが複数に分割されて取得されるので、連結してファイルに出力します。

response_audio_data = b''
for resp in self.assistant.Assist(iter_assist_requests(),
                                  self.deadline):
    if resp.audio_out.audio_data:
        response_audio_data += resp.audio_out.audio_data
def save_file(output_path, binary):
    with open(output_path, "wb") as fout:          
            fout.write(binary)

音声ファイルをAlexaのフォーマットに変換する

Googleアシスタントのレスポンスは、mp3で取得できますが、Alexaが求める要件は以下の用になっています。

音声ファイルをAlexaに適した形式に変換する

必要に応じて、変換ソフトウェアを使用してMP3ファイルを必要なコーデックバージョン(MPEGバージョン2)とビットレート(48 kbps)に変換してください。

丁寧にffmpegのパラメーターの記述もあります。

ffmpeg -i <input-file> -ac 2 -codec:a libmp3lame -b:a 48k -ar 16000 <output-file.mp3>

ffmpegはLambdaの環境には準備されていないので、デプロイパッケージに含める必要があります。
ffmpegは ここ の「Linux Static Builds」のリンク先からx86_64 buildのものを取得しました。
取得したファイルの中にある、ffmpegバイナリーのみを、デプロイパッケージのルートに格納されるように圧縮します。

Pythonのプログラム中でffmpegを呼び出す部分はこんな感じです。

def convert(input_path, output_path):
    try:
        command = './ffmpeg -i '+input_path+' -ac 2 -codec:a libmp3lame -b:a 48k -ar 16000 -af volume=2.0 ' + output_path
        output = subprocess.check_output(
            command, stderr=subprocess.STDOUT, shell=True, timeout=3,
            universal_newlines=True)
    except subprocess.CalledProcessError as exc:
        print("Status : FAIL", exc.returncode, exc.output)
    else:
        print("Output: \n{}\n".format(output))

つづく