メインコンテンツへスキップ
Realtime Speech-to-Text (Auto) API は、生のトランスクリプトセグメントではなく、ユーザーターンを中心に文字起こしを構成します。モデル自身がユーザーターンの開始と終了を通知するため、ボイスエージェントは独自の音声活動検出を実行する代わりに、イベントに反応します。 その結果、より人間らしいボイスエージェントが実現します:
  • ポーズや電話番号を適切に処理
  • 会話のコンテキストを取り込んで精度を向上

ステートマシン

ユーザーターンの間、セッションはアイドル状態です。ユーザーが話し始めると turn.start が発火し、トランスクリプトが構築されるに従って turn.update イベントが発火します。ターンは次の 2 通りのいずれかで終了します:
  • 確信のある終了turn.end が直接発火します。ユーザーターンは完了です。
  • 早期終了 (eager end) — まず turn.eager_end が発火し、ユーザーが_もしかしたら_終わったかもしれないことを示します。その後、turn.end がユーザーターンの完了を確定するか、turn.resume が発火してユーザーターンが続行されます。

イベント

API は会話の状態を表すために以下のイベントを発行します。 transcript プロパティはターン内で累積的です。デルタではなく、このユーザーターンでこれまでに文字起こしされた完全なテキストが含まれます。イベント間で部分結果を連結する必要はありません。 発行されるすべてのテキストは確定 (final) です。モデルは既に送信したテキストを修正しません。turn.update の部分トランスクリプトを、変更を心配せずに到着した瞬間から利用できます。 WebSocket が確立されると、別個の connected イベントが 1 回発火します。音声を送信する前にそれを待つ必要はありません。

レイテンシー削減のための turn.eager_end の利用 [PREVIEW]

turn.eager_end を使うと、ユーザーが話し終えたとモデルが確信する前にエージェントが応答生成を開始できます。発火した瞬間にトランスクリプトを LLM に送信すると、turn.end が到着した瞬間に再生できる応答が準備できています。 これは最適化機能であり、ユースケースによっては必須ではありません。開発初期は turn.startturn.end イベントに集中し、エージェントが成熟してから他のイベントの取り込みを検討することを推奨します。 turn.eager_end の後には 2 つのことが起こり得ます:
  • turn.resume: ユーザーが話し続けている。進行中の LLM と TTS の生成をキャンセルし、ターン終了を待ちます。
  • turn.end: ユーザーは本当に終わっている。準備した応答を再生します。
turn.eager_endturn.resume の動作を引き続き調整しているため、これはプレビュー機能です。

例: 1 ターン

ユーザーが「Hi I need to cancel my subscription please.」と発話します。
このストリームを聞いているエージェントは次のように動作します:
  1. 最初の turn.eager_end で応答準備を開始する。
  2. turn.resume でそれをキャンセルする。
  3. 2 回目の turn.eager_end で再び準備を開始する。
  4. turn.end で準備した応答を再生する。

保証

  • 各ターンの最初のイベントは turn.start です。
  • turn.eager_end の後には turn.end または turn.resume が続きます。
  • turn.resume は直前の turn.eager_end のあとにのみ発火します。
  • turn.eager_end のトランスクリプトが完全でない場合は、必ず turn.resume が発火します。
  • turn.end は常にターンを閉じ、次のターンは新しい turn.start で始まります。
  • イベントは、それ以前のテキストを変更することなく、ターンのトランスクリプトに追加します。

エッジケース

音声なし vs 無音

Cartesia の API は連続した音声ストリームを想定しています。 音声の送信を停止すると、サーバーはユーザーが無音であると見なすのではなく、追加の音声チャンクが到着するのを待ちます。 これは通常、ネットワークの遅延に対応するために望ましい挙動ですが、クライアントが音声入力をミュートしている間、無音 (すべてゼロ) を送信し続ける必要があることも意味します。

イベントのドレイン

セッションの音声をすべて送信し終えたら、{"type": "close"} を送信して、バッファリングされている音声をフラッシュし、残りのイベントを発行するようモデルに伝えます。モデルが完了すると、サーバーがソケットをクローズします。 サーバーは文字起こしの精度を高めるために音声を一定量バッファします。close コマンドを送信しなかったり、メッセージの読み取りを早期に停止したりすると、バッファされた音声は処理されません。最後の 1 秒の音声を気にしないのであれば、これは問題ありません。

トランスクリプトの結合

transcript フィールドは ターン内で累積的 です。各 turn.updateturn.eager_endturn.end イベントには、これまでのターンの全文がすでに含まれています。 最終的なトランスクリプトだけが必要な場合は、完了したターンごとに 1 つずつ、各 turn.end から transcript プロパティを取得してください。transcript はそのまま連結してください。strip() で空白を取り除いたり、正規化したり、独自の区切り文字を追加してはいけません。
turn.updateturn.eager_end イベントのトランスクリプトを連結するのは、テキストの重複の典型的な原因です。各更新は累積的なので、それらを連結するとトランスクリプトの一部が繰り返されます。 turn.updateturn.eager_end は、トランスクリプトのチャンクではなく、ターン状態の更新として扱ってください。 最終トランスクリプトは turn.end のみから読み取ってください。

次に進む

オンラインで試す

サインアップやコード不要でターン検出を動作確認

API を使う

Realtime STT API で構築を開始

SDK を使う

実際のコードを見てみる