クラウド側からプッシュしたテキストをAndroidタブレットに読み上げさせる (MacrodroidのWebhook + Text to Speech)


TL;DR

MacroDroidはWebhookをトリガーにすることができる。
HTTP GET https://https://trigger.macrodroid.com/DEVICE_ID/NAME?param=ABC
と投げ込むと MacroDroid変数 g_param が設定できるので、テキスト読み上げアクションの中から [v=g_param] と参照することでText to Speechができる。

概要

こんな感じで話せることが可能です。(YouTubeに飛びます)
Text to Speech by MacroDroid

Android OSの自動化アプリ「MacroDroid」は、Androidが元々持っている音声読み上げ機能(Text to Speech; 以下 TTS)が利用できます。
そして、TTSはMacroDroidのWebhookトリガーから起動できるので、クラウド側からプッシュしたテキストをAndroidに読み上げさせることが可能です。

確認環境

  • TECLAST P80X (Android 9)
  • MacroDroid 5.7

MacroDroidでの手順

  • 1. 変数
    • Webhook経由で送信されたテキストを保存しておくグローバル変数の作成
  • 2. マクロ
    • トリガー > 接続 > Webhook
      • 識別子を入力してURLを作成、入手
    • アクション > 機器アクション > テキストを読み上げる
      • 読み上げるテキストにグローバル変数を指定

以上で準備が整います。
あとはHTTP ClientからWebhook URLに対して、読み上げさせたいテキストをパラメータとして付けてHTTP GETするとテキストが読まれます。

MacroDroid: 変数

Webhookで投げ込まれたパラメータは、MacroDroid内の一致するグローバル変数名の値として設定できます。
ここでは tts_text としました。

MacroDroid: マクロ / トリガー > 接続 > Webhook

識別子を入力すると、最終的なWebhook URLが作成されます。このURLをメモしておいてください。
ここでは text2speech という識別子としました。

注意点

  1. 短縮URLでも問題なく機能しますがtinyurlはMacroDroidとは別サービスですので、経由するか否かは検討の余地があります。
  2. trigger.macrodroid.com/ の後に続くランダム文字列の再生成はアプリの再インストール、もしくはアプリデータの消去にて可能のようです(未調査)。URL漏洩にはお気を付けください。

MacroDroid: マクロ / アクション > 機器アクション > テキストを読み上げる

読み上げるテキストを入力 にMacroDroid変数を参照するようにします。
ここでは [v=tts_text] としています。

実行: curl

curlコマンドで実行できます。

$ curl "https://trigger.macrodroid.com/${DEVICE_ID}/text2speech?tts_text=ABC"
ok

「エービーシー」と話し始める事でしょう。

日本語も話させることが可能です。
UTF-8をURLエンコードします。 --get を使うと --data-urlencode をURLエンコードしつつ、QueryStringにしてくれます。

$ curl --get --data-urlencode "tts_text=日本語も話せます" https://trigger.macrodroid.com/${DEVICE_ID}/text2speech
ok
$ curl --get --data-urlencode "tts_text=現在の時刻は、$(date +%H:%m)です。" https://trigger.macrodroid.com/${DEVICE_ID}/text2speech
ok

実行: AWS Lambda

URLを環境変数 MACRODROID_WEBHOOK_URL に設定します。
テストや呼び出しは {"tts_text": "大丈夫だ、問題ない。"} とすればOKです。

macrodroid_webhook_invoker
# for Python 3.8
import urllib.request
import os
MACRODROID_WEBHOOK_URL = os.environ['MACRODROID_WEBHOOK_URL']

def lambda_handler(event, context):
    print(event)
    if 'tts_text' in event:
        payload = {'tts_text': event['tts_text']}
    url = f'{MACRODROID_WEBHOOK_URL}?{urllib.parse.urlencode(payload)}'
    with urllib.request.urlopen(url) as res:
        print(res.read().decode("utf-8"))
    return {'statusCode': 20

他のLambda関数から呼び出したい場合は boto3.client('lambda').invoke() で OK です。
呼び出し元のLambda関数にInvokeFunctionポリシーの付与をお忘れなく。

他のLambdaから呼び出す例
import boto3
w = '晴れ'
t = {'tts_text': f'今日の天気は{w}です'}
boto3.client('lambda').invoke(FunctionName='macrodroid_webhook_invoker', InvocationType='Event', Payload=json.dumps(t))

おわりに

今年もよろしくお願いします。

EoT