实时交互
通过 Realtime WebSocket 处理实时文本、音频与函数调用。
OpenAI Realtime 使用持久连接和双向事件处理实时文本、音频与函数调用。客户端发送会话、音频缓冲区、对话项和响应控制事件,服务端持续返回会话状态、转写、文本、音频、函数参数和错误事件。
本页以 WebSocket 作为主要连接方式。连接时请将 MODEL_ID 替换为当前账户可见且支持 Realtime 的模型 ID。
典型场景包括实时语音对话、会议实时转写与语音助手、实时翻译、语音转写、实时代码交互以及服务端实时集成。连接可同时承载文本与音频,并通过事件处理 VAD、函数调用和状态更新。
wss://api.agtcloud.cn/v1/realtime?model=MODEL_ID认证与连接
WebSocket 认证
服务端应用通过 Bearer API Key 建立 WSS 连接,并在握手请求中携带 Realtime Beta Header。
| 项目 | 值 |
|---|---|
| 连接地址 | wss://api.agtcloud.cn/v1/realtime?model=MODEL_ID |
| Authorization | Bearer your-api-key |
| OpenAI-Beta | realtime=v1 |
长期 API Key 只应在可信服务端使用,不要把它写入浏览器、移动端包或公开仓库。所有连接都应使用 HTTPS/WSS。
临时令牌
客户端连接时,可先由可信服务端创建有效期为一分钟、仅用于单个连接的临时令牌。
POST https://api.agtcloud.cn/v1/realtime/sessions
Content-Type: application/json
Authorization: Bearer your-api-key
{
"model": "MODEL_ID",
"voice": "verse"
}连接流程
WebSocket 主流程由服务端直接使用 API Key 建立连接,握手成功后在同一连接中发送客户端事件并接收服务端事件。
WebRTC 流程则由客户端先向自己的应用服务器请求临时令牌,应用服务器调用会话接口创建令牌;客户端随后生成 SDP Offer、提交至 Realtime 端点并接收 SDP Answer,最后通过 oai-events 数据通道交换 JSON 事件。
WebSocket 连接示例
下面的示例分别展示 Node.js、Python、事件发送和事件接收。建立连接后,客户端发送 JSON 事件,服务端也以 JSON 事件持续返回结果。
import WebSocket from 'ws';
const ws = new WebSocket('wss://api.agtcloud.cn/v1/realtime?model=MODEL_ID', {
headers: {
Authorization: 'Bearer your-api-key',
'OpenAI-Beta': 'realtime=v1',
},
});
ws.on('open', () => {
console.log('Connected to server.');
});
ws.on('message', (message) => {
console.log(JSON.parse(message.toString()));
});WebRTC 接入说明
当前推荐使用 WebSocket。使用 WebRTC 前,请先确认目标模型是否支持;以下示例说明临时令牌、SDP、音频轨道和数据通道的基本连接结构。
WebRTC 连接地址为 https://api.agtcloud.cn/v1/realtime?model=MODEL_ID。客户端使用临时令牌提交 application/sdp,数据通道名称为 oai-events,事件格式为 JSON;输入音频通过 addTrack() 发送,输出音频通过 ontrack 接收。
浏览器客户端与 SDP 交换
async function init() {
const tokenResponse = await fetch('/session');
const data = await tokenResponse.json();
const ephemeralKey = data.client_secret.value;
const pc = new RTCPeerConnection();
const audioElement = document.createElement('audio');
audioElement.autoplay = true;
pc.ontrack = (event) => {
audioElement.srcObject = event.streams[0];
};
const mediaStream = await navigator.mediaDevices.getUserMedia({ audio: true });
pc.addTrack(mediaStream.getTracks()[0]);
const dataChannel = pc.createDataChannel('oai-events');
dataChannel.addEventListener('message', (event) => {
console.log(JSON.parse(event.data));
});
const offer = await pc.createOffer();
await pc.setLocalDescription(offer);
const response = await fetch(
'https://api.agtcloud.cn/v1/realtime?model=MODEL_ID',
{
method: 'POST',
body: offer.sdp,
headers: {
Authorization: `Bearer ${ephemeralKey}`,
'Content-Type': 'application/sdp',
},
},
);
await pc.setRemoteDescription({
type: 'answer',
sdp: await response.text(),
});
}
init();服务端创建临时令牌
import express from 'express';
const app = express();
app.get('/session', async (_request, response) => {
const result = await fetch('https://api.agtcloud.cn/v1/realtime/sessions', {
method: 'POST',
headers: {
Authorization: 'Bearer your-api-key',
'Content-Type': 'application/json',
},
body: JSON.stringify({
model: 'MODEL_ID',
voice: 'verse',
}),
});
response.send(await result.json());
});
app.listen(3000);数据通道事件收发
const dataChannel = pc.createDataChannel('oai-events');
dataChannel.addEventListener('message', (event) => {
const realtimeEvent = JSON.parse(event.data);
console.log(realtimeEvent);
});
dataChannel.send(JSON.stringify({
type: 'response.create',
response: {
modalities: ['text'],
instructions: 'Write a haiku about code',
},
}));类浏览器运行时的标准 WebSocket 示例
Deno、Cloudflare Workers 等类浏览器运行时可通过子协议传递认证信息。使用前请确认当前运行时和节点是否支持;不建议在普通浏览器页面中放置长期 API Key。
const ws = new WebSocket(
'wss://api.agtcloud.cn/v1/realtime?model=MODEL_ID',
[
'realtime',
'openai-insecure-api-key.your-api-key',
'openai-organization.ORGANIZATION_ID',
'openai-project.PROJECT_ID',
'openai-beta.realtime-v1',
],
);
ws.addEventListener('open', () => {
console.log('Connected to server.');
});
ws.addEventListener('message', (event) => {
console.log(JSON.parse(event.data));
});会话、音频与对话
Realtime 支持纯文本、语音以及文本与音频混合对话。会话配置可以包含输入和输出音频格式、语音、温度、最大输出长度、工具以及 VAD 参数。
- 输入与输出音频格式:
pcm16、g711_ulaw、g711_alaw。 - 示例语音选项:
alloy、echo、shimmer。 - VAD 配置包括阈值、语音前缀填充和静音持续时间。
- 对话由会话、对话项、内容部分和响应事件共同推进。
具体事件字段请在下方事件浏览器中查看;复用的参数和值域集中列在“公共类型”。
事件 Reference
选择事件以查看字段定义和 JSON 示例。可以切换事件方向、按类别筛选或搜索事件名称。
session.update
更新会话的默认配置。
| 字段 | 类型 | 必填 | 说明 | 示例值 |
|---|---|---|---|---|
event_id | 字符串 | 否 | 客户端生成的事件标识符 | event_123 |
type | 字符串 | 否 | 事件类型 | session.update |
modalities | 字符串数组 | 否 | 模型可以响应的模态类型 | ["text", "audio"] |
instructions | 字符串 | 否 | 预置到模型调用前的系统指令 | "请用简洁、准确的语言回答。" |
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 | 字符串/整数 | 否 | 单次响应最大token数 | "inf"/4096 |
{
"event_id": "event_123",
"type": "session.update",
"modalities": [
"text",
"audio"
],
"instructions": "请用简洁、准确的语言回答。",
"voice": "alloy",
"input_audio_format": "pcm16",
"output_audio_format": "pcm16",
"input_audio_transcription": {
"model": "whisper-1"
},
"turn_detection": {
"type": "server_vad",
"threshold": 0.8,
"prefix_padding_ms": 500,
"silence_duration_ms": 1000
},
"tools": [],
"tool_choice": "auto",
"temperature": 0.8,
"max_output_tokens": "inf"
}公共类型
以下折叠区汇总速率限制、函数调用、音频、VAD、工具、模型、事件、会话、对话项、内容、响应、转写、音频流和 WebRTC 参数表。
速率限制事件4 个字段
| 字段 | 类型 | 必填 | 说明 | 可选值或示例 |
|---|---|---|---|---|
name | 字符串 | 是 | 限制名称 | 示例值:requests_per_min |
limit | 整数 | 是 | 限制值 | 示例值:60 |
remaining | 整数 | 是 | 剩余可用量 | 示例值:45 |
reset_seconds | 整数 | 是 | 重置时间(秒) | 示例值:35 |
函数调用4 个字段
| 字段 | 类型 | 必填 | 说明 | 可选值或示例 |
|---|---|---|---|---|
type | 字符串 | 是 | 函数类型 | 示例值:function |
name | 字符串 | 是 | 函数名称 | 示例值:get_weather |
description | 字符串 | 否 | 函数描述 | 示例值:Get the current weather |
parameters | 对象 | 是 | 函数参数定义 | 示例值:{"type": "object", "properties": {...}} |
音频格式4 个字段
| 字段 | 类型 | 必填 | 说明 | 可选值或示例 |
|---|---|---|---|---|
sample_rate | 整数 | — | 采样率 | 可选值:8000, 16000, 24000, 44100, 48000 |
channels | 整数 | — | 声道数 | 可选值:1 (单声道), 2 (立体声) |
bits_per_sample | 整数 | — | 采样位数 | 可选值:16 (pcm16), 8 (g711) |
encoding | 字符串 | — | 编码方式 | 可选值:pcm16, g711_ulaw, g711_alaw |
语音检测3 个字段
| 字段 | 类型 | 必填 | 说明 | 可选值或示例 |
|---|---|---|---|---|
threshold | 浮点数 | — | VAD 激活阈值 | 默认值:0.5;范围:0.0-1.0 |
prefix_padding_ms | 整数 | — | 语音前缀填充(毫秒) | 默认值:500;范围:0-5000 |
silence_duration_ms | 整数 | — | 静音检测时长(毫秒) | 默认值:1000;范围:100-10000 |
工具选择2 个字段
| 字段 | 类型 | 必填 | 说明 | 可选值或示例 |
|---|---|---|---|---|
tool_choice | 字符串 | — | 工具选择方式 | 可选值:auto, none, required |
tools | 数组 | — | 可用工具列表 | 可选值:[{type, name, description, parameters}] |
模型配置4 个字段
| 字段 | 类型 | 必填 | 说明 | 可选值或示例 |
|---|---|---|---|---|
temperature | 浮点数 | — | 采样温度 | 范围/可选值:0.0-2.0;默认值:1.0 |
max_output_tokens | 整数/字符串 | — | 最大输出长度 | 范围/可选值:1-4096/"inf";默认值:"inf" |
modalities | 字符串数组 | — | 响应模态 | 范围/可选值:["text", "audio"];默认值:["text"] |
voice | 字符串 | — | 语音类型 | 范围/可选值:alloy, echo, shimmer;默认值:alloy |
事件通用3 个字段
| 字段 | 类型 | 必填 | 说明 | 可选值或示例 |
|---|---|---|---|---|
event_id | 字符串 | 是 | 事件的唯一标识符 | 示例值:event_123 |
type | 字符串 | 是 | 事件类型 | 示例值:session.update |
timestamp | 整数 | 否 | 事件发生的时间戳(毫秒) | 示例值:1677649363000 |
会话状态3 个字段
| 字段 | 类型 | 必填 | 说明 | 可选值或示例 |
|---|---|---|---|---|
status | 字符串 | — | 会话状态 | 可选值:active, ended, error |
error | 对象 | — | 错误信息 | 可选值:{"type": "error_type", "message": "error message"} |
metadata | 对象 | — | 会话元数据 | 可选值:{"client_id": "web", "session_type": "chat"} |
对话项状态3 个字段
| 字段 | 类型 | 必填 | 说明 | 可选值或示例 |
|---|---|---|---|---|
status | 字符串 | — | 对话项状态 | 可选值:completed, in_progress, incomplete |
role | 字符串 | — | 发送者角色 | 可选值:user, assistant, system |
type | 字符串 | — | 对话项类型 | 可选值:message, function_call, function_call_output |
内容类型3 个字段
| 字段 | 类型 | 必填 | 说明 | 可选值或示例 |
|---|---|---|---|---|
type | 字符串 | — | 内容类型 | 可选值:text, audio, transcript |
format | 字符串 | — | 内容格式 | 可选值:plain, markdown, html |
encoding | 字符串 | — | 编码方式 | 可选值:utf-8, base64 |
响应状态3 个字段
| 字段 | 类型 | 必填 | 说明 | 可选值或示例 |
|---|---|---|---|---|
status | 字符串 | — | 响应状态 | 可选值:completed, cancelled, failed, incomplete |
status_details | 对象 | — | 状态详情 | 可选值:{"reason": "user_cancelled"} |
usage | 对象 | — | 使用统计 | 可选值:{"total_tokens": 50, "input_tokens": 20, "output_tokens": 30} |
音频转写4 个字段
| 字段 | 类型 | 必填 | 说明 | 可选值或示例 |
|---|---|---|---|---|
enabled | 布尔值 | — | 是否启用转写 | 示例值:true |
model | 字符串 | — | 转写模型 | 示例值:whisper-1 |
language | 字符串 | — | 转写语言 | 示例值:en, zh, auto |
prompt | 字符串 | — | 转写提示词 | 示例值:"Transcript of a conversation" |
音频流3 个字段
| 字段 | 类型 | 必填 | 说明 | 可选值或示例 |
|---|---|---|---|---|
chunk_size | 整数 | — | 音频块大小(字节) | 可选值:1024, 2048, 4096 |
latency | 字符串 | — | 延迟模式 | 可选值:low, balanced, high |
compression | 字符串 | — | 压缩方式 | 可选值:none, opus, mp3 |
WebRTC 配置3 个字段
| 字段 | 类型 | 必填 | 说明 | 可选值或示例 |
|---|---|---|---|---|
ice_servers | 数组 | — | ICE 服务器列表 | 默认值:[{"urls": "stun:stun.l.google.com:19302"}] |
audio_constraints | 对象 | — | 音频约束 | 默认值:{"echoCancellation": true} |
connection_timeout | 整数 | — | 连接超时(毫秒) | 默认值:30000 |
错误处理与恢复
Realtime 错误通常来自连接、认证、音频或会话四类问题:
| 类型 | 常见原因 | 处理方向 |
|---|---|---|
| 连接错误 | 网络中断、握手失败或连接配置错误 | 检查 WSS 地址、网络和握手请求,按有限次数重连 |
| 认证错误 | API Key 无效、临时令牌过期或与 API 地址不匹配 | 更新凭证,并确保 API Key 与请求使用的 API 地址匹配 |
| 音频错误 | 设备权限、格式不支持或编解码不匹配 | 检查设备权限、采样与编码设置,再重新建立音频链路 |
| 会话错误 | 会话超时、并发限制或事件状态不一致 | 保存错误事件,重新建立会话,必要时降级到非实时接口 |
恢复策略可以包括自动重连、会话恢复、有限重试和功能降级。发生错误时,应优先读取 error 事件,保存其 event_id、error.type、error.code、error.message 和关联事件信息,再决定是否重发。