

翻訳は機械翻訳により提供されています。提供された翻訳内容と英語版の間で齟齬、不一致または矛盾がある場合、英語版が優先します。

# Amazon Chime SDK の通知について
<a name="va-notification-targets"></a>

音声分析では、スピーカー検索または音声トーン分析のタスクの開始時、実行中、および終了時に、自動的にターゲットにイベントが送信されます。通知ターゲットを使用してこれらのイベントを受信します。ワークフローやアプリケーションに高可用性が必要な場合は、複数の通知ターゲットを使用することをお勧めします。

また、通知ターゲットへのアクセスに必要なポリシーには IAM ロールを使用する必要があります。詳細については、「[Amazon Chime SDK で通話分析のリソースアクセスロールを使用する](call-analytics-resource-access-role.md)」を参照してください。

**注記**  
Amazon SQS と Amazon SNS では、先入れ先出しキューはサポートされていません。そのため、メッセージが順不同で届く可能性があります。タイムスタンプを確認して必要に応じてメッセージを順序付け、メッセージを Amazon DynamoDB などのデータストアに保持することをお勧めします。「[Amazon Chime SDK のタスク結果のポーリング](va-task-result-poll.md)」で説明されている Get API を使用して最新の結果を取得することもできます。

次の表に、イベントとそれに対応する詳細タイプを示します。


| 通知イベント | Detail-type | 
| --- | --- | 
| 音声分析メタデータ | `VoiceAnalyticsStatus` | 
| 発話者検索 | `SpeakerSearchStatus` | 
| 音声トーン分析 | `VoiceToneAnalysisStatus` | 

# Amazon Chime SDK の通知ターゲットの IAM ポリシーについて
<a name="va-iam-target-policies"></a>

Amazon SQS、Amazon SNS、AWS Lambda、または Amazon KDS の通知ターゲットへのアクセスを許可する、通話分析設定の IAM ロールのポリシーを使用する必要があります。詳細については、このガイドの「[Amazon Chime SDK で通話分析のリソースアクセスロールを使用する](call-analytics-resource-access-role.md)」を参照してください。

## スピーカー検索イベント
<a name="va-speaker-search-events"></a>

スピーカー検索イベントの詳細タイプは `SpeakerSearchStatus` です。

Amazon Chime SDK Voice Connector は、以下のスピーカー検索イベントを送信します。
+ ID の一致
+ 音声埋め込みの生成

イベントには以下のステータスがあります。
+ `IdentificationSuccessful` - 特定の音声プロファイルドメイン内で、高い信頼度スコアで一致する音声プロファイル ID を少なくとも 1 つ正常に識別しました。
+ `IdentificationFailure` - 識別を実行できませんでした。原因: 発信者が 10 秒以上話していないか、音質が良くありません。
+ `IdentificationNoMatchesFound` - 指定された音声プロファイルドメインで、高い確率で一致する音声プロファイルが見つかりませんでした。発信者が新規であるか、声が変わっている可能性があります。
+ `VoiceprintGenerationSuccessful` - システムは、20 秒間の無音ではない音声を使用して音声埋め込みを生成しました。
+ `VoiceprintGenerationFailure` - システムは音声埋め込みを生成できませんでした。原因: 発信者が 20 秒以上話していないか、音質が良くありません。

### ID の一致
<a name="va-id-matches"></a>

