For the complete documentation index, see llms.txt. Markdown versions of documentation pages are available by appending .md to the page URL.
メインナビゲーション
Theme

リアルタイム文字起こし

Realtime セッションでライブ音声を文字に起こします。

マイク入力や通話などのライブ音声ストリームからテキストを取得したい場合で、アシスタントの音声応答が不要なときは、リアルタイム文字起こしを使用します。推奨モデルは音声を受信するたびに文字起こしの差分を返し、アプリケーションが音声ターンをコミットするたびに、そのターンの確定結果を返します。

まずは gpt-live-transcribe を使用してください。録音済みの音声にはファイルの文字起こしを使用します。各ワークフローの比較は文字起こしの概要を参照してください。

文字起こしセッションの作成

標準の API キーを使ってサーバー側で WebSocket 経由の文字起こしを行う場合は、wss://api.openai.com/v1/realtime?intent=transcription に接続します。WebSocket ガイドに記載の認証ヘッダーを使用し、model は URL に含めないでください。ガイドに記載されているモデル指定付きの URL で接続すると、会話セッションが作成されます。このセッションでは、以下の文字起こし用の更新を受け付けません。

接続が確立したら、session.update を送信します。このイベントでは type: "transcription" を指定し、セッション設定で gpt-live-transcribe を選択します。ブラウザで音声を扱う場合は WebRTC を参照してください。

{
  "type": "session.update",
  "session": {
    "type": "transcription",
    "audio": {
      "input": {
        "format": {
          "type": "audio/pcm",
          "rate": 24000
        },
        "transcription": {
          "model": "gpt-live-transcribe"
        },
        "turn_detection": null
      }
    }
  }
}

この例では 24 kHz の PCM 音声を使用します。gpt-live-transcribe の文字起こしセッションでは、audio.input.turn_detection を省略するか、null に設定してください。このモデルは server_vad と semantic_vad のどちらにも対応していません。セッション設定の全項目は Realtime セッションのリファレンスを参照してください。

音声のストリーミング

音声チャンクを input_audio_buffer.append で送信します。

ws.send(
  JSON.stringify({
    type: "input_audio_buffer.append",
    audio: base64Pcm16,
  })
);

各音声ターンの終了時に input_audio_buffer.commit を送信すると、文字起こしの確定結果を受け取れます。

ws.send(
  JSON.stringify({
    type: "input_audio_buffer.commit",
  })
);

クライアント側の VAD で発話の終了を検出してから、input_audio_buffer.commit を送信します。

文字起こしイベントの処理

文字起こしの差分イベントと完了イベントを監視します。

ws.on("message", (data) => {
  const event = JSON.parse(data);

  if (event.type === "conversation.item.input_audio_transcription.delta") {
    process.stdout.write(event.delta);
  }

  if (event.type === "conversation.item.input_audio_transcription.completed") {
    console.log("\nFinal transcript:", event.transcript);
  }
});

差分イベントには、新たに文字に起こされたテキストが含まれます。

{
  "type": "conversation.item.input_audio_transcription.delta",
  "item_id": "item_003",
  "content_index": 0,
  "delta": "Hello,"
}

完了イベントには、コミットした項目の文字起こしの確定結果が含まれます。

{
  "type": "conversation.item.input_audio_transcription.completed",
  "item_id": "item_003",
  "content_index": 0,
  "transcript": "Hello, how are you?"
}

異なる発話ターンの完了イベントが発話順に届く保証はありません。item_id を使って、文字起こしイベントをコミット済みの入力項目に対応付けてください。

文字起こしセッションを設定したら、以下の Go 関数を使って 24 kHz のモノラル PCM16 音声を送信し、ターンをコミットして、文字起こしの確定結果をコミット済みの項目に対応付けます。

func transcribeTurn(ctx context.Context, conn *realtime.RealtimeConnection, audio []byte) error {
	for start := 0; start < len(audio); start += 9600 {
		end := min(start+9600, len(audio))
		if err := conn.Send(ctx, realtime.RealtimeClientEventParamOfInputAudioBufferAppend(base64.StdEncoding.EncodeToString(audio[start:end]))); err != nil {
			return err
		}
	}
	if err := conn.Send(ctx, realtime.RealtimeClientEventUnionParam{
		OfInputAudioBufferCommit: &realtime.InputAudioBufferCommitEventParam{},
	}); err != nil {
		return err
	}
	// Match the final transcript to the committed item, not event arrival order.
	var itemID string
	for {
		event, err := conn.Recv(ctx)
		if err != nil {
			return err
		}
		switch event.Type {
		case "input_audio_buffer.committed":
			itemID = event.OfInputAudioBufferCommittedEvent.ItemID
		case "conversation.item.input_audio_transcription.delta":
			delta := event.OfConversationItemInputAudioTranscriptionDeltaEvent
			if itemID != "" && delta.ItemID == itemID {
				fmt.Fprintf(os.Stderr, "Partial transcript (%s): %s\n", delta.ItemID, delta.Delta)
			}
		case "conversation.item.input_audio_transcription.completed":
			completed := event.OfConversationItemInputAudioTranscriptionCompletedEvent
			if itemID == "" || completed.ItemID != itemID {
				continue
			}
			fmt.Println("Final transcript:", completed.Transcript)
			return nil
		case "conversation.item.input_audio_transcription.failed":
			if itemID != "" && event.OfConversationItemInputAudioTranscriptionFailedEvent.ItemID == itemID {
				return fmt.Errorf("transcription failed")
			}
		case "error":
			return fmt.Errorf("Realtime API error: %s", event.OfRealtimeErrorEvent.Error.Message)
		}
	}
}

文字起こし用コンテキストの追加

