Twilio Conversational Intelligence でゲームのイベントのユーザーボイスを構造化してみた

Twilio Conversational Intelligence でゲームのイベントのユーザーボイスを構造化してみた

Twilio Conversational Intelligence を使って、クリスマスイベント向けのサンタさん直通ダイヤルから集まるユーザーボイスを自動で文字起こしし、ラベル付けするデモを紹介します。イベントで集まる音声フィードバックを構造化でき、分析や振り返りに活用できます。
2025.12.25

はじめに

本記事は SaaSで加速するゲーム開発 - Advent Calendar 2025 - の 25 日目のブログです。

本記事では Twilio Conversational Intelligence を使ってゲームのクリスマスイベント中におけるユーザーボイスのメタデータを取得してみた事例を紹介します。

Twilio とは

Twilio は API を通じて電話や SMS などのコミュニケーション機能をアプリケーションに組み込めるクラウドサービスです。

Twilio Conversational Intelligence とは

Twilio Conversational Intelligence は、音声通話やメッセージなどの会話データを文字起こしし、要約や感情分析、エンティティ抽出などの結果を構造化データとして返してくれるサービスです。録音ファイルをあとから人手で聞き直すのではなく、 Language Operator と呼ばれるモジュール単位で機械的に分類されたインサイトとして扱える点が特徴です。

対象読者

  • クリスマスなどのイベント施策に関わるゲーム開発の企画や運営に携わっている方
  • Twilio をゲームタイトルや周辺ツールで活用してみたいエンジニアの方
  • Conversational Intelligence のユースケースを知りたい方

参考

サンタさん直通ダイヤルの構成

サンタさん直通ダイヤルとは

企画のイメージは次のようなものです。

  • クリスマスイベント期間中に、ゲーム内のお知らせや公式 X などでサンタさん直通ダイヤルを告知する
  • プレイヤーは Twilio の電話番号に発信し、イベントの感想や要望をそのまま音声で話す

プレイヤー側から見ると、サンタさんに直接話しかけるような小さな体験です。開発側から見ると、イベント中に集まるフィードバックを音声ベースで集約し、 Conversational Intelligence によってテキスト化や要約、感情分析がされた状態で受け取る仕組みになります。

本記事では、録音の受付から Conversational Intelligence の呼び出しまでを Twilio Functions で構成し、解析結果は Webhook で自前のバックエンドへ連携する前提で説明します。

全体のデータフロー

  • Twilio Programmable Voice

    • 電話番号の取得
    • 通話フローの制御 (録音)
    • 録音ファイルと RecordingSid の取得
  • Twilio Functions

    • 録音完了イベントを受け取り、 Conversational Intelligence の Transcript 作成 API を呼び出す Function (Function A)
    • Conversational Intelligence の Webhook を受け取り、解析結果をログ出力したりバックエンドに連携したりするエンドポイント (検証では Twilio Functions で実装)
  • Twilio Conversational Intelligence

    • Intelligence Service の作成
    • Transcript API による文字起こしと会話解析
    • Language Operators (Conversation Summary、 Sentiment Analysis) によるメタデータの取得

実装と検証

全体の流れ

  1. Conversational Intelligence の Intelligence Service を作成し、 Conversation Summary と Sentiment Analysis の Language Operator を紐付ける
  2. サンタさん直通ダイヤルの通話フローを返す Twilio Function を用意し、録音を有効にする
  3. 録音完了イベントを受けて Transcript 作成 API を呼ぶ Twilio Function (Function A) を実装する
  4. Conversational Intelligence 側の Webhook を受けて OperatorResults を取得するエンドポイント (検証では Twilio Function) を実装する

Intelligence Service の作成

まずは Conversational Intelligence の基盤となる Intelligence Service を作成します。 Conversational Intelligence > Intelligence Service から Create a Service で Service を作成します。

Create CI Service

  • Unique name: test-ci など任意の識別子
  • Language: 英語

CI Service Config 1

  • Auto transcribe: 今回は録音完了時に手動で Transcript API を呼ぶためオフ
  • PII Redaction: 検証用途のためオフ

CI Service Config 2

Service を作成後、 Webhook タブで下記の設定を行います。

  • Webhook URL : 後述の /ci-webhook Function の URL
  • Webhook HTTP method : POST

webhook setting

Language Operators タブで、 Conversation Summary, Sentiment Analysis を追加します。

add services

add to service button

追加されると Added to Service と表示されます。

Added to Service

