金曜日, 7月 18, 2025
金曜日, 7月 18, 2025
- Advertisment -
ホームニューステックニュースAppSync Event API を使用したリアルタイム文字起こしをブラウザに表示させてみた! #lambda

AppSync Event API を使用したリアルタイム文字起こしをブラウザに表示させてみた! #lambda



AppSync Event API を使用したリアルタイム文字起こしをブラウザに表示させてみた! #lambda

こんにちは。株式会社ウフルの廣田です。

この記事は「2025 Japan AWS Jr. Champions 夏のQiitaリレー」の14日目です。

過去の投稿(リンク集)はこちらからご覧ください!

  • AWS AppSyncとは
    サーバーレスで高性能なGraphQLおよびPub/Sub APIsを使用して、アプリケーションとサービスをイベントに接続できるサービスです。[1]
    元々はGraphQLのイメージが強かったですが、2024年10月にAppSync Event APIがリリースされました。
    こちらはあらゆる規模のリアルタイムウェブ体験およびモバイル体験を強化する、安全で高性能なサーバーレス WebSocket API を構築するためのソリューションを提供しているようです。[2]
  • 課題、願望
    Amazon Connect の文字起こしをリアルタイムで画面に表示させたら便利だよな〜と思っていました!
  • 今回やってみること!
    「AppSync Event API のWebSocket APIを使用して、Amazon Connect Contact Lensによってリアルタイムに文字起こしされた情報をブラウザに表示する」ことを実装してみました!

ブラウザに表示することができるということは、他のSaaSなどに文字起こし内容をリアルタイムで表示することが可能になると考えています。

この記事の内容が誰かの助けになれば幸いです。

リアルタイム文字起こしAppSync使用.png
今回はAmazon Connect 内のストリーミング情報をKinesisで受け取り、LambdaにEvent情報として渡します。
Lambda側ではブラウザ側で通話者間のやりとりがわかりやすいように整形して、AWS AppSyncへ渡し、そのままブラウザに表示する流れです。

  • マネージメントコンソール > AWS AppSync > 「Event API を作成」をクリック
  • 任意のAPI名を記載し、「作成」をクリック
    スクリーンショット 2025-07-16 15.15.25.png
  • 設定 > DNSエンドポイントのそれぞれを取得
    • HTTP
    • リアルタイム
    • API キー
      image.png
      image.png
"""
Kinesis(Contact Lens Streams) → Lambda → AppSync Event API へ API キー認証でイベントを Publish する関数
環境変数
  HTTP_ENDPOINT = ".appsync-api..amazonaws.com"
  API_KEY       = "da2-xxxxxxxxxxxxxxxxxxxx"     # AWS AppSync で発行したキー
  CHANNEL       = "/default/message"             # チャンネル名
"""
import botocore.awsrequest, botocore.httpsession, json, os, base64

HTTP_ENDPOINT = os.environ["HTTP_ENDPOINT"].rstrip("/")
API_KEY       = os.environ["API_KEY"]
CHANNEL       = os.environ["CHANNEL"]

session = botocore.httpsession.URLLib3Session()

def lambda_handler(event, context):
    try:
      print(f"Received event: {event}")
      segments = []
      for record in event.get("Records", []):
        payload = record["kinesis"]["data"]
        decoded = base64.b64decode(payload)
        data = json.loads(decoded)
        print(f"Decoded data: {data}")
        if "Segments" in data:
          segments.extend(data["Segments"])
        else:
          print("No Segments found in the record.")
      transcript = correct_transcript(segments)

      events = [
          json.dumps({"role": t["role"], "content": t["content"]})
          for t in transcript
      ]
      print(f"AppSync Post Event: ", events)

      body = _http_post({"channel": CHANNEL, "events": events})
      return {"statusCode": 200, "body": body}
    except Exception as e:
      print(f"Error processing event: {e}")
      return {"statusCode": 500, "body": str(e)}

def correct_transcript(segments: list):
    corrected_segments = []
    role_mapping = {
        "AGENT": "エージェント",
        "CUSTOMER": "顧客",
    }
    for s in segments:
        if "Transcript" in s:
            transcript = s["Transcript"]
            content = transcript.get("Content", "")
            participant_role = transcript.get("ParticipantRole", "")
            role = role_mapping.get(participant_role)
            begin_offset = transcript.get("BeginOffsetMillis", 0)
            if role and content:
                corrected_segments.append({
                    "role": role,
                    "content": content,
                    "beginOffsetMillis": begin_offset
                })
    corrected_segments.sort(key=lambda x: x["beginOffsetMillis"])
    return corrected_segments

def _http_post(payload: dict) -> str:
    req = botocore.awsrequest.AWSRequest(
        method="POST",
        url=f"https://{HTTP_ENDPOINT}/event",
        data=json.dumps(payload).encode(),
        headers={
            "content-type": "application/json",
            "x-api-key": API_KEY
        }
    )
    resp = session.send(req.prepare())
    if resp.status_code >= 400:
        raise RuntimeError(f"Publish failed: {resp.status_code} {resp.text[:200]}")
    return resp.text or "OK"

 lang="ja">
  
    

リアルタイムの文字起こし



Source link

Views: 0

RELATED ARTICLES

返事を書く

あなたのコメントを入力してください。
ここにあなたの名前を入力してください

- Advertisment -