音声に専門用語が含まれる場合や、複数の言語が想定される場合は、コンテキストを追加します。進行中のセッションで文字起こし設定を変更するには、session.update イベントを再度送信します。

{
  "type": "session.update",
  "session": {
    "type": "transcription",
    "audio": {
      "input": {
        "format": {
          "type": "audio/pcm",
          "rate": 24000
        },
        "transcription": {
          "model": "gpt-live-transcribe",
          "prompt": "A customer support call about a premium plan and account AC-42.",
          "keywords": ["premium plan", "AC-42", "billing"],
          "languages": ["en", "fr"],
          "delay": "low"
        },
        "turn_detection": null
      }
    }
  }
}
  • prompt には、録音の内容や収録時の状況を記述します。
  • keywords には、製品名や略語など、音声に登場しそうな用語をそのまま指定します。
  • languages には、入力で想定される言語を指定します。

対応する言語コードの形式には、以下のものがあります。

  • ISO 639-1 コード(en、es、fr など)
  • 一部の ISO 639-3 コード(eng、spa、yue、cmn など)
  • 地域を指定する zh ロケールコード(zh-cn、zh-tw、zh-hk など)

Realtime API は、未対応の言語コードや形式が正しくない言語コードを拒否します。

キーワードは文字起こしのヒントであり、出力に必ず含まれるわけではありません。各キーワードは 1 行に収め、<、>、キャリッジリターン、ラインフィードを含めないでください。キーワードにこれらの文字が含まれている場合や、prompt がモデルの長さ制限を超えている場合、Realtime API はセッションの更新を拒否します。

gpt-live-transcribe では languages を使用します。単数形の language フィールドと併せて送信しないでください。

コミット済みターンの文字起こし

Realtime セッションで gpt-transcribe を使用するのは、音声ターンのコミット後に文字起こしを開始する必要がある場合や、検出された言語を出力として取得する必要がある場合に限ります。このワークフローには WebSocket 接続が必要です。

gpt-transcribe は、Realtime API セッションで入力音声を文字に起こす場合も、文字起こし専用セッションで動作する場合も、文字起こし済みの過去のターンを自動的にコンテキストとして使用します。

{
  "type": "session.update",
  "session": {
    "type": "transcription",
    "audio": {
      "input": {
        "format": {
          "type": "audio/pcm",
          "rate": 24000
        },
        "transcription": {
          "model": "gpt-transcribe"
        },
        "turn_detection": null
      }
    }
  }
}

音声を追加し、input_audio_buffer.commit を送信します。その後、モデルは完了イベントの前に文字起こしの差分を送信することがあります。完了イベントには、検出された言語も含まれます。

{
  "type": "conversation.item.input_audio_transcription.completed",
  "item_id": "item_003",
  "content_index": 0,
  "transcript": "Bonjour, pouvez-vous m'entendre ?",
  "languages": [{ "code": "fr" }]
}

gpt-transcribe が十分な確度で言語を判定できない場合、languages は空の配列になります。gpt-live-transcribe は言語の判定結果を返しません。

レイテンシと精度の調整

ストリーミング文字起こしでは、レイテンシと文字起こしの品質の間にトレードオフがあります。遅延を短く設定すると、途中結果を早く取得できる場合があります。遅延を長く設定すると、モデルがテキストを出力する前にコンテキストとして使える音声が増え、単語誤り率が下がる場合があります。

まず audio.input.transcription.delay を設定し、実際の音声でテストします。初期設定の目安は以下のとおりです。

  • minimal は、応答の速さが最優先のやり取り向け
  • low は、低レイテンシのライブ字幕向け
  • medium は、レイテンシと精度のバランスを重視する用途向け
  • high は、即時表示より精度を重視する用途向け
  • xhigh は、より長い音声をコンテキストとして使うために最大の遅延を許容できるワークフロー向け

実際の遅延時間(ミリ秒)はモデル設定によって変わります。各レベルの遅延を固定値とみなさず、実際の利用状況を代表する音声で測定してください。

合成音声だけで設定を決めないでください。実際の利用状況に合ったマイクや通話音声を使い、アクセント、背景雑音、発話中の言語の切り替え、専門用語、長時間のセッションを含めてテストしてください。

信頼度、タイムスタンプ、話者ラベルの扱い

gpt-live-transcribe は、単語単位のタイムスタンプ、話者ラベル、文字起こしの信頼度スコアを返しません。アプリケーションでタイムスタンプや話者ラベルが必要な場合は、それらに対応したファイルの文字起こしモデルを使用するか、アプリケーション側に代替処理を追加してください。

本番運用のチェックリスト

  • 調整を始める前に、目標レイテンシと精度のしきい値を決めます。
  • 雑音のないサンプルに加え、本番環境の実際の音声でもテストします。
  • 対象言語ごとにテストします。
  • 評価用データセットに、数値、日付、通貨、メールアドレス、製品名、専門用語を含めます。
  • 空の結果、途中で途切れた結果、遅れて届いた結果を、単語誤り率とは別に追跡します。
  • 後続の差分で先に届いたテキストが訂正された場合に、UI に表示した途中結果をどう更新するか決めます。
  • item_id を使って文字起こしの確定結果を順に並べ、対応する入力項目と照合します。
  • タイムスタンプ、話者ラベル、信頼度のフィールドがサポートされていない場合に備え、代替処理を用意します。

関連ガイド

Realtime と音声の概要

音声エージェント、翻訳、文字起こしの各セッションを比較します。

リアルタイム翻訳

翻訳専用セッションを使って発話をリアルタイムで翻訳します。

WebSocket 接続

サーバー側のメディアパイプラインを通じて生の音声データをストリーミングします。

音声区間検出

ライブ音声ストリームのターン検出を設定します。