サンタさん直通ダイヤル用 TwiML を返す Function

次に、プレイヤーからの着信に対して録音を行う Twilio Function を用意します。

Twilio Functions の管理画面から新しい Function を作成します。

下記のように環境変数を設定します。

変数名
RECORDING_STATUS_URL 後述の /ci-create-transcript Function の公開 URL
INTELLIGENCE_SERVICE_SID Intelligence Service の SID

次に、受電時に呼び出すコードを配置します。

/incoming-call
exports.handler = function (context, event, callback) {
  const twiml = new Twilio.twiml.VoiceResponse();

  // 録音完了後にもう一度呼ばれると RecordingSid が付与される
  if (event.RecordingSid) {
    // 2 回目以降の呼び出しでは、お礼だけ伝えて通話を切る
    twiml.say(
      {
        language: "ja-JP",
        voice: "woman",
      },
      "ありがとうございました。メリークリスマス。"
    );
    twiml.hangup();
  } else {
    // 1 回目の呼び出しでは、ガイダンスを流して録音を開始する
    twiml.say(
      {
        language: "ja-JP",
        voice: "woman",
      },
      "メリークリスマス。サンタさんへのご意見、ご感想をどうぞ。ピーという音のあとに話してください。"
    );

    twiml.record({
      recordingStatusCallback: context.RECORDING_STATUS_URL,
      recordingStatusCallbackEvent: ["completed"],
      recordingChannels: "dual",
      timeout: 5,
      maxLength: 120,
      playBeep: true,
    });
  }

  return callback(null, twiml);
};

Function を作成後、Twilio 購入番号の Voice Configuration からこの Function を A calls comes in として登録します。

voice config

録音完了 Function で Transcript を作成する

Twilio Functions に次のような Function を追加します。

/ci-create-transcript
exports.handler = async function (context, event, callback) {
  const client = context.getTwilioClient();

  const recordingSid = event.RecordingSid;
  const callSid = event.CallSid;

  console.log("RecordingSid:", recordingSid, "CallSid:", callSid);

  if (!recordingSid) {
    console.error("RecordingSid is missing");
    return callback(null, {});
  }

  try {
    const transcript = await client.intelligence.v2.transcripts.create({
      serviceSid: context.INTELLIGENCE_SERVICE_SID,
      customerKey: callSid || recordingSid,
      channel: {
        media_properties: {
          // Twilio Recording を Conversational Intelligence に渡す
          source_sid: recordingSid,
        },
      },
    });

    console.log("Queued transcript:", transcript.sid, "status:", transcript.status);
    return callback(null, {});
  } catch (err) {
    console.error("Failed to create transcript", err);
    return callback(err);
  }
};

ここでは、次のような方針にしています。

  • serviceSid にあらかじめ作成しておいた Intelligence Service の SID を指定する
  • channel.media_properties.source_sid として、 Twilio の RecordingSid を渡す
  • customerKey に CallSid などを入れておくことで、あとから自分のシステム内で関連付けしやすくする

Transcript 作成 API を呼び出したあとは、即座に解析結果が返ってくるわけではありません。 Conversational Intelligence 側で文字起こしと解析が非同期で実行され、完了したタイミングで Intelligence Service に設定した Webhook URL にイベントが通知されます。

Intelligence Webhook で解析結果を受け取る

Transcript が完成すると、 Conversational Intelligence から Transcript SID やイベント種別が Webhook で送信されます。この通知を受けて、 Summary や Sentiment を取得するのが Webhook エンドポイントの役割です。

/ci-webhook
exports.handler = async function (context, event, callback) {
  const client = context.getTwilioClient();

  const transcriptSid = event.transcript_sid;
  const eventType = event.event_type;
  const customerKey = event.customer_key;

  console.log("CI webhook:", eventType, "TranscriptSid:", transcriptSid, "CustomerKey:", customerKey);

  // Conversational Intelligence の Webhook は voice_intelligence_transcript_available が送られてくる
  if (eventType !== "voice_intelligence_transcript_available") {
    return callback(null, {});
  }

  try {
    // OperatorResults を一括取得
    const operatorResults = await client.intelligence.v2
      .transcripts(transcriptSid)
      .operatorResults.list({ limit: 20 });

    // Conversation Summary の結果を取得
    const summaryResult = operatorResults.find(
      (r) => r.name === "Conversation Summary"
    );
    const summaryText = summaryResult?.textGenerationResults?.result;

    // Sentiment Analysis の結果を取得
    const sentimentResult = operatorResults.find(
      (r) => r.name === "Sentiment Analysis"
    );

    const predictedLabel = sentimentResult?.predictedLabel;
    const labelProbabilities = sentimentResult?.labelProbabilities;

    console.log("Summary:", summaryText);
    console.log("Sentiment predictedLabel:", predictedLabel);
    console.log("Sentiment labelProbabilities:", labelProbabilities);

    // 実運用ではここで summaryText、predictedLabel などを自前の DB に保存する

    return callback(null, {});
  } catch (err) {
    console.error("Failed to fetch transcript or operator results:", err);
    return callback(err);
  }
};