[https://docs.aws.amazon.com/chime-sdk/latest/APIReference/API_voice-chime_StartSpeakerSearchTask](https://docs.aws.amazon.com/chime-sdk/latest/APIReference/API_voice-chime_StartSpeakerSearchTask) API が特定の `transactionId` に対して呼び出されると、Voice Connector サービスは、無音でない音声が 10 秒間聞こえた後、ID が一致したことを示す通知を返します。このサービスは、上位 10 件の一致を、音声プロファイル ID と [0, 1] の範囲の信頼スコアと共に返します。信頼度スコアが高いほど、通話中のスピーカーが音声プロファイル ID と一致する可能性が高くなります。機械学習モデルで一致が見つからなかった場合、通知の `detailStatus` フィールドには `IdentificationNoMatchesFound` が含まれます。

次の例は、一致が見つかった場合の通知を示しています。

```
{    
    "version": "0",
    "id": "12345678-1234-1234-1234-111122223333",
    "detail-type": "SpeakerSearchStatus",
    "service-type": "VoiceAnalytics",
    "source": "aws.chime",
    "account": "111122223333",
    "time": "yyyy-mm-ddThh:mm:ssZ",
    "region": "us-east-1",
    "resources": [],
    "detail": {
        "taskId": "uuid",
        "detailStatus": "IdentificationSuccessful",
        "speakerSearchDetails" : {
            "results": [
                {
                    "voiceProfileId": "vp-505e0992-82da-49eb-9d4a-4b34772b96b6",
                    "confidenceScore": "0.94567856",
                },
                {
                    "voiceProfileId": "vp-fba9cbfa-4b8d-4f10-9e41-9dfdd66545ab",
                    "confidenceScore": "0.82783350",
                },
                {
                    "voiceProfileId": "vp-746995fd-16dc-45b9-8965-89569d1cf787",
                    "confidenceScore": "0.77136436",
                }
            ]
        },
        "mediaInsightsPipelineId": "87654321-33ca-4dc6-9cdf-abcde6612345",
        "sourceArn": "arn:aws:chime:us-east-1:111122223333:media-pipeline/87654321-33ca-4dc6-9cdf-abcde6612345",
        "streamArn": "arn:aws:kinesisvideo:us-east-1:111122223333:stream/my-stream/0123456789012",
        "channelId": 0
    }
}
```

### 音声埋め込みの生成
<a name="va-voice-print-generation"></a>

無音でない音声がさらに 10 秒間続くと、Voice Connector は通知ターゲットに音声埋め込み生成通知を送信します。音声プロファイルに新しい音声埋め込みを登録したり、音声プロファイルに既に登録されている声紋を更新したりできます。

次の例は、一致が見つかった場合の通知を示しています。この場合、関連する音声プロファイルを更新できます。

```
{
    "version": "0",
    "id": "12345678-1234-1234-1234-111122223333",
    "detail-type": "SpeakerSearchStatus",
    "service-type": "VoiceAnalytics",
    "source": "aws.chime",
    "account": "111122223333",
    "time": "yyyy-mm-ddThh:mm:ssZ",
    "region": "us-east-1",
    "resources": [],
    "detail": {
        "taskId": "guid",
        "detailStatus": "VoiceprintGenerationSuccess",
        "mediaInsightsPipelineId": "87654321-33ca-4dc6-9cdf-abcde6612345",
        "sourceArn": "arn:aws:chime:us-east-1:111122223333:media-pipeline/87654321-33ca-4dc6-9cdf-abcde6612345",
        "streamArn": "arn:aws:kinesisvideo:us-east-1:111122223333:stream/my-stream/0123456789012",
        "channelId": 0
    }
}
```

## 音声トーン分析イベント
<a name="va-tone-status"></a>

音声トーン分析イベントの詳細タイプは `VoiceToneAnalysisStatus` です。分析では次のステータスが返されます。
+ `VoiceToneAnalysisSuccessful` — 発信者とエージェントの声を分析し、感情 (肯定的、否定的、または中立的) を予測できました。
+ `VoiceToneAnalysisFailure` -トーン分析を実行できませんでした。これは、発信者が 10 秒間話さずに電話を切ったり、音質が悪くなりすぎたりした場合に発生する可能性があります。
+ `VoiceToneAnalysisCompleted` - ユーザーとエージェントの声を分析して、通話全体の感情を予測できました。これは音声トーン分析が終了したときに送信される最後のイベントです。

次の例は、典型的な音声トーン分析イベントを示しています。

```
{
  "detail-type": "VoiceToneAnalysisStatus",
  "service-type": "VoiceAnalytics",
  "source": "aws.chime",
  "account": "216539279014",
  "time": "2022-08-26T17:55:15.563441Z",
  "region": "us-east-1",
  "detail": {
    "taskId": "uuid",
    "detailStatus": "VoiceToneAnalysisSuccessful",
    "voiceToneAnalysisDetails": {
      "currentAverageVoiceTone": {
          "startTime": "2022-08-26T17:55:15.563Z",
          "endTime": "2022-08-26T17:55:45.720Z",
          "voiceToneLabel": "neutral",
          "voiceToneScore": {    
            "neutral": "0.83",    
            "positive": "0.13",    
            "negative": "0.04"
          }
      },
      "overallAverageVoiceTone": {
          "startTime": "2022-08-26T16:23:13.344Z",
          "endTime": "2022-08-26T17:55:45.720Z",
          "voiceToneLabel": "positive",
          "voiceToneScore": {    
            "neutral": "0.25",    
            "positive": "0.65",    
            "negative": "0.1"
          }
      }
    },
        "startFragmentNumber": "01234567890123456789",
        "mediaInsightsPipelineId": "87654321-33ca-4dc6-9cdf-abcde6612345",
        "sourceArn": "arn:aws:chime:us-east-1:111122223333:media-pipeline/87654321-33ca-4dc6-9cdf-abcde6612345",
        "streamArn": "arn:aws:kinesisvideo:us-east-1:111122223333:stream/my-stream/0123456789012",
        "channelId": 0
  },
  "version": "0",
  "id": "Id-f928dfe3-f44b-4965-8a17-612f9fb92d59"
}
```

## 通話後のサマリーイベント
<a name="va-post-call-summary-events"></a>

通話後のサマリーイベントは、通話が終了した 5 分後に送信されます。これらのサマリーには、通話中に発生したスピーカー検索タスクの概要が記載されています。

次の例は、通話後のサマリーを示しています。これには、最も一致した音声プロファイル、確認済みのスピーカー ID、通話中に行われた `CreateVoiceProfile` および `UpdateVoiceProfile` API コールを通じて作成または更新された音声プロファイルのリストが含まれます。

```
{
    "version": "0",
    "id": "12345678-1234-1234-1234-111122223333",
    "detail-type": "VoiceAnalyticsStatus",
    "service-type": "VoiceAnalytics",
    "source": "aws.chime",
    "account": "111122223333",
    "time": "yyyy-mm-ddThh:mm:ssZ",    
    "region": "us-east-1",
    "resources": [],
    "detail": {
        "detailStatus": "PostCallVoiceAnalytics",
        "callId": "22e8dee8-bbd7-4f94-927b-2d0ebaeddc1c",
        "transactionId": "daaeb6bf-2fe2-4e51-984e-d0fbf2f09436",
        "voiceConnectorId": "abcdef1ghij2klmno3pqr4",
        "isCaller": true | false,
        "speakerSearchResults": {
            "bestMatchedVoiceProfileId": "vp-04c25ba1-a059-4fd3-8495-4ac91b55e2bf",
            "customerValidatedCallerIdentity": "vp-04c25ba1-a059-4fd3-8495-4ac91b55e2bf",
            "createVoiceProfileTransactions": [
                {
                    "voiceProfileId": "vp-04c25ba1-a059-4fd3-8495-4ac91b55e2bf",
                    "requestTimestamp": "2022-12-14T18:38:38.796Z"
                },
                {
                    "voiceProfileId": "vp-04c25ba1-a059-4fd3-8495-4ac91b55e2bf",
                    "requestTimestamp": "2022-12-14T18:38:38.796Z",
                }
            ],
            "updateVoiceProfileTransactions": [
                {
                    "voiceProfileId": "vp-04c25ba1-a059-4fd3-8495-4ac91b55e2bf",
                    "requestTimestamp": "2022-12-14T18:38:38.796Z",
                },
                {
                    "voiceProfileId": "vp-04c25ba1-a059-4fd3-8495-4ac91b55e2bf",
                    "requestTimestamp": "2022-12-14T18:38:38.796Z",
                }
            ]
        }
    }
}
```

# Amazon Chime SDK の音声分析の Lambda 関数の例
<a name="va-sample-lambda"></a>

次の例の Python コードは、Voice Connector から受信した通知を処理します。 AWS Lambda 関数にコードを追加できます。また、これを使用して Amazon SQS キュー、Amazon SNS トピック、または Amazon Kinesis Data Streams をトリガーすることもできます。その後、通知を `EventTable` に保存して今後の処理に備えることができます。正確な通知形式については、「[Amazon Chime SDK の通知について](va-notification-targets.md)」を参照してください。

```
import base64
import boto3
import json
import logging
import time

from datetime import datetime
from enum import Enum

log = logging.getLogger()
log.setLevel(logging.INFO)

dynamo = boto3.client("dynamodb")

EVENT_TABLE_NAME = "EventTable"

class EventType(Enum):
    """
    This example code uses a single Lambda processor to handle either
    triggers from SQS, SNS, Lambda, or Kinesis. You can adapt it to fit your
    desired infrastructure depending on what you prefer. To distinguish
    where we get events from, we use an EventType enum as an
    example to show the different ways of parsing the notifications.
    """
    SQS = "SQS"
    SNS = "SNS"
    LAMBDA = "LAMBDA"
    KINESIS = "KINESIS"


class AnalyticsType(Enum):
    """
    Define the various analytics event types that this Lambda will
    handle.
    """
    SPEAKER_SEARCH = "SpeakerSearch"
    VOICE_TONE_ANALYSIS = "VoiceToneAnalysis"
    ANALYTICS_READY = "AnalyticsReady"
    UNKNOWN = "UNKNOWN"
 
   
class DetailType(Enum):
    """
    Define the  various detail types that Voice Connector's voice
    analytics feature can return.
    """
    SPEAKER_SEARCH_TYPE = "SpeakerSearchStatus"
    VOICE_TONE_ANALYSIS_TYPE = "VoiceToneAnalysisStatus"
    ANALYTICS_READY = "VoiceAnalyticsStatus"
 

def handle(event, context):
    """
    Example of how to handle incoming Voice Analytics notification messages
    from Voice Connector.
    """
    logging.info(f"Received event of type {type(event)} with payload {event}")
    is_lambda = True
    
    # Handle triggers from SQS, SNS, and KDS. Use the below code if you would like
    # to use this Lambda as a trigger for an existing SQS queue, SNS topic or Kinesis
    # stream.
    if "Records" in event:
        logging.info("Handling event from SQS or SNS since Records exists")
        is_lambda = False
        for record in event.get("Records", []):
            _process_record(record)
    
    # If you would prefer to have your Lambda invoked directly, use the
    # below code to have the Voice Connector directly invoke your Lambda.
    # In this scenario, there are no "Records" passed.
    if is_lambda:
        logging.info(f"Handling event from Lambda")
        event_type = EventType.LAMBDA
        _process_notification_event(event_type, event)


def _process_record(record):
    # SQS and Kinesis use eventSource.
    event_source = record.get("eventSource")
    
    # SNS uses EventSource.
    if not event_source:
        event_source = record.get("EventSource")

    # Assign the event type explicitly based on the event source value.
    event_type = None
    if event_source == "aws:sqs":
        event = record["body"]
        event_type = EventType.SQS
    elif event_source == "aws:sns":
        event = record["Sns"]["Message"]
        event_type = EventType.SNS
    elif event_source == "aws:kinesis":
        raw_data = record["kinesis"]["data"]
        raw_message = base64.b64decode(raw_data).decode('utf-8')
        event = json.loads(raw_message)
        event_type = EventType.KINESIS
    else:
        raise Exception(f"Event source {event_source} is not supported")

    _process_notification_event(event_type, event)


def _process_notification_event(
    event_type: EventType,
    event: dict
):
    """
    Extract the attributes from the Voice Analytics notification message
    and store it as a DynamoDB item to process later.
    """
    message_id = event.get("id")
    analytics_type = _get_analytics_type(event.get("detail-type"))
    pk = None
    if analytics_type == AnalyticsType.ANALYTICS_READY.value or analytics_type == AnalyticsType.UNKNOWN.value:
        transaction_id = event.get("detail").get("transactionId")
        pk = f"transactionId#{transaction_id}#notificationType#{event_type.value}#analyticsType#{analytics_type}"
    else:
        task_id = event.get("detail").get("taskId")
        pk = f"taskId#{task_id}#notificationType#{event_type.value}#analyticsType#{analytics_type}"
    logging.info(f"Generated PK {pk}")
    _create_request_record(pk, message_id, json.dumps(event))


def _create_request_record(pk: str, sk: str, body: str):
    """
    Record this notification message into the Dynamo db table
    """
    try:
        # Use consistent ISO8601 date format.
        # 2019-08-01T23:09:35.369156 -> 2019-08-01T23:09:35.369Z
        time_now = (
            datetime.utcnow().isoformat()[:-3] + "Z"
        )
        response = dynamo.put_item(
            Item={
                "PK": {"S": pk},
                "SK": {"S": sk},
                "body": {"S": body},
                "createdOn": {"S": time_now},
            },
            TableName=EVENT_TABLE_NAME,
        )
        logging.info(f"Added record in table {EVENT_TABLE_NAME}, response : {response}")
    except Exception as e:
        logging.error(f"Error in adding record: {e}")


def _get_analytics_type(detail_type: str):
    """
    Get analytics type based on message detail type value.
    """
    if detail_type == DetailType.SPEAKER_SEARCH_TYPE.value:
        return AnalyticsType.SPEAKER_SEARCH.value
    elif detail_type == DetailType.VOICE_TONE_ANALYSIS_TYPE.value:
        return AnalyticsType.VOICE_TONE_ANALYSIS.value
    elif detail_type == DetailType.ANALYTICS_READY.value:
        return AnalyticsType.ANALYTICS_READY.value
    else:
        return AnalyticsType.UNKNOWN.value
```

**重要**  
[https://docs.aws.amazon.com/chime-sdk/latest/APIReference/API_voice-chime_StartSpeakerSearchTask](https://docs.aws.amazon.com/chime-sdk/latest/APIReference/API_voice-chime_StartSpeakerSearchTask) または [https://docs.aws.amazon.com/chime-sdk/latest/APIReference/API_voice-chime_StartVoiceToneAnalysis.html](https://docs.aws.amazon.com/chime-sdk/latest/APIReference/API_voice-chime_StartVoiceToneAnalysis.html) API を呼び出す前に、同意を得る必要があります。同意が得られるまでは、Amazon DynamoDB などの保持エリアでイベントを保持することをお勧めします。