Office 365で受信メールに添付された音声ファイルをMicrosoft Power AutomateとGoogle Cloud Speechで自動文字起こし


※2019/10/4のMicrosoft社の発表の通り、従来の「Microsoft Flow」は新機能のUI Flowsが追加されて「Microsoft Power Automate」となりました。記事内のMicrosoft Flowの記述はPower Automateに読み替えて下さい。

はじめに

Office 365(Outlook)で受信メールに添付された音声ファイルをMicrosoft FlowとGoogle Cloud Speechで自動で文字起こしして、別のアドレスに転送してくれる機能を作った際のメモ。

経緯としては、現在利用しているSMARTalkというIP電話サービスで、不在着信時の留守電音声をWAVファイルにしてメール送付してくれる機能があり、そのWAVファイルをOffice 365 で受信した際に自動で文字起こしすることによって音声を再生しなくても留守電の内容を把握できるようにしたかった。

構築手順

前提

  • Office 365(Outlook、Microsoft Flow)
  • Google Cloud Platform

Google Cloud Platformの準備

リフレッシュトークンの取得

【GCP】Google Cloud Storage を curl コマンドで利用する に記載の以下手順を実施して、Google Cloud Storage への読み取り・書き込み権限およびCloud Speech-to-Text APIの利用権限を持ったリフレッシュトークンを取得する。

  • Google Cloud Storage JSON API の有効化(この時、Cloud Speech-to-Text APIも追加で有効化すること)
  • OAuth 同意画面作成(この時、[スコープの追加]でCloud Speech-to-Text APIで検索してヒットする../auth/cloud-platformもスコープに追加すること)
  • クライアントID作成(この時、scopeクエリの値はhttps://www.googleapis.com/auth/devstorage.read_write%20https://www.googleapis.com/auth/cloud-platformとすること)
  • 認証コードの取得
  • アクセストークン/リフレッシュトークンの取得

Google Cloud Storageのバケットを作成

Google Cloud Storageにバケットを作成する。

文字起こしされる音声ファイルは一時的にこのバケットにアップロードされる。

フロー作成(音声認識結果取得まで)

1. フローを新規作成

  1. Microsoft Flow画面に接続してマイ フロー画面を表示
  2. [新規]-[自動-一から作成]をクリック
  3. 適当なフロー名を指定し、トリガー一覧から「When a new email arrives (V2)」を選択して[作成]をクリック

2. 新しいメールが届いたとき トリガーの設定

  1. 既に作成されている「新しいメールが届いたとき」トリガーを以下のように設定
プロパティ名 説明
フォルダー 受信トレイ 任意のメールフォルダ
開始 [email protected] SMARTalkの場合の差出人アドレス
添付ファイルあり はい
添付ファイルを含める はい
件名フィルター 【SMARTalk】メッセージお預かり通知 SMARTalkの場合の件名

3. HTTP GCSアクセストークン取得アクションの作成

  1. [新しいステップ]をクリック
  2. アクション一覧より、[HTTP]を選択
  3. プロパティを以下のように設定
プロパティ名
アクション名 HTTP GCSアクセストークン取得
方法 POST
URI https://www.googleapis.com/oauth2/v4/token
クエリ 下記のquery.jsonの内容を設定
query.json
{
  "refresh_token": "<前手順で取得したリフレッシュトークン>",
  "client_id": "<前手順で取得したクライアントID>",
  "client_secret": "<前手順で取得したクライアントシークレット>",
  "grant_type": "refresh_token"
}

4. JSON の解析 GCSアクセストークン取得 アクションの作成

  1. [新しいステップ]をクリック
  2. アクション一覧より、[JSON の解析]を選択
  3. プロパティを以下のように設定
プロパティ名
アクション名 JSON の解析 GCSアクセストークン取得
コンテンツ @{body('HTTP_GCSアクセストークン取得')}
スキーマ 下記のschema.jsonの内容を設定
schema.json
{
    "type": "object",
    "properties": {
        "access_token": {}
    }
}

5. JSON の解析 添付ファイル アクションの作成

  1. [新しいステップ]をクリック
  2. アクション一覧より、[JSON の解析]を選択
  3. プロパティを以下のように設定
プロパティ名
アクション名 JSON の解析 添付ファイル
コンテンツ @{first(triggerBody()?['Attachments'])}
スキーマ 下記のschema.jsonの内容を設定
schema.json
{
    "type": "object",
    "properties": {
        "ContentBytes": {}
    }
}

6. HTTP バケットへアップロード アクションの作成

  1. [新しいステップ]をクリック
  2. アクション一覧より、[HTTP]を選択
  3. プロパティを以下のように設定
プロパティ名 説明
アクション名 HTTP バケットへアップロード 説明
方法 POST
URI https://www.googleapis.com/upload/storage/v1/b/<バケット名>/o <バケット名>には前手順で作成したバケットの名前を指定
ヘッダー 下記のheader.jsonの内容を設定 Content-TypeはSMARTalkの場合の値
クエリ 下記のquery.jsonの内容を設定
本文 @{base64ToBinary(body('JSON_の解析_添付ファイル')?['ContentBytes'])}
header.json
{
  "Authorization": "Bearer @{body('JSON_の解析_GCSアクセストークン取得')?['access_token']}",
  "Content-Type": "audio/x-wav"
}
query.json
{
  "uploadType": "media",
  "name": "input.wav"
}

7. HTTP 音声認識 アクションの作成

  1. [新しいステップ]をクリック
  2. アクション一覧より、[HTTP]を選択
  3. プロパティを以下のように設定
プロパティ名 説明
アクション名 HTTP 音声認識
方法 POST
URI https://speech.googleapis.com/v1/speech:recognize
ヘッダー 下記のheader.jsonの内容を設定
本文 下記のbody.jsonの内容を設定 encodingsampleRateHertzはSMARTalkの場合の値。<バケット名>は前手順で作成したバケットの名前。
header.json
{
  "Authorization": "Bearer @{body('JSON_の解析_GCSアクセストークン取得')?['access_token']}",
  "Content-Type": "application/json"
}
body.json
{
  "config": {
    "encoding": "LINEAR16",
    "sampleRateHertz": 8000,
    "languageCode": "ja-JP"
  },
  "audio": {
    "uri": "gs://<バケット名>/input.wav"
  }
}

ここまで作成すれば、このフローで留守電ファイルが音声認識された結果の取得までは行うことができる。

フロー作成(音声認識結果をメール転送)

自分の場合は、上記手順の処理までで取得した音声認識結果を、さらに最初に受信した留守電メールに記載して別のアドレスに転送する設定を行った。その手順を記載する。

前手順で作成したフローの続きからアクションを作成していく。

1. JSON の解析 results アクションの作成

  1. [新しいステップ]をクリック
  2. アクション一覧より、[JSON の解析]を選択
  3. プロパティを以下のように設定
プロパティ名
アクション名 JSON の解析 results
コンテンツ @{first(body('JSON_の解析_音声認識')?['results'])}
スキーマ 下記のschema.jsonの内容を設定
schema.json
{
    "type": "object",
    "properties": {
        "alternatives": {}
    }
}

2. JSON の解析 alternatives アクションの作成

  1. [新しいステップ]をクリック
  2. アクション一覧より、[JSON の解析]を選択
  3. プロパティを以下のように設定
プロパティ名
アクション名 JSON の解析 alternatives
コンテンツ @{first(body('JSON_の解析_results')?['alternatives'])}
スキーマ 下記のschema.jsonの内容を設定
schema.json
{
    "type": "object",
    "properties": {
        "transcript": {},
        "confidence": {}
    }
}

3. メールの転送 (V2) アクションの作成

  1. [新しいステップ]をクリック
  2. アクション一覧より、[メールの転送 (V2)]を選択
  3. プロパティを以下のように設定
プロパティ名 説明
アクション名 メールの転送 (V2)
メッセージID @{triggerBody()?['Id']}
宛先 <宛先アドレス> 任意の宛先アドレス
コメント 下記のcomment.htmlの内容を設定
comment.html
transcript : @{body('JSON_の解析_alternatives')?['transcript']}<br>
confidence : @{body('JSON_の解析_alternatives')?['confidence']}

作成したフローの全体像はこんな感じ。

動作確認

Office 365で以下のようなメールを受信すると、

別のメールサービスに以下のようなメールが転送されてきた。句読点がない以外はほぼ完璧な文字起こしがされていてびっくり。電話番号はハイフンまで付けてくれている。

おわりに

Google Cloud Speechの採用理由

今回はフローのみによる単純な構成にしたかったので、日本語音声の音声認識機能をRESTful APIで使えるサービスを各社クラウドから下記の通り比較した。

  • Microsoft → 日本語対応、RESTful APIの場合は最大10秒
  • Google Cloud  → 日本語対応、RESTful APIの場合は最大1分
  • AWS → 日本語未対応

留守電音声は10秒以上ある場合がほとんどのため、結果としてGoogle の Google Cloud Speechを採用することとなった。

課題

1分以上の音声ファイルを受信したときの例外処理を考慮してなかったのでそのうち。

その他

Office 365ではすでにこんな機能がリリースされた?らしい。そのうち今回のような作り込みも不要になるかも。
https://pc.watch.impress.co.jp/docs/news/1140448.html

以上