介紹
即時對話透過 WebSocket(一種在用戶端與伺服器端之間保持長連線、可雙向推送資料的協定)建立持久連線,把你的音訊或文字輸入即時送入對話模型,模型再以增量方式推送文字與語音回覆,適合語音助理、即時問答、口語練習等需要來回互動的情境。 它與即時語音轉錄同樣走 WebSocket,但用途不同:
可用模型:
- gpt-realtime-2.1:語音對話模型,支援音訊與文字輸入,即時輸出文字與語音回覆。
快速開始
連線端點
model=gpt-realtime-2.1:必填,模型在連線時由 URL 參數固定,工作階段中不可再更改(見下方約束)。- 注意與轉錄的區別:對話端點不帶
intent=transcription。
鑑權
握手時透過標準 HTTP 標頭傳入金鑰:音訊格式要求
目前音訊輸入與輸出均只支援一種格式,發送前請將音訊轉換為:- 編碼:PCM16(16 位元有符號整數,小端序)
- 取樣率:24000 Hz
- 聲道:單聲道(mono)
audio/pcm@24000。輸入或輸出宣告為其它格式(如 G.711/µ-law)會被拒絕並關閉工作階段。
與轉錄不同,對話工作階段支援語音活動偵測(turn_detection / VAD)。開啟後模型會自動判斷一段話何時結束並觸發回覆;關閉(設為
null)則由你手動控制何時提交音訊、何時請求回覆。二者按需選擇即可。工作階段設定(session.update)
連線建立後,用戶端可發送一幀session.update 設定對話參數(如語音音色、系統指令、是否開啟 VAD)。對話工作階段的模型已由連線 URL 錨定,因此不發送 session.update 也能直接對話;需要自訂音色或指令時再發送。
設定參數
string
必填
工作階段類型,對話情境為
realtime。string
系統指令,用於設定模型角色、語氣與回答約束。
string[]
輸出模態,取值為
["audio"] 或 ["text"]:傳 ["audio"](預設)時模型輸出語音,回覆文字隨 response.output_audio_transcript.delta 事件返回;傳 ["text"] 時只輸出文字,文字隨 response.output_text.delta 事件返回。其它組合(如 ["audio", "text"])會被拒絕並返回 error 事件。object
必填
輸入音訊格式,固定為
{ "type": "audio/pcm", "rate": 24000 }。object | null
語音活動偵測。傳入
{ "type": "server_vad" } 開啟自動斷句;傳入 null 關閉,由用戶端手動提交與請求回覆。object
必填
輸出音訊格式,固定為
{ "type": "audio/pcm", "rate": 24000 }。string
回覆語音的音色。首次回覆開始後不可再更改:工作階段進入產生狀態後,再次發送的
voice 會被忽略(其餘設定正常生效)。因此如需指定音色,請在首次請求回覆前設定。以下能力本期暫不支援,設定後工作階段將被關閉(關閉碼
1008):在工作階段內開啟內嵌轉寫(audio.input.transcription,原因 input_transcription_not_supported)、透過工作階段項目注入音訊(原因 item_audio_not_supported)或圖像(原因 image_input_not_supported)、文字以外的其它內容項目類型(原因 unsupported_content_part)。音訊輸入請統一走 input_audio_buffer.append 通道。發送輸入
發送音訊
將 PCM16 音訊切成小片(如每 100ms 一片),base64 編碼後透過input_audio_buffer.append 事件持續發送:
發送文字
也可以直接注入一則文字訊息,再請求回覆:接收回覆
伺服器端會持續推送事件,關鍵事件類型:event
工作階段建立、設定更新的確認。收到
session.created 後即可開始傳送音訊與文字。event
工作階段項目寫入完成:使用者輸入與模型回覆各產生一條工作階段項目。
event
一輪回覆開始產生。
event
本輪回覆的輸出項目開始、結束。
added 事件裡的 item.id 是後續截斷音訊時要引用的工作階段項目 ID。event
回覆語音的增量片段(base64 編碼的 PCM16 音訊)與結束標記,可邊收邊播。
event
與回覆語音逐句對應的文字稿增量與結束標記,欄位
delta 是本次新增的文字。開啟語音輸出時,回覆文字從這個事件取,可用於邊播語音邊上字幕。event
純文字回覆的增量與結束標記,僅在把輸出模態設為純文字(
output_modalities: ["text"])時出現。event
一輪回覆完成。該事件攜帶本輪的 token 用量(
usage),是計費的依據。event
錯誤事件,包含錯誤碼與說明。請求本身有問題(如
output_modalities 取值非法)時只回一幀 error,工作階段繼續可用;涉及策略(如改模型、餘額耗盡)時關閉工作階段。取回覆文字要認準事件。 預設(輸出含語音)時模型只推
response.output_audio_transcript.delta,不會推 response.output_text.delta;把輸出模態設為純文字後,文字才走 response.output_text.delta。兩種模式都建議一併監聽,避免漏字(見下方執行結果)。打斷與截斷
使用者在模型說話途中開口時,已經產生但還沒播放的內容會與使用者的下一句錯位。WebSocket 連線由用戶端負責播放,打斷後的收尾需要用戶端完成。 開啟 VAD 時,伺服器端偵測到使用者開口後會推送input_audio_buffer.speech_started。用戶端收到該事件後:
- 立即停止本地播放,並記錄這一輪回覆已播放到的位置(毫秒)。
- 傳送
conversation.item.truncate,把未播放的音訊從工作階段中移除,避免下一輪對話裡模型認為這些內容已經說過。
item_id:本輪回覆的工作階段項目 ID,取自response.output_item.added事件的item.id。content_index:音訊內容項目的下標,固定為0。audio_end_ms:保留的音訊長度,單位毫秒,按用戶端實際播放到的位置填寫。
conversation.item.truncated。截斷只影響這一輪回覆的音訊與對應文字稿,工作階段本身不受影響,之後可以繼續下一輪對話。使用 OpenAI SDK 時對應 conn.conversation.item.truncate(item_id=..., content_index=0, audio_end_ms=...)。
關閉 VAD(如按鍵說話)時,按下按鍵即表示打斷:用戶端在按下時傳送 response.cancel 取消進行中的回覆,再按上面的步驟截斷;鬆開按鍵後依序傳送 input_audio_buffer.append、input_audio_buffer.commit 與 response.create。
完整範例
以下給出三種寫法,任選其一:- OpenAI 官方 SDK(推薦):無需手寫 WebSocket,把
websocket_base_url(SDK 的 WebSocket 基底參數)指向閘道即可重用官方函式庫。 - OpenAI Agents SDK:官方 agent 框架的即時語音形態,把
model_config裡的url換成閘道位址即可。 - 原生 websockets:不裝 SDK,直接按協定收發幀,依賴最少、便於排查。
為什麼要在連線時傳模型名? AiHubMix 閘道在 WebSocket 握手那一刻就要用
model 選擇模型推理廠商、鑑權、預留額度,而 session.update 是握手完成之後才到、來不及。所以用 SDK 時要給 connect() 顯式傳 model(SDK 會把它拼進 URL query);缺了它閘道在握手期就會拒絕,連線根本建不起來。與轉錄不同,對話端點不需要 intent=transcription。重用官方範例
OpenAI 官方發布的即時對話範例多數只依賴 SDK 的基底參數,把位址換成 AiHubMix 端點即可重用:執行結果(線上實測)
以下為 OpenAI SDK 範例在aihubmix.com 線上環境(模型 gpt-realtime-2.1)的真實執行結果。工作階段開啟 server_vad,prompt 與語音均為英文。
文字輸入
實測確認:預設(輸出含語音)時回覆文字只從
response.output_audio_transcript.delta 逐字返回,response.output_text.delta 不出現;response.done 攜帶本輪 usage;握手耗時約 2 至 4 秒,為建立工作階段時的額度預留開銷。計費說明
- 按 token 計費:對話工作階段在每輪回覆完成時隨
response.done事件返回本輪 token 用量(usage),據此計費。用量按音訊輸入 / 音訊輸出 / 文字輸入 / 文字輸出等組件分別計量,各組件單價以模型詳情頁即時掛牌價為準。 - 邊用邊結算:這是一條長連線,費用在整個工作階段過程中隨每輪回覆即時扣除,無需等工作階段結束再一次性結算。建立工作階段時會先做一次約 1 分鐘用量的額度預留(僅作准入校驗,不是真實扣費),工作階段結束後釋放剩餘預留。因此帳戶可用餘額至少要夠約 1 分鐘的用量,工作階段才能建立。
- 在用量與帳單的消費明細裡可以逐條查看每次即時對話的計費記錄。
限制與約束
- 單一工作階段時長:一條 WebSocket 連線最長 62 分鐘,到時伺服器端主動關閉(關閉碼
1000,原因session_duration_limit);需要更長請分段重連。 - 空閒斷線:用戶端與模型雙方都沒有活動持續 5 分鐘時,伺服器端關閉工作階段(關閉碼
1008,原因idle_timeout)。任一方有活動都會重置計時,模型持續輸出的長回覆不會因此中斷。 - 餘額不足:建立工作階段時可用餘額不足以覆蓋約 1 分鐘的預留額度,握手直接被拒(HTTP 403),工作階段不會建立;工作階段進行中若餘額耗盡,已建立的連線會被立即關閉。
- 僅伺服器端:不支援瀏覽器直接連線(校驗
Origin標頭),請在伺服器端整合。 - 模型鎖定:模型在連線 URL 固定,工作階段中透過
session.update改模型會被拒絕並關閉工作階段。 - 格式鎖定:音訊輸入與輸出均僅支援
audio/pcm@24000單聲道,其它格式會被拒絕。 - 音色鎖定:
voice在首次回覆開始後不可更改,請在首次請求回覆前設定。 - 暫不支援:工作階段內的內嵌轉寫、透過工作階段項目注入音訊或圖像內容、以及文字以外的其它內容項目類型。
- 單輪回覆:同一工作階段同一時刻只允許一輪進行中的回覆,上一輪未完成時再次傳送
response.create會被拒絕並關閉工作階段(關閉碼1008,原因response_already_active)。
常見錯誤
更新時間:2026-09-21