选择您的应用使用的 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,每个采样占一个字节。
对原始字节进行 Base64 编码,不要包含 WAV 或其他容器头。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。您可以使用标准 API 密钥对该连接进行身份验证,因为此 Token 只会存在于您的安全后端服务器上。
通过 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 对话指南。