動作確認

  1. ログが確認できるよう、 Twilio Function の Live logs on を有効にしました。

Live logs on

  1. Twilio 電話番号宛てに電話し、下記の内容で話しかけました。
I enjoyed the event very much, thank you!
  1. Live logs に下記のようなログが出力されるのを確認しました。
Dec 13, 2025, 02:22:49 PM
Execution started...
Dec 13, 2025, 02:22:49 PM
CI webhook: voice_intelligence_transcript_available TranscriptSid: GT**** CustomerKey: CA****
Dec 13, 2025, 02:22:49 PM
Summary: The customer expressed their appreciation for the event, indicating that they found it enjoyable. The agent acknowledged this sentiment with gratitude. Overall, the interaction was positive and focused on the customer's satisfaction with the event.
Dec 13, 2025, 02:22:49 PM
Sentiment predictedLabel: neutral
Dec 13, 2025, 02:22:49 PM
Sentiment labelProbabilities: { neutral: 1 }
Dec 13, 2025, 02:22:49 PM
Execution ended in 223.29ms using 107MB

考察

生の声をあとから眺めるハードルが下がる

音声ベースのフィードバックは、どうしてもあとから聞き直すのが負担になりがちです。録音ファイルを一覧表示しても、ファイル名や長さだけを見てもどこから手を付けてよいか分からないことが多くあります。

Conversational Intelligence を挟むことで、 Summary をざっと眺めるだけで内容の傾向を掴みやすくなります。さらに Sentiment のようなラベルが付いていると、どこから確認すべきかの優先順位付けもしやすくなります。

企画や運営と同じフォーマットで会話しやすくなる

開発チームだけでなく、企画や運営、 CS などの職種が横断的に関わる場合でも、同じデータを見ながら会話しやすくなります。たとえば次のような議論がしやすくなります。

  • バランス調整に関するフィードバックがどの程度寄せられているか
  • クリスマスシナリオに対する感想が、全体としてどの程度ポジティブか
  • ガチャに対する不満がどの程度あるか

このような問いに対して、生の録音ファイルだけでは整理が難しい一方、 Summary、 Sentiment といったシンプルなメタデータがあれば共通の前提を持って議論できます。 Conversational Intelligence 側で一段階整形されたデータを受け取れることは、そのままコミュニケーションコストの削減につながると感じました。

クリスマス限定施策として外付けしやすい

今回のサンタさん直通ダイヤルは、ゲームクライアント側への変更を最小限に抑えた構成にしました。基本的には告知とキャンペーン ID の管理に留め、音声の受付と解析は Twilio 側で完結させています。

SaaS を活用して機能を外付けしておくことで、ゲーム本体に大きな改修を入れずに試行錯誤できる余地が増えると感じました。

まとめ

本記事では、電話の向こうのサンタさんを入り口に、 Twilio Conversational Intelligence を使ってクリスマスイベント中のユーザーボイスのメタデータを取得してみた事例を紹介しました。プレイヤーにとってはサンタさんにひとこと伝えられる小さな企画ですが、開発側から見ると音声フィードバックを文字起こしとサマリ、感情ラベルといった形で整理してくれる裏方の仕組みとして機能します。

会話データの解析というと大がかりな基盤を想像しがちですが、 Twilio のような SaaS を活用すると、イベント向けの小さな試みから始めてみるアプローチを取りやすくなります。録音ファイルを扱う部分やプライバシー保護など、実運用にあたって検討すべき点は多くありますが、ライトなクリスマス施策の一環として Conversational Intelligence を試してみるきっかけになれば幸いです。

今後は、通話だけでなくメッセージングやチャットの履歴にも同様の解析を適用したり、 AI エージェントとのやり取りをあわせて分析したりといった方向にも広げていけそうです。そうした応用例についても、別の機会に検証してみたいと考えています。

この記事をシェアする

FacebookHatena blogX

関連記事