OpenAI リアルタイム対話インターフェース
OpenAI リアルタイム対話インターフェース
Section titled “OpenAI リアルタイム対話インターフェース”このページの概要
公式ドキュメント
- OpenAI Realtime WebRTC
- OpenAI Realtime WebSocket
OpenAI Realtime API は、2つの接続方式を提供します。
- WebRTC - ブラウザやモバイルクライアントでのリアルタイム音声・映像のやり取りに適しています
- WebSocket - サーバー間のアプリケーション統合に適しています
ユースケース✅
Section titled “ユースケース✅”- リアルタイム音声対話
- 音声・映像会議
- リアルタイム翻訳
- 音声文字起こし
- リアルタイムコード生成
- サーバー側のリアルタイム統合
- 双方向音声ストリーム転送
- テキストと音声を組み合わせた対話
- 関数呼び出し対応
- 自動音声検出(VAD)
- 音声文字起こし機能
- WebSocket を使ったサーバー側統合
🔐 認証とセキュリティ✅
Section titled “🔐 認証とセキュリティ✅”- 標準 API キー(サーバー側のみで使用)
- 一時トークン(クライアント側で使用)
一時トークン✅
Section titled “一時トークン✅”- 有効期限: 1分
- 使用制限: 1接続につき1つ
- 取得方法: サーバー側 API で作成
POST https://4All API地址/v1/realtime/sessionsContent-Type: application/jsonAuthorization: Bearer $4All API_API_KEY
{ "model": "gpt-4o-realtime-preview-2024-12-17", "voice": "verse"}セキュリティの推奨事項✅
Section titled “セキュリティの推奨事項✅”- 標準 API キーをクライアントに絶対に公開しない
- 通信には HTTPS/WSS を使用する
- 適切なアクセス制御を実装する
- 不審なアクティビティを監視する
🔌 接続の確立✅
Section titled “🔌 接続の確立✅”WebRTC 接続✅
Section titled “WebRTC 接続✅”- URL: https://4All API地址/v1/realtime
- クエリパラメータ: model
- リクエストヘッダー:
- Authorization: Bearer EPHEMERAL_KEY
- Content-Type: application/sdp
WebSocket 接続
Section titled “WebSocket 接続”- URL: wss://4All API地址/v1/realtime
- クエリパラメータ: model
- リクエストヘッダー:
- Authorization: Bearer YOUR_API_KEY
- OpenAI-Beta: realtime=v1
接続フロー✅
Section titled “接続フロー✅”データチャネル✅
Section titled “データチャネル✅”- 名前: oai-events
- 用途: イベント転送
- 形式: JSON
音声ストリーム✅
Section titled “音声ストリーム✅”- 入力: addTrack()
- 出力: ontrack イベント
💬 対話インタラクション
Section titled “💬 対話インタラクション”対話モード✅
Section titled “対話モード✅”- テキストのみの対話
- 音声対話
- テキストと音声の混在対話
- 会話の作成
- 会話の更新
- 会話の終了
- 会話設定
イベント種別✅
Section titled “イベント種別✅”- テキストイベント
- 音声イベント
- 関数呼び出し
- 状態更新
- エラーイベント
⚙️ 設定オプション✅
Section titled “⚙️ 設定オプション✅”音声設定[¶]✅
Section titled “音声設定[¶]✅”- 入力形式
- pcm16
- g711_ulaw
- g711_alaw
- 出力形式
- pcm16
- g711_ulaw
- g711_alaw
- 音声タイプ
- alloy
- echo
- shimmer
モデル設定✅
Section titled “モデル設定✅”- 温度
- 最大出力長
- システムプロンプト
- ツール設定
VAD 設定✅
Section titled “VAD 設定✅”- 閾値
- 無音継続時間
- プレフィックスパディング
💡 リクエスト例✅
Section titled “💡 リクエスト例✅”WebRTC 接続 ❌
Section titled “WebRTC 接続 ❌”クライアント実装 (ブラウザ)✅
Section titled “クライアント実装 (ブラウザ)✅”async function init() { // サーバーから一時キーを取得 - 下記のサーバーコードを参照 const tokenResponse = await fetch("/session"); const data = await tokenResponse.json(); const EPHEMERAL_KEY = data.client_secret.value;
// ピア接続を作成 const pc = new RTCPeerConnection();
// モデルが返すリモート音声の再生を設定 const audioEl = document.createElement("audio"); audioEl.autoplay = true; pc.ontrack = e => audioEl.srcObject = e.streams[0];
// ブラウザのマイク入力からローカル音声トラックを追加 const ms = await navigator.mediaDevices.getUserMedia({ audio: true }); pc.addTrack(ms.getTracks()[0]);
// イベント送受信用のデータチャネルを設定 const dc = pc.createDataChannel("oai-events"); dc.addEventListener("message", (e) => { // ここでリアルタイムサーバーイベントを受信します! console.log(e); });
// セッション記述プロトコル(SDP)を使ってセッションを開始 const offer = await pc.createOffer(); await pc.setLocalDescription(offer);
const baseUrl = "https://4All API地址/v1/realtime"; const model = "gpt-4o-realtime-preview-2024-12-17"; const sdpResponse = await fetch(`${baseUrl}?model=${model}`, { method: "POST", body: offer.sdp, headers: { Authorization: `Bearer ${EPHEMERAL_KEY}`, "Content-Type": "application/sdp" }, });
const answer = { type: "answer", sdp: await sdpResponse.text(), }; await pc.setRemoteDescription(answer);}
init();サーバー側実装 (Node.js)✅
Section titled “サーバー側実装 (Node.js)✅”import express from "express";
const app = express();
// 一時トークンを生成するためのエンドポイントを作成// このエンドポイントは上記のクライアントコードと連携して使用しますapp.get("/session", async (req, res) => { const r = await fetch("https://4All API地址/v1/realtime/sessions", { method: "POST", headers: { "Authorization": `Bearer ${process.env.4All API_API_KEY}`, "Content-Type": "application/json", }, body: JSON.stringify({ model: "gpt-4o-realtime-preview-2024-12-17", voice: "verse", }), }); const data = await r.json();
// OpenAI REST API から受け取った JSON をクライアントに返す res.send(data);});
app.listen(3000);WebRTC イベント送受信の例✅
Section titled “WebRTC イベント送受信の例✅”// ピア接続からデータチャネルを作成const dc = pc.createDataChannel("oai-events");
// データチャネル上でサーバーイベントを監視// イベントデータは JSON 文字列からパースする必要がありますdc.addEventListener("message", (e) => { const realtimeEvent = JSON.parse(e.data); console.log(realtimeEvent);});
// クライアントイベントを送信: 有効なクライアントイベントを// JSON にシリアライズし、データチャネル経由で送信const responseCreate = { type: "response.create", response: { modalities: ["text"], instructions: "Write a haiku about code", },};dc.send(JSON.stringify(responseCreate));WebSocket 接続 ✅
Section titled “WebSocket 接続 ✅”Node.js (ws モジュール)✅
Section titled “Node.js (ws モジュール)✅”import WebSocket from "ws";
const url = "wss://4All API地址/v1/realtime?model=gpt-4o-realtime-preview-2024-12-17";const ws = new WebSocket(url, { headers: { "Authorization": "Bearer " + process.env.4All API_API_KEY, "OpenAI-Beta": "realtime=v1", },});
ws.on("open", function open() { console.log("Connected to server.");});
ws.on("message", function incoming(message) { console.log(JSON.parse(message.toString()));});Python (websocket-client)✅
Section titled “Python (websocket-client)✅”# 必要なライブラリ:# pip install websocket-client
import osimport jsonimport websocket
NEW_API_KEY = os.environ.get("4All API_API_KEY")
url = "wss://4All API地址/v1/realtime?model=gpt-4o-realtime-preview-2024-12-17"headers = [ "Authorization: Bearer " + 4All API_API_KEY, "OpenAI-Beta: realtime=v1"]
def on_open(ws): print("Connected to server.")
def on_message(ws, message): data = json.loads(message) print("Received event:", json.dumps(data, indent=2))
ws = websocket.WebSocketApp( url, header=headers, on_open=on_open, on_message=on_message,)
ws.run_forever()ブラウザ (標準 WebSocket)✅
Section titled “ブラウザ (標準 WebSocket)✅”/*注意: ブラウザなどのクライアント環境では、WebRTC の使用を推奨します。ただし、Deno や Cloudflare Workers のようなブラウザ風環境では、標準の WebSocket インターフェースも使用できます。*/
const ws = new WebSocket( "wss://4All API地址/v1/realtime?model=gpt-4o-realtime-preview-2024-12-17", [ "realtime", // 認証 "openai-insecure-api-key." + 4All API_API_KEY, // 任意 "openai-organization." + OPENAI_ORG_ID, "openai-project." + OPENAI_PROJECT_ID, // Beta プロトコル、必須 "openai-beta.realtime-v1" ]);
ws.on("open", function open() { console.log("Connected to server.");});
ws.on("message", function incoming(message) { console.log(message.data);});メッセージ送受信の例✅
Section titled “メッセージ送受信の例✅”Node.js/ブラウザ✅
Section titled “Node.js/ブラウザ✅”// サーバーイベントを受信ws.on("message", function incoming(message) { // メッセージデータは JSON からパースする必要があります const serverEvent = JSON.parse(message.data) console.log(serverEvent);});
// イベントを送信: クライアントイベント形式に合う JSON データ構造を作成const event = { type: "response.create", response: { modalities: ["audio", "text"], instructions: "Give me a haiku about code.", }};ws.send(JSON.stringify(event));Python✅
Section titled “Python✅”# クライアントイベントを送信: 辞書を JSON にシリアライズdef on_open(ws): print("Connected to server.")
event = { "type": "response.create", "response": { "modalities": ["text"], "instructions": "Please assist the user." } } ws.send(json.dumps(event))
# メッセージ受信時はメッセージ本体を JSON からパースする必要がありますdef on_message(ws, message): data = json.loads(message) print("Received event:", json.dumps(data, indent=2))⚠️ エラー処理✅
Section titled “⚠️ エラー処理✅”よくあるエラー✅
Section titled “よくあるエラー✅”- 接続エラー
- ネットワーク問題
- 認証失敗
- 設定ミス
- 音声エラー
- デバイス権限
- 未対応フォーマット
- コーデック問題
- 会話エラー
- トークン期限切れ
- セッションタイムアウト
- 同時実行制限
エラー復旧✅
Section titled “エラー復旧✅”- 自動再接続
- セッション復元
- エラーの再試行
- フォールバック処理
📝 イベントリファレンス✅
Section titled “📝 イベントリファレンス✅”共通リクエストヘッダー✅
Section titled “共通リクエストヘッダー✅”すべてのイベントには、以下のリクエストヘッダーが必要です。
| リクエストヘッダー | 種類 | 説明 | 例 |
|---|---|---|---|
| Authorization | 文字列 | 認証トークン | Bearer $NEW_API_KEY |
| OpenAI-Beta | 文字列 | API バージョン | realtime=v1 |
クライアントイベント✅
Section titled “クライアントイベント✅”session.update✅
Section titled “session.update✅”会話のデフォルト設定を更新します。
| パラメータ | 種類 | 必須 | 説明 | 例/選択肢 |
|---|---|---|---|---|
| event_id | 文字列 | いいえ | クライアント生成のイベント識別子 | event_123 |
| type | 文字列 | いいえ | イベント種別 | session.update |
| modalities | 文字列配列 | いいえ | モデルが応答できるモダリティ | [“text”, “audio”] |
| instructions | 文字列 | いいえ | モデル呼び出し前に設定されるシステム指示 | ”Your knowledge cutoff is 2023-10…“ |
| voice | 文字列 | いいえ | モデルが使用する音声タイプ | alloy、echo、shimmer |
| input_audio_format | 文字列 | いいえ | 入力音声フォーマット | pcm16、g711_ulaw、g711_alaw |
| output_audio_format | 文字列 | いいえ | 出力音声フォーマット | pcm16、g711_ulaw、g711_alaw |
| input_audio_transcription.model | 文字列 | いいえ | 文字起こしに使用するモデル | whisper-1 |
| turn_detection.type | 文字列 | いいえ | 音声検出タイプ | server_vad |
| turn_detection.threshold | 数値 | いいえ | VAD の有効化しきい値(0.0-1.0) | 0.8 |
| turn_detection.prefix_padding_ms | 整数 | いいえ | 発話開始前に含める音声の長さ | 500 |
| turn_detection.silence_duration_ms | 整数 | いいえ | 発話終了を検出するための無音継続時間 | 1000 |
| tools | 配列 | いいえ | モデルが利用できるツール一覧 | [] |
| tool_choice | 文字列 | いいえ | モデルがツールを選択する方法 | auto/none/required |
| temperature | 数値 | いいえ | モデルのサンプリング温度 | 0.8 |
| max_output_tokens | 文字列/整数 | いいえ | 1回の応答で生成可能な最大 token 数 | ”inf”/4096 |
input_audio_buffer.append✅
Section titled “input_audio_buffer.append✅”入力音声バッファに音声データを追加します。
| パラメータ | 種類 | 必須 | 説明 | 例 |
|---|---|---|---|---|
| event_id | 文字列 | いいえ | クライアント生成のイベント識別子 | event_456 |
| type | 文字列 | いいえ | イベント種別 | input_audio_buffer.append |
| audio | 文字列 | いいえ | Base64 エンコードされた音声データ | Base64EncodedAudioData |
input_audio_buffer.commit✅
Section titled “input_audio_buffer.commit✅”バッファ内の音声データをユーザーメッセージとして確定します。
| パラメータ | 種類 | 必須 | 説明 | 例 |
|---|---|---|---|---|
| event_id | 文字列 | いいえ | クライアント生成のイベント識別子 | event_789 |
| type | 文字列 | いいえ | イベント種別 | input_audio_buffer.commit |
input_audio_buffer.clear✅
Section titled “input_audio_buffer.clear✅”入力音声バッファ内のすべての音声データを消去します。
| パラメータ | 種類 | 必須 | 説明 | 例 |
|---|---|---|---|---|
| event_id | 文字列 | いいえ | クライアント生成のイベント識別子 | event_012 |
| type | 文字列 | いいえ | イベント種別 | input_audio_buffer.clear |
conversation.item.create✅
Section titled “conversation.item.create✅”会話に新しいアイテムを追加します。
| パラメータ | 種類 | 必須 | 説明 | 例 |
|---|---|---|---|---|
| event_id | 文字列 | いいえ | クライアント生成のイベント識別子 | event_345 |
| type | 文字列 | いいえ | イベント種別 | conversation.item.create |
| previous_item_id | 文字列 | いいえ | 新しい会話アイテムをこの ID の後に挿入します | null |
| item.id | 文字列 | いいえ | 会話アイテムの一意識別子 | msg_001 |
| item.type | 文字列 | いいえ | 会話アイテムの種別 | message/function_call/function_call_output |
| item.status | 文字列 | いいえ | 会話アイテムの状態 | completed/in_progress/incomplete |
| item.role | 文字列 | いいえ | メッセージ送信者の役割 | user/assistant/system |
| item.content | 配列 | いいえ | メッセージ内容 | [text/audio/transcript] |
| item.call_id | 文字列 | いいえ | 関数呼び出しの ID | call_001 |
| item.name | 文字列 | いいえ | 呼び出された関数名 | function_name |
| item.arguments | 文字列 | いいえ | 関数呼び出しの引数 | {“param”: “value”} |
| item.output | 文字列 | いいえ | 関数呼び出しの出力結果 | {“result”: “value”} |
conversation.item.truncate✅
Section titled “conversation.item.truncate✅”アシスタントメッセージ内の音声コンテンツを切り詰めます。
| パラメータ | 種類 | 必須 | 説明 | 例 |
|---|---|---|---|---|
| event_id | 文字列 | いいえ | クライアント生成のイベント識別子 | event_678 |
| type | 文字列 | いいえ | イベント種別 | conversation.item.truncate |
| item_id | 文字列 | いいえ | 切り詰めるアシスタントメッセージアイテムの ID | msg_002 |
| content_index | 整数 | いいえ | 切り詰め対象のコンテンツ部分のインデックス | 0 |
| audio_end_ms | 整数 | いいえ | 音声切り詰めの終了時刻 | 1500 |
conversation.item.delete✅
Section titled “conversation.item.delete✅”会話履歴から指定の会話アイテムを削除します。
| パラメータ | 種類 | 必須 | 説明 | 例 |
|---|---|---|---|---|
| event_id | 文字列 | いいえ | クライアント生成のイベント識別子 | event_901 |
| type | 文字列 | いいえ | イベント種別 | conversation.item.delete |
| item_id | 文字列 | いいえ | 削除する会話アイテムの ID | msg_003 |
response.create✅
Section titled “response.create✅”応答生成を開始します。
| パラメータ | 種類 | 必須 | 説明 | 例 |
|---|---|---|---|---|
| event_id | 文字列 | いいえ | クライアント生成のイベント識別子 | event_234 |
| type | 文字列 | いいえ | イベント種別 | response.create |
| response.modalities | 文字列配列 | いいえ | 応答のモダリティ | [“text”, “audio”] |
| response.instructions | 文字列 | いいえ | モデルへの指示 | ”Please assist the user.” |
| response.voice | 文字列 | いいえ | モデルが使用する音声タイプ | alloy/echo/shimmer |
| response.output_audio_format | 文字列 | いいえ | 出力音声フォーマット | pcm16 |
| response.tools | 配列 | いいえ | モデルが利用できるツール一覧 | [“type”, “name”, “description”] |
| response.tool_choice | 文字列 | いいえ | モデルがツールを選択する方法 | auto |
| response.temperature | 数値 | いいえ | サンプリング温度 | 0.7 |
| response.max_output_tokens | 整数/文字列 | いいえ | 最大出力 token 数 | 150/“inf” |
response.cancel✅
Section titled “response.cancel✅”進行中の応答生成をキャンセルします。
| パラメータ | 種類 | 必須 | 説明 | 例 |
|---|---|---|---|---|
| event_id | 文字列 | いいえ | クライアント生成のイベント識別子 | event_567 |
| type | 文字列 | いいえ | イベント種別 | response.cancel |
サーバーイベント✅
Section titled “サーバーイベント✅”error✅
Section titled “error✅”エラー発生時に返されるイベントです。
| パラメータ | 種類 | 必須 | 説明 | 例 |
|---|---|---|---|---|
| event_id | 文字列配列 | いいえ | サーバーイベントの一意識別子 | [“event_890”] |
| type | 文字列 | いいえ | イベント種別 | error |
| error.type | 文字列 | いいえ | エラー種別 | invalid_request_error/server_error |
| error.code | 文字列 | いいえ | エラーコード | invalid_event |
| error.message | 文字列 | いいえ | 人間が読めるエラーメッセージ | ”The ‘type’ field is missing.” |
| error.param | 文字列 | いいえ | エラーに関連するパラメータ | null |
| error.event_id | 文字列 | いいえ | 関連イベントの ID | event_567 |
conversation.item.input_audio_transcription.completed✅
Section titled “conversation.item.input_audio_transcription.completed✅”入力音声の文字起こしが有効で、文字起こしに成功した場合に返されるイベントです。
| パラメータ | 種類 | 必須 | 説明 | 例 |
|---|---|---|---|---|
| event_id | 文字列 | いいえ | サーバーイベントの一意識別子 | event_2122 |
| type | 文字列 | いいえ | イベント種別 | conversation.item.input_audio_transcription.completed |
| item_id | 文字列 | いいえ | ユーザーメッセージアイテムの ID | msg_003 |
| content_index | 整数 | いいえ | 音声を含むコンテンツ部分のインデックス | 0 |
| transcript | 文字列 | いいえ | 文字起こしされたテキスト | ”Hello, how are you?“ |
conversation.item.input_audio_transcription.failed✅
Section titled “conversation.item.input_audio_transcription.failed✅”入力音声の文字起こしが設定されているにもかかわらず、ユーザーメッセージの文字起こし要求に失敗した場合に返されるイベントです。
| パラメータ | 種類 | 必須 | 説明 | 例 |
|---|---|---|---|---|
| event_id | 文字列 | いいえ | サーバーイベントの一意識別子 | event_2324 |
| type | 文字列配列 | いいえ | イベント類 |