リアルタイムAPI(Realtime API)とは?接続方式と実装手順【2026年8月版】
リアルタイムAPI、すなわちOpenAIのRealtime APIは、マイクで拾った音声をそのままモデルへ送り、生成された音声をそのまま受け取るAPIです。文字起こし・テキスト生成・音声合成を別々に呼び出す従来の構成と違い、ひとつのセッションの中で音声が往復します。注意したいのは、2024年のベータ期に書かれた手順が現在そのままでは動かない点。ヘッダもイベント名もエンドポイントもGA移行で変わり、当時よく参照されたLangChainの実装例はアーカイブされました。この記事では、定義の切り分けから接続方式の選び方、GA後の実装、そして採用を見送るべき条件までを扱います。
まとめ:着手前に決める接続方式と、ベータ実装からの移行点
- 最初に決めるのは接続方式:ブラウザとモバイルはWebRTC、サーバへ生音声が届く構成はWebSocket、電話まわりはSIPです。ここが後工程の作りをほぼ決めるため、モデル選定より先に固めてください。
- ベータ実装からの移行:
OpenAI-Beta: realtime=v1ヘッダを外し、session.typeを指定し、応答イベントをresponse.output_audio.delta系の名前へ置き換えます。
モデルは用途で分かれており、音声エージェントは gpt-realtime-2.1、通訳は gpt-realtime-translate、文字起こしは gpt-live-transcribe が対象です。以降では、まぎらわしい「リアルタイムAPI」という語の切り分けから始め、接続方式ごとの判断条件、セッション設定と関数呼び出し、音声対話AIの作り方にあたるPythonの最小実装、2024年の手順が落ちる箇所、採用判断の順に説明します。
Realtime APIの定義と「リアルタイムAPI」が指す2つの対象
一般名詞のリアルタイム連携APIとOpenAI Realtime APIの区別
日本語で「リアルタイムAPI」と検索したとき、指しているものは2つに分かれます。ひとつは、サーバ側の状態変化を待たずにクライアントへ届ける連携APIの総称です。WebSocketやServer-Sent Events、Webhookを土台にした実装がこれにあたり、Supabase RealtimeやFirebase Realtime Databaseのような製品名にも同じ語が使われます。通信レイヤの仕組みから確認したい場合は、WebSocketのハンドシェイクと運用設計を先に読むと接続方式の判断が早くなります。
もうひとつが、本記事で扱うOpenAIのRealtime APIです。こちらは固有名詞で、音声対話のためにモデルとクライアントを常時接続し、音声チャンクとイベントを双方向に流すAPIを指します。両者は目的が違うため、社内で「リアルタイムAPIを使いたい」と話が出たときは、データ連携の話なのか音声対話の話なのかを最初に確認しておくと設計の手戻りを防げます。
音声を1セッションで往復させる構造とチェーン型との違い
OpenAIの音声エージェント向けドキュメントは、実装の型を2つに分けています。ひとつはspeech-to-speechで、モデルが音声の入力と出力を直接扱い、低遅延の自然な会話を狙う構成です。もうひとつはchained voice pipelineで、文字起こし・テキスト推論・音声合成を自分の側で明示的に制御します。公式はチェーン型を「予測可能なワークフロー」や「既存のテキストエージェントの拡張」に向くと位置づけており、速さだけでどちらかが上位というつくりにはなっていません。
旧来の3段構成では、音声認識の完了を待ってからテキスト生成が始まり、その完了を待って音声合成が動くため、待ち時間が積み上がります。Realtime APIは、この直列の待ちをセッション内のイベント連携に置き換える設計です。
GA後に選べる3モデルとセッションの指定方法
| モデル | 担当する処理 | セッションの指定方法 |
|---|---|---|
| gpt-realtime-2.1 | 音声エージェントの対話 | session.type に realtime |
| gpt-realtime-translate | 発話の連続翻訳 | 専用エンドポイント |
| gpt-live-transcribe | 低遅延の文字起こし | session.type に transcription |
3つのうち翻訳だけが指定方法の系統が違い、session.type ではなく /v1/realtime/translations という別エンドポイントで区別します。対話と文字起こしは同じ /v1/realtime に接続したうえで session.type を切り替える形です。各モデルの仕様と料金の比較はOpenAI音声3モデルの仕様と料金の違いで、製品版であるGPT-Live-1とAPIの役割分担はフルデュプレックス音声モデルとRealtime APIの使い分けで扱っています。この記事はAPIそのものの構造と実装に絞ります。
接続方式の選定:WebRTC・WebSocket・SIP
ブラウザとモバイルでWebRTCを選ぶ条件とエフェメラルキー
公式はWebRTCを「音声を直接取り込む、あるいは再生するブラウザとモバイルのクライアント」向けと明記しています。判断の分かれ目は、音声デバイスを触るのがユーザーの端末かサーバかという一点です。端末側なら、パケットロス耐性やジッタバッファを自前で用意しなくて済むWebRTCが素直な選択になります。
ここで問題になるのが認証です。APIキーをブラウザへ配ることはできないため、サーバ側で POST /v1/realtime/client_secrets を呼んで短命の資格情報を発行し、それをクライアントへ渡します。WebRTCセッション自体は /v1/realtime/calls に対して確立します。
const sessionConfig = JSON.stringify({
session: {
type: "realtime",
model: "gpt-realtime-2.1",
audio: { output: { voice: "marin" } },
},
});
const response = await fetch(
"https://api.openai.com/v1/realtime/client_secrets",
{
method: "POST",
headers: {
Authorization: `Bearer ${apiKey}`,
"Content-Type": "application/json",
"OpenAI-Safety-Identifier": "hashed-user-id",
},
body: sessionConfig,
}
);
渡す sessionConfig は session をルートに持つJSON文字列です。オブジェクトのまま body に入れると [object Object] が送られて400が返るため、JSON.stringify を必ず通してください。セッションの設定をサーバ側で組み立てられるので、クライアントから勝手にモデルや指示文を差し替えられない構成にできます。
サーバへ生音声が届く構成でWebSocketを選ぶ条件
WebSocketは「メディアパイプライン、通話システム、ワーカーからサーバがすでに生音声を受け取っている」場合に使うと公式が説明しています。既存のCTIや音声収録基盤がサーバ側に音声を落としているなら、端末を経由させずWebSocketで直結するほうが構成は単純です。接続先は wss://api.openai.com/v1/realtime?model=gpt-realtime-2.1、ヘッダは Authorization と OpenAI-Safety-Identifier の2つになります。
電話音声でSIPを選ぶ場合の確認事項
SIPは電話向けの音声エージェントで使う方式です。公式は、翻訳や文字起こしにSIPを使う前にモデル側の対応を確認するよう注記しています。コールセンターの一次応答を組む場合、対話は組めても同じ回線で通訳や逐語記録まで通せるとは限らないため、方式の決定前にモデル対応の確認を工程へ入れてください。
通話そのものの制御は /realtime/calls 配下に用意されています。着信を受ける accept、通話を切る hangup、別番号へ転送する refer、着信を断る reject がそれぞれ /realtime/calls/{call_id}/accept のような形で並び、公式SDKからは client.realtime.calls.accept() のように呼び出す形です。オペレーターへのエスカレーションは refer で組むため、有人転送の要件がある場合はこの4操作を先に確認しておくと設計が固まります。
セッション設定とターン制御・関数呼び出し
session.updateで決める音声フォーマットと発話指示
接続後、最初に送るのが session.update です。入力音声のフォーマット、ターン検出、出力音声とボイス、モデルへの指示をここでまとめて指定します。
{
"type": "session.update",
"session": {
"type": "realtime",
"model": "gpt-realtime-2.1",
"output_modalities": ["audio"],
"audio": {
"input": {
"format": { "type": "audio/pcm", "rate": 24000 },
"turn_detection": { "type": "semantic_vad" }
},
"output": {
"format": { "type": "audio/pcm" },
"voice": "marin"
}
},
"instructions": "日本語で簡潔に答えてください。"
}
}
ベータ期との差が出るのがこの構造です。session.type を明示すること、出力音声の設定が session.audio.output の下へ移ったことの2点は、古い実装をそのまま持ち込むと必ず引っかかります。なお上の例は semantic_vad を明示していますが、指定を省いた場合の既定は次に説明する server_vad です。
ターン検出2方式(server_vad・semantic_vad)と割り込みの制御
会話の切れ目をどう判定するかは、用途で選び分けます。VADに対応したセッションとモデルでの既定値は server_vad で、無音が続いた区間を境に発話を切ります。調整に使うのは threshold(0から1の感度)、発話検出前に含める音声の長さを決める prefix_padding_ms、発話終了とみなす無音の長さを決める silence_duration_ms の3つ。長い沈黙が想定外になる電話用途では、server_vad だけで使える idle_timeout_ms を置くと、モデル側から会話を促せます。
もう一方の semantic_vad は、無音の長さではなく発話が意味的に完結したかで区切ります。パラメータは割り込みの積極性を決める eagerness で、low・medium・high・auto の4値、既定は auto です。言い淀みが多い相手や、単語の切れ目で先走って応答されると困る場面では、こちらへ切り替える判断になります。
検出そのものを止めることもできます。押しボタン通話のように区切りをアプリ側で決めたい場合は turn_detection を null にし、input_audio_buffer.commit と response.create を自分で送ってください。検出は使いつつ応答の発火だけ自前で決めたいなら、turn_detection.interrupt_response と turn_detection.create_response を false にします。この最後の構成は、応答前に内容の審査を挟みたい業務で効いてきます。自動応答のまま運用すると、審査工程を差し込む余地がなくなるためです。
関数呼び出しで社内データにつなぐ流れ
ツールは session.tools または response.tools に type が function のオブジェクトとして定義します。モデルが関数を呼ぶと、response.done の中に引数のJSON文字列と call_id が入って返ります。アプリ側で処理した結果の返し先は conversation.item.create で、function_call_output の項目として同じ call_id を添えてください。
社内文書に基づいて回答させたい場合も、この関数呼び出しが接続点になります。音声側の設定より検索側の設計で精度が決まるため、RAGの検索工程と精度改善の判断基準を先に固めてから音声を載せる順序をおすすめします。
音声対話AIの作り方:Pythonでの最小実装
セッション確立とsession.updateの送信
Python向けの公式SDKは、GA後 client.realtime.connect() でセッションを張ります。ベータ期の client.beta.realtime も残っていますが、新規実装はGA側のパスを使ってください。次のコードは openai 2.53.0(2026年8月3日公開)で client.realtime.connect() の実在を確認したうえで組んだものです。
import asyncio
import base64
from openai import AsyncOpenAI
client = AsyncOpenAI()
SESSION = {
"type": "realtime",
"model": "gpt-realtime-2.1",
"output_modalities": ["audio"],
"audio": {
"input": {
"format": {"type": "audio/pcm", "rate": 24000},
"turn_detection": {"type": "semantic_vad"},
},
"output": {"format": {"type": "audio/pcm"}, "voice": "marin"},
},
"instructions": "日本語で簡潔に答えてください。",
}
async def talk(pcm_chunks):
async with client.realtime.connect(model="gpt-realtime-2.1") as conn:
await conn.send({"type": "session.update", "session": SESSION})
async def send_audio():
for chunk in pcm_chunks:
await conn.send({
"type": "input_audio_buffer.append",
"audio": base64.b64encode(chunk).decode(),
})
sender = asyncio.create_task(send_audio())
try:
async for event in conn:
if event.type == "response.output_audio.delta":
yield base64.b64decode(event.delta)
elif event.type == "response.output_audio_transcript.delta":
print(event.delta, end="", flush=True)
elif event.type == "response.done":
break
finally:
sender.cancel()
受信イベントの振り分けと音声フォーマットの前提
音声は24kHzのPCMをbase64にして input_audio_buffer.append で送り、返ってくる音声は response.output_audio.delta から取り出します。読み上げ内容をテキストでも押さえたい場合は response.output_audio_transcript.delta を併読してください。送信と受信は別々に動くため、送信側をタスクへ逃がし、受信ループを主体にする形が扱いやすくなります。上のコードが response.done で抜けているのは、実接続では受信ループが自然に終端しないためです。1往復で終わらせず会話を続ける場合は break を外し、終了時に送信タスクを止める処理だけ残します。
TypeScriptで組む場合は @openai/agents/realtime の RealtimeAgent と RealtimeSession を使う経路が公式の推奨です。Pythonからテキストエージェントを音声へ広げるなら、チェーン型の VoicePipeline が案内されています。
2024年のRealtime APIとLangChainの手順が動かなくなった理由
参照実装 react-voice-agent のアーカイブと固定モデル
2024年当時、Realtime APIとLangChainを組み合わせる記事の多くが土台にしていたのが、LangChain公式の langchain-ai/react-voice-agent です。このリポジトリは2026年8月時点でアーカイブ済みで、最終コミットは2024年12月11日です。中身も当時のまま止まっています。接続部の DEFAULT_MODEL は gpt-4o-realtime-preview-2024-10-01 に固定され、リクエストヘッダには "OpenAI-Beta": "realtime=v1" が入ります。無視するイベントの一覧に response.audio_transcript.delta が並んでいる点も、GAの response.output_audio_transcript.delta とは別名です。
LangChain本体側にも代わりの実装は入っていません。langchain-openai 1.4.1(2026年7月23日公開)のモジュール構成は chat_models・embeddings・llms・middleware・output_parsers・tools で、音声セッションを扱うクラスは含まれていません。つまり「LangChainでRealtime APIを使う」という導入は、現在は自前でイベントを扱う実装を書くという意味になります。
websockets 14.0以降のextra_headers廃止で出るTypeError
アーカイブされたコードをそのまま動かそうとしたとき、モデル名を差し替えても手前で止まります。原因はOpenAI側ではなく依存ライブラリです。websocketsは14.0(2024年11月9日)で from websockets import connect の実体を新しいasyncio実装へ切り替えており、ヘッダを渡す引数は additional_headers になりました。旧実装の extra_headers を渡すと、15.0.1でも最新の17.0.1(2026年7月31日公開)でも同じエラーになります。
TypeError: BaseEventLoop.create_connection() got an unexpected keyword argument 'extra_headers'
先頭の BaseEventLoop. はPython 3.10以降の表示で、3.9では create_connection() だけが出ます。当該リポジトリは requires-python が3.10以上なので、読者の環境では上の文面になるはずです。当時のコードを再現するにはwebsocketsを13系へ固定する必要がありますが、その先でGAのイベント名とセッション構造の差にぶつかります。書き直したほうが早い状況です。
ベータからGAへ移行するときの指定変更
| 移行項目 | GA後の指定 |
|---|---|
| ベータ指定ヘッダ | OpenAI-Beta: realtime=v1 を削除 |
| セッション種別 | session.type を明示 |
| 出力音声の設定 | session.audio.output の下へ移動 |
| 応答イベント名 | response.output_audio.delta 系へ変更 |
| ブラウザ資格情報の発行先 | POST /v1/realtime/client_secrets |
| WebRTCの接続先 | /v1/realtime/calls |
移行の作業量そのものは大きくありません。問題は、古い記事のコードが「動かない」ではなく「途中まで動いて別の場所で落ちる」形で失敗しやすい点です。ヘッダとイベント名を先に直してから接続を試すと、切り分けが短くなります。
採用判断:Realtime APIを選ぶ場面と見送る場面
音声往復の速さが要件になる用途
向いているのは、間の悪さがそのまま体験の質になる用途です。コールセンターの一次応答、作業中のハンズフリー操作、店頭端末の音声案内などが該当します。公式もspeech-to-speechの適所を「自然で低遅延の会話」と位置づけており、3段ぶんの待ちが積み上がらない構造そのものが選定理由になります。関数呼び出しで基幹システムを引ける点も含めると、問い合わせの一次切り分けは現実的な適用先です。
チェーン型を選ぶべき条件
一方で、Realtime APIを避けたほうがよい場面もはっきりしています。発話内容の逐語監査が必要な業務、専門用語の辞書を認識側へ効かせたい業務、出力文を送出前に審査する必要がある業務では、speech-to-speechは不利です。音声から音声へ一気に通す構造は、途中のテキストを工程として押さえにくいからです。公式もチェーン型の適所を、サポート業務や承認を多く挟む業務、そして「各段の間に確定した記録と決定的なロジックが欲しい場合」と説明しています。この条件に当てはまるなら、文字起こし・推論・合成を分けたチェーン型を選び、各段で検証と差し替えができる形にしてください。
目的が文字起こしだけなら、そもそも対話用のセッションを張る必要はありません。低遅延のストリーミング文字起こしはGPT-Live-Transcribeの実装手順と使い分けが、サービス横断の比較は文字起こしAPI主要7サービスの比較が対象を絞って扱っています。他社の音声基盤と並べて検討する段階なら、Live APIで音声エージェントを作るGemini 3.1 Flash LiveやxAIのGrok Voice Agent Builderも判断材料になります。
よくある質問
リアルタイムAPIとは何ですか?
文脈で2つに分かれます。一般名詞としては、サーバの状態変化を即時にクライアントへ届ける連携APIの総称で、WebSocketやServer-Sent Events、Webhookを土台にした実装を指します。固有名詞としては、音声の入出力をひとつのセッションで往復させるOpenAIのRealtime APIです。
音声対話AIは自作できますか。作り方に何が必要ですか?
自作できます。必要なのは、接続方式の決定(ブラウザならWebRTC、サーバ側に音声が来るならWebSocket)、session.update による音声フォーマットとターン検出の設定、そして音声チャンクの送受信処理の3つ。24kHzのPCMをbase64で送り、返ってきた音声デルタを再生する処理が最小構成になります。社内データを参照させたい場合は、関数呼び出しの実装が追加で必要です。
LangChainでRealtime APIは使えますか?
LangChain公式が公開していた参照実装 langchain-ai/react-voice-agent は2026年8月時点でアーカイブ済みで、最終コミットは2024年12月11日です。モデル名もベータ期の gpt-4o-realtime-preview-2024-10-01 のまま固定されています。langchain-openai 1.4.1にも音声セッション用のクラスはありません。LangChainのツール定義を流用すること自体は可能ですが、セッションとイベントの処理は自分で書く前提になります。
自社の資料に基づいて回答させることはできますか?
できます。session.tools に検索用の関数を定義し、モデルが呼び出したときに response.done から call_id と引数を取り出し、検索結果を conversation.item.create の function_call_output として返します。回答精度は音声側の設定ではなく検索側の設計で決まるため、チャンク分割と検索方式の検討を先行させてください。
文字起こしだけしたい場合もRealtime APIですか?
文字起こし専用のセッションが用意されており、session.type に transcription を指定して gpt-live-transcribe を使います。発話の途中から差分が返る必要がなく、区切ったあとで確定テキストが得られればよい場合は gpt-transcribe が案内されています。対話が不要なら、対話用のセッションを張る必要はありません。
関連記事
- GPT-Realtime-2とは|OpenAI音声3モデルの仕様・料金とgpt-realtime-2.1の違い
- GPT-Live-1とは?OpenAIのフルデュプレックス音声モデルの仕組み・Realtime APIとの違いと実装判断を解説【2026年7月版】
- GPT-Live-Transcribeとは?OpenAIの低遅延ストリーミング文字起こしの実装手順とGPT-Transcribeとの使い分けを解説【2026年7月版】
- WebSocketとは?仕組み・ハンドシェイクからNode.js実装・運用の判断まで実装者向けに解説
- 文字起こしAPIの比較と選び方|主要7サービスの料金・日本語対応・使い方【2026年最新】