Amazon ConnectとKinesis Video Streamで通話を録音時、Lex を利用し発話終了のタイミングで録音を自動停止(無人対応)

2023.11.10

はじめに

Amazon Connectの無人対応で、Kinesis Video Stream(KVS)で通話を録音時、プッシュボタンでなく発話終了のタイミングで録音を停止させる方法をまとめました。

Amazon Connectの無人対応において、通話をKVSで録音する場合、ユーザーが話した後、プッシュボタンを押すことで録音を終了する方法があります。

この方法のコンタクトフローは、以下の通りです。

  1. ユーザーが発話する
  2. ユーザーが発話を終了した後、プッシュボタンを押して録音を終了する

以下の記事では、この方法を使用して、顧客の一次対応を無人で行っています。

ただし、ユーザーがプッシュボタンを押すのはユーザーにとって負担がかかります。今回は、ユーザーが発話を終了させたら、自動で録音を終了する方法が見つけたので、その手順をまとめます。

ちなみに、プッシュボタンではなく、時間経過で録音を終了させる方法もありますが、今回の場合は、ユーザー体験が悪くなるため、採用しません。

実現方法

以下の要件を満たす方法で実現します。

  • 顧客の発話を無人で聞き取る
  • 顧客が発話を終了したら録音を停止する
  • 音声の文字起こしにはWhisper APIを利用する
    • Amazon Lexは音声の文字起こしにAmazon Transcribeを使用するため、KVSで音声を録音し、Whisper APIで文字起こしを行う

上記の要件に基づいた実現方法として、以下のフローで「顧客の入力を取得する」ブロックでLexを利用します。

ConnectフローからLexを呼び出すと、顧客が何秒間発話しなかったら、顧客の会話が終了したと判断する機能があります。

Lexを利用するブロックでは、文字起こしした内容は特に使用せず、発話を終了すると「メディアストリーミングの停止」ブロックに移動させることが目的です。

ストリーミング停止の後に、KVSの録音データをLambdaで取得し、文字起こしなどを行います。

ただし、注意点として、1度の発話でLexは最大15秒までしか聞き取れないため、15秒を超えると録音が自動的に終了します。

構築

Lexボット

インテント名をOneVoiceとし、適当なサンプル発話を追加します。また、スロットを1つ作成しますが、このスロットは今回の実装では利用しません。

Lambdaがトリガーになるように、初期化と検証に Lambda 関数を使用にチェックします。

OneVoiceのサンプル発話以外もLambdaが起動できるように、FallbackIntent初期化と検証に Lambda 関数を使用をチェックします。

後の作業になりますが、後で作成するLambdaをLexから呼び出すため、Lambdaを指定し保存します。

Lambdaを呼び出す設定は、分かりにくいのですが、[エイリアス]→対象のエイリアス(TestBotAlias)→[言語:Japanese (Japan)]を順にクリックすると、呼び出す設定画面がでます。

これでビルドすると、完了です。

Lambdaの作成

Lexで利用するLambdaをランタイムPython3.11で作成します。

コードは下記の通りです。

import json
from decimal import Decimal

def decimal_to_int(obj):
    if isinstance(obj, Decimal):
        return int(obj)

def elicit_intent(intent_name):
    return {
        "sessionState": {
            "dialogAction": {
                "type": "ElicitIntent",
            },
            "intent": {
                "name": intent_name,
                "state": "Fulfilled"
            }
        },
        "messages": [
                {
                    "contentType": "PlainText",
                    "content": ","
                }
            ]
    }
def close(intent_name):
    return {
        "sessionState": {
            "dialogAction": {
                "type": "Close",
            },
            "intent": {
                "name": intent_name,
                "state": "Fulfilled"
            }
        },
        "messages": [
                {
                    "contentType": "PlainText",
                    "content": ","
                }
            ]
    }
def lambda_handler(event, context):
    print("Received event:" + json.dumps(event, default=decimal_to_int, ensure_ascii=False))

    if not event["inputTranscript"]:
        return elicit_intent("OneVoice")

    return close("OneVoice")

顧客の発話を聞き、発話を終了すると、Lexインテントを終了させる処理をしています。

Connectフロー

フローは、抜粋になりますが下記の通りです。

「顧客の入力を取得する」ブロックに、先程作成したLexを利用します。

セッション属性のキーと値は下記の通りです。

  • x-amz-lex:audio:max-length-ms:*:*(音声入力の最大時間)
    • 15秒間発話できます。15秒が上限です。
  • x-amz-lex:audio:start-timeout-ms:*:*(発話の最大待機時間)
    • 発話するまで、15秒間Lex側が待ってくれます。
  • x-amz-lex:audio:end-timeout-ms:*:*(発話終了判定の最大時間)
    • 発話してから、2.5秒間黙ると終了します。

発話終了判定の最大時間は、2.5秒にしていますが、個々で調整されるとよいと思います。

上記のセッション属性は下記で詳細に解説していますので、ご参考ください。

「メディアストリーミングの停止」ブロックの後で、Lambdaを呼び出し、KVSの録音データ取得し、録音をS3に保存したり、文字起こししたりすることが可能です。

下記の記事では、Whisper APIで文字起こしとChatGPTで要約して音声出力する方法をまとめていますので、ご参考ください。記事では、プッシュボタンで録音を停止しているので、その部分のみLexのブロックに変えるだけです。

最後に

今回は、Amazon Connectでの通話をKVSで録音する際に、プッシュ式ではなく発話終了のタイミングでストリームを終了させる方法をご紹介しました。

ただし、制限としてLexのブロックでは最大15秒までしか聞き取ることができないため、15秒を超えると録音が自動的に終了する点に注意が必要です。

本記事が参考になれば幸いです。