選擇應用程式使用的 API。每個 API 都有各自的身分驗證方式、工作階段建立流程和事件規範。
將伺服器連接至 GPT-Live
當伺服器擷取音訊或為用戶端轉送音訊串流時,請使用主要 WebSocket 連線。這條連線會雙向傳輸音訊和 JSON 事件。請將專案 API 金鑰保存在該受信任的伺服器上。若要開發瀏覽器或行動應用程式,請先從 WebRTC 開始。
本指南介紹主要音訊連線。側頻連線可讓伺服器監看並控制現有的 Live 工作階段。Responses WebSocket 則將後端連接至 Responses API,以使用推理和工具。這兩種連線都無法取代主要音訊連線。
進行身分驗證並啟動工作階段
- 連接至
wss://api.openai.com/v1/live/sessions,不要附加查詢參數。使用Authorization: Bearer $OPENAI_API_KEY進行身分驗證,並加入範例所示的連線標頭。 - 以
session.start作為第一則訊息傳送。將模型、對話指示、音訊格式、語音和委派組態放在session物件中。 - 等收到
session.started後,再傳送音訊或應用程式指令。該事件包含解析後的工作階段組態和工作階段 ID。
以下範例使用 Marin、24 kHz 的 PCM16 音訊,以及支援網頁搜尋的 Responses 後端。請保持對話指示簡短。如需設定後端指示、工具和工具權限,請參閱委派與工具。
使用 SDK 串流傳輸音訊
若使用 Node.js,請以 npm install openai ws 安裝 openai 和 ws,並將 JavaScript 範例儲存為 client.mjs。若在 macOS 或 Linux 上使用 Python,請安裝 openai[realtime],並將 Python 範例儲存為 client.py。在伺服器環境中設定 OPENAI_API_KEY。這些範例需要支援 Live 的 SDK 版本。範例會從標準輸入讀取 24 kHz 的原始單聲道 PCM16 音訊,並將傳回的音訊以相同格式寫入標準輸出。請將這些串流連接至應用程式的音訊擷取與播放功能。記錄和轉錄事件會寫入標準錯誤輸出,以免破壞音訊串流。
import OpenAI from "openai";
import { LiveWS } from "openai/resources/live/ws";
// stdin and stdout carry raw mono PCM16 audio at 24 kHz, not WAV files.
// Supply microphone bytes continuously and play stdout in the same format.
process.stdin.pause();
const ws = new LiveWS(new OpenAI());
let started = false;
let closing = false;
let finalized = false;
let pendingByte = Buffer.alloc(0);
let closeTimeout;
ws.socket.on("open", () => {
ws.send({
type: "session.start",
event_id: "event_start",
session: {
model: "gpt-live-1",
instructions:
"Be concise. Delegate requests needing current information to the backend, which can search the web.",
audio: {
format: { type: "audio/pcm", rate: 24000 },
output: { voice: "marin" },
},
delegation: {
type: "responses",
responses: {
model: "gpt-5.6-luna",
tools: [{ type: "web_search" }],
tool_choice: "auto",
},
},
},
});
});
process.stdin.on("data", (chunk) => {
if (!started || closing || ws.socket.readyState !== 1) return;
const bytes = Buffer.concat([pendingByte, chunk]);
const completeLength = bytes.length - (bytes.length % 2);
pendingByte = bytes.subarray(completeLength);
if (completeLength) {
ws.send({
type: "session.input_audio.append",
audio: bytes.subarray(0, completeLength).toString("base64"),
});
}
});
// Register the final-event handler before any close command can be sent.
ws.on("event", (event) => {
if (event.type === "session.started") {
started = true;
console.error("Session ready", event.session.id);
process.stdin.resume();
} else if (event.type === "session.output_audio.delta") {
process.stdout.write(Buffer.from(event.delta, "base64"));
} else if (event.type === "session.closed") {
finalized = true;
clearTimeout(closeTimeout);
process.stdin.pause();
console.error("Final session usage", event.usage);
ws.close();
} else {
// Includes transcript deltas and nested response.event usage.
console.error(JSON.stringify(event));
}
});
process.on("SIGINT", () => {
if (closing) return;
if (!started || ws.socket.readyState !== 1) {
ws.socket.platformSocket.terminate();
return;
}
closing = true;
process.stdin.pause();
ws.send({ type: "session.close" });
closeTimeout = setTimeout(() => {
console.error("Incomplete finalization: session.closed was not received");
process.exitCode = 1;
ws.socket.platformSocket.terminate();
}, 15_000);
});
ws.on("error", (error) => {
console.error(error.message);
process.exitCode = 1;
});
ws.socket.on("close", () => {
clearTimeout(closeTimeout);
process.stdin.pause();
if (!finalized) {
console.error("Connection closed without final session usage");
process.exitCode = 1;
}
});連接音訊來源和播放器後,執行 node client.mjs 或 python client.py。出現 Session ready 後,請依錄音取樣率持續提供麥克風串流。透過管線一次傳入整個檔案,無法模擬即時麥克風。音訊來源到達 EOF 並不會結束對話。請向處理程序傳送 SIGINT,要求正常關閉。
此範例會連接音訊串流;應用程式則負責擷取、緩衝、播放,以及必要時的重新取樣。在評估模型行為之前,請先使用自己的裝置和網路測試這些功能。
選擇音訊格式
在啟動時設定 session.audio.format。輸入和輸出共用同一種格式,且在工作階段期間無法變更。
{"type":"audio/pcm","rate":24000}:24 kHz、單聲道、帶正負號的 16 位元小端序 PCM;這是預設格式。{"type":"audio/pcm","rate":16000}:16 kHz、單聲道、帶正負號的 16 位元小端序 PCM。{"type":"audio/pcmu","rate":8000}:8 kHz 的 G.711 μ-law,每個樣本占一個位元組。{"type":"audio/pcma","rate":8000}:8 kHz 的 G.711 A-law,每個樣本占一個位元組。
請對不含 WAV 或其他容器標頭的原始位元組進行 Base64 編碼。PCM 區塊必須包含完整的 16 位元樣本,因此位元組長度必須是偶數。範例會將末尾剩餘的一個位元組保留至下一個輸入區塊。除此之外,區塊邊界可以任意劃分,只要串流保持連續且順序正確即可。
當音訊取樣率與設定的取樣率不同時,請重新取樣。變更格式設定不會轉換輸入位元組。若要將範例調整為使用 G.711,請轉送各區塊的編碼位元組,不要套用 PCM 專用的雙位元組對齊邏輯,並將輸出播放器設定為使用相同的編解碼器。格式相符的 G.711 串流可以直接傳遞,無須轉換為 PCM。如需連接電話通話,請參閱電話整合。
傳送與接收事件
將每個事件以 JSON 文字訊息傳送。音訊會以 base64 編碼放在這些訊息中傳輸。
- 傳送音訊: 傳送
session.input_audio.append,並在audio中放入經 base64 編碼的原始位元組。附加音訊不會收到確認回覆。 - 接收音訊: 解碼每個
session.output_audio.delta事件中的delta,並依序將音訊加入播放佇列,以設定的格式播放。 - 接收轉錄文字: 將
session.input_transcript.delta和session.output_transcript.delta中delta的文字附加至對應的轉錄文字。 - 接收後端事件: 使用 Responses 委派時,請處理每個
response.event封套中巢狀的event。 - 處理錯誤: 根據
error事件處理遭拒的指令和工作階段錯誤。若事件中包含error.client_event_id,可用它識別對應的指令。
輸出音訊事件沒有時間資訊欄位,GPT-Live 也不會發出 output-audio-done 事件。請追蹤播放佇列,以掌握已接收的音訊中有哪些已經播放。轉錄文字的時間戳記描述的是工作階段時間軸上的區間,並不表示音訊播放完畢。後端回應完成,也不代表助理已經說完話。
GPT-Live 會在音訊串流傳輸期間管理聆聽和說話的時機。它不使用 Realtime 透過提交輸入緩衝區和 response.create 來進行的語音輪次循環。在 Live 中,response.create 用於啟動或繼續已委派的後端工作。如需瞭解此工作流程,請參閱委派與工具。
設定進行中的工作階段
Live 模型、初始對話指示、音訊格式、語音和委派模式都在啟動時固定。請使用 session.update 調整現有委派模式支援的設定;未指定的設定會保留目前的值。更新成功時會傳回 session.updated,其中包含解析後的工作階段組態。
使用 session.instructions.append 新增對話指示,並使用 session.input_audio.mute 或 session.input_audio.unmute 控制傳入的音訊。將輸入靜音不會取消後端工作,也不會停止已生成的語音。如需瞭解上下文更新、轉錄文字、輸入控制和用量,請參閱管理工作階段。
關閉工作階段
對話結束時,傳送 session.close。請先註冊 session.closed 監聽器,持續接收直到該事件到達,再釋放連線。範例最多等待 15 秒;如果始終未收到終止事件,便會回報結束程序未完成。
保留 session.closed 中的最終語音用量,以及已收到的後端用量事件。語音時長更新是累計值的快照,請勿將它們相加。若在收到 session.closed 之前發生傳輸失敗或逾時,最終用量便無法確認。如需瞭解完整生命週期,請參閱管理工作階段。
WebSockets 是廣泛受到支援的即時資料傳輸 API,非常適合用於在伺服器對伺服器的應用程式中連接 OpenAI Realtime API。對於瀏覽器和行動用戶端,我們建議透過 WebRTC 連線。
與 Realtime 進行伺服器對伺服器的整合時,後端系統會透過 WebSocket 直接連接至 Realtime API。由於 Token 只會存放在安全的後端伺服器上,因此可以使用標準 API 金鑰來驗證此連線。
透過 WebSocket 連線
以下提供幾個透過 WebSocket 連接至 Realtime API 的範例。除了使用下方的 WebSocket URL,您還需要傳入含有 OpenAI API 金鑰的身分驗證標頭。如果應用程式會指派安全識別碼,請在 OpenAI-Safety-Identifier 標頭中傳入終端使用者的固定識別碼,且該識別碼須能保護隱私。
您可以按照 WebRTC 連線指南所示,在瀏覽器中使用短效 API Token 建立 WebSocket 連線。不過,若從瀏覽器或行動應用程式等用戶端連線,WebRTC 在多數情況下會是更穩健的解決方案。
import WebSocket from "ws";
const url = "wss://api.openai.com/v1/realtime?model=gpt-realtime-2.1";
const ws = new WebSocket(url, {
headers: {
Authorization: "Bearer " + process.env.OPENAI_API_KEY,
"OpenAI-Safety-Identifier": "hashed-user-id",
},
});
ws.on("open", function open() {
console.log("Connected to server.");
});
ws.on("message", function incoming(message) {
console.log(JSON.parse(message.toString()));
});# example requires websocket-client library:
# pip install websocket-client
import os
import json
import websocket
OPENAI_API_KEY = os.environ["OPENAI_API_KEY"]
url = "wss://api.openai.com/v1/realtime?model=gpt-realtime-2.1"
headers = [
"Authorization: Bearer " + OPENAI_API_KEY,
"OpenAI-Safety-Identifier: hashed-user-id",
]
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()使用以下指令安裝所需的 gem:
gem install openai async-websocket。
require "openai"
client = OpenAI::Client.new(
default_headers: { "OpenAI-Safety-Identifier" => "hashed-user-id" }
)
client.realtime.connect(model: "gpt-realtime-2.1") do |connection|
puts("Connected to the Realtime API: #{connection.url.host}")
connection.each { |event| puts("Received event: #{event.type}") }
end/*
Note that in client-side environments like web browsers, we recommend
using WebRTC instead. It is possible, however, to use the standard
WebSocket interface in browser-like environments like Deno and
Cloudflare Workers.
*/
const ws = new WebSocket(
"wss://api.openai.com/v1/realtime?model=gpt-realtime-2.1",
[
"realtime",
// Use a short-lived token fetched from your application server.
"openai-insecure-api-key." + OPENAI_REALTIME_EPHEMERAL_KEY,
// Optional
"openai-organization." + OPENAI_ORG_ID,
"openai-project." + OPENAI_PROJECT_ID,
]
);
ws.addEventListener("open", function open() {
console.log("Connected to server.");
});
ws.addEventListener("message", function incoming(event) {
console.log(event.data);
});傳送與接收事件
Realtime API 工作階段透過兩類事件共同管理:一類是由你這位開發人員發出的用戶端事件,另一類是由 Realtime API 產生、用來表示工作階段生命週期事件的伺服器事件。
透過 WebSocket 傳送與接收事件時,事件會序列化為 JSON,並以文字字串的形式傳輸,如下方的 Node.js 範例所示(其他 WebSocket 程式庫也適用相同原則):
import WebSocket from "ws";
const url = "wss://api.openai.com/v1/realtime?model=gpt-realtime-2.1";
const ws = new WebSocket(url, {
headers: {
Authorization: "Bearer " + process.env.OPENAI_API_KEY,
"OpenAI-Safety-Identifier": "hashed-user-id",
},
});
ws.on("open", function open() {
console.log("Connected to server.");
// Send client events over the WebSocket once connected
ws.send(
JSON.stringify({
type: "session.update",
session: {
type: "realtime",
instructions: "Be extra nice today!",
},
})
);
});
// Listen for and parse server events
ws.on("message", function incoming(message) {
console.log(JSON.parse(message.toString()));
});WebSocket 介面可能是目前可用來與 Realtime 模型互動的最底層介面。使用此介面時,你需要自行負責透過通訊端連線傳送及處理 Base64 編碼的音訊區塊。
若要瞭解如何透過 Websockets 傳送與接收音訊,請參閱 Realtime 對話指南。