跳到主要内容

GPT-Live 实时语音会话

GPT-Live(gpt-live-1)是全双工实时语音模型:可以边听边说、随时被打断;需要检索或调用工具时,它把工作委托给您的应用或 Responses 模型完成,对话同时继续。图灵平台提供两种传输:浏览器和 App 使用 WebRTC,由您的服务端创建会话、音频直连服务;服务端和设备也可以通过图灵的 WebSocket 收发音频。

完整 schema 与 Try-It

本页说明接入流程、会话控制与计费。请求、响应字段见 API 参考 → Create a GPT-Live WebRTC session 与 Stop a running GPT-Live session。

与 GPT Realtime 的区别

GPT-Live 使用独立的会话协议,接口和事件与 turing/gpt-realtime 系列不通用。GPT Realtime 的用法见 GPT Realtime 使用指南。

接口概览​

项目说明
创建会话(WebRTC)POST /api/v1/live/sessions
WebSocket 会话wss://live-turing.cn.llm.tcljd.com/ws/v1/live/sessions,见WebSocket 传输
停止会话POST /api/v1/live/sessions/{session_id}/close
模型gpt-live-1
传输方式WebRTC:音频走媒体轨,会话事件走名为 oai-events 的 data channel;WebSocket:音频与事件都走同一条连接
委托client(默认)或 responses,见委托
鉴权Authorization: Bearer $TURING_API_KEY,只在服务端使用
计费语音按会话时长 $0.05 / 分钟、按秒计费;Responses 委托另按所用模型计费
支持地区中国区

选择传输方式​

传输适用场景说明
WebRTC浏览器、App延迟最低,浏览器内置回声消除与编解码;媒体直连服务端的 3478 端口(UDP / TCP),需要网络放行
WebSocket您的服务端、设备、封锁 UDP 的网络走 TCP 443,能访问 HTTPS 即可使用;由调用方采集、编码和播放 24 kHz PCM16 音频

两种传输的会话事件、委托、停止接口与计费完全相同。

WebRTC 接入流程​

  1. 浏览器创建 RTCPeerConnection,加入麦克风音轨和名为 oai-events 的 data channel,生成 SDP offer。
  2. 浏览器把 offer 发给您的服务端。
  3. 您的服务端用 Turing API Key 调用创建会话接口,拿到 session.id 与 SDP answer。
  4. 浏览器设置 answer 后,音频在浏览器与 GPT-Live 之间直连,会话事件通过 data channel 收发。
不要在浏览器中使用 Turing API Key

GPT-Live 不提供临时客户端密钥,创建会话必须在持有 API Key 的服务端完成。浏览器只与您的服务端交换 SDP。

浏览器端​

const audioElement = document.querySelector("audio");
const pc = new RTCPeerConnection();
pc.ontrack = (event) => {
audioElement.srcObject = event.streams[0];
};

const microphone = await navigator.mediaDevices.getUserMedia({ audio: true });
pc.addTrack(microphone.getAudioTracks()[0], microphone);

const events = pc.createDataChannel("oai-events");
events.addEventListener("message", ({ data }) => {
const event = JSON.parse(data);
console.log(event.type, event);
});

const offer = await pc.createOffer();
await pc.setLocalDescription(offer);

// 您自己的服务端接口,由它调用 POST /live/sessions(见下一节)
const { session_id, answer_sdp } = await fetch("/your-server/live-session", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ sdp: offer.sdp }),
}).then((response) => response.json());

await pc.setRemoteDescription({ type: "answer", sdp: answer_sdp });

服务端:创建会话​

服务端把浏览器的 SDP offer 连同会话配置发给平台,再把 SDP answer 返回浏览器。请求与响应遵循 GPT-Live WebRTC 协议,平台原样透传。

# OFFER_SDP 为浏览器发给您服务端的 SDP offer
curl "https://live-turing.cn.llm.tcljd.com/api/v1/live/sessions" \
-H "Authorization: Bearer $TURING_API_KEY" \
-H "Content-Type: application/json" \
-d "$(jq -n --arg sdp "$OFFER_SDP" '{
session: {model: "gpt-live-1", instructions: "Be concise.", delegation: {type: "client"}},
transport: {type: "webrtc", sdp: $sdp}
}')"
  • 创建成功返回 201,session.id 用于停止会话和排查问题。
  • 响应头 x-turing-trace-id 是这次会话的追踪 ID,结算后可以用它查询计费(见计费与限额)。
  • session 对象由上游严格校验,包含未知字段的请求会被拒绝。可用字段:model(必填,gpt-live-1)、instructions、audio.output.voice、delegation(见委托)。其中 model、instructions 和音色在会话开始后不可修改。
  • 可选查询参数 idle_timeout_seconds:会话连续这么多秒没有人说话(没有转写事件)时,平台主动关闭会话,例如 POST /api/v1/live/sessions?idle_timeout_seconds=300。不传时使用平台的 1 小时,更大的值也按 1 小时处理。取值必须是正整数,否则返回 400(错误码 1004)。

WebSocket 传输​

连接 wss://live-turing.cn.llm.tcljd.com/ws/v1/live/sessions(也可以用 /api/openai/v1/live/sessions),用请求头 Authorization: Bearer $TURING_API_KEY 鉴权,只在服务端或设备上使用。连接后按 GPT-Live 的 WebSocket 协议收发事件:

  1. 发送 session.start,session 对象与创建 WebRTC 会话时相同;收到 session.started 后会话开始。
  2. 用 session.input_audio.append 发送 base64 编码的 24 kHz 单声道 PCM16 音频,从 session.output_audio.delta 取回模型语音。
  3. 发送 session.close,收到 session.closed 后连接关闭。

握手响应头 x-turing-trace-id 是这次会话的追踪 ID。连接 URL 同样可以带 idle_timeout_seconds(例如 /ws/v1/live/sessions?idle_timeout_seconds=300),规则与 WebRTC 相同。连接时同样会检查预算、限流、同时进行的会话数和 idle_timeout_seconds,不满足时收到错误消息后连接以关闭码 1008 断开。平台拒绝的命令(例如把委托换成不支持的模型)会收到带 client_event_id 的 error 事件,且不会发给上游,会话继续。

import asyncio
import base64
import json
import os

import websockets


async def speak_then_close(ws, audio: str) -> None:
await ws.send(json.dumps({"type": "session.input_audio.append", "audio": audio}))
await asyncio.sleep(10) # 留出时间让模型回答
await ws.send(json.dumps({"type": "session.close"}))


async def main() -> None:
async with websockets.connect(
"wss://live-turing.cn.llm.tcljd.com/ws/v1/live/sessions",
extra_headers={"Authorization": f"Bearer {os.environ['TURING_API_KEY']}"},
) as ws:
print("trace id:", ws.response_headers.get("x-turing-trace-id"))
await ws.send(
json.dumps({"type": "session.start", "session": {"model": "gpt-live-1", "instructions": "Be concise."}})
)
# hello_24khz_mono.pcm:无文件头的 24 kHz 单声道 PCM16 音频
audio = base64.b64encode(open("hello_24khz_mono.pcm", "rb").read()).decode()
async for message in ws:
event = json.loads(message)
if event["type"] == "session.started":
asyncio.ensure_future(speak_then_close(ws, audio))
elif event["type"] == "session.output_audio.delta":
pcm16 = base64.b64decode(event["delta"]) # 交给您的播放器
elif event["type"] == "session.closed":
print("usage:", event["usage"])


asyncio.run(main())

会话事件​

两种传输的常用事件(WebRTC 走 data channel):

事件说明
session.started会话已开始
session.input_transcript.delta / session.output_transcript.delta用户与模型语音的转写片段,按音频节奏分段,不代表完整轮次
session.delegation.created模型把一项工作交给您的应用;完成后用 session.thinking.append 或 session.commentary.append 带上 delegation_id 回填结果
response.eventResponses 委托的事件信封,按内层 event.type 处理,例如 response.output_item.done、response.completed
session.usage.updated累计语音时长(usage.seconds),约每分钟一次;是累计值,不要相加
session.closed会话已结束,带最终 usage.seconds 与结束原因 reason
error启动、校验或命令错误

完整事件定义见 Azure GPT-Live 事件参考。

委托​

对话中需要检索、调用工具或深入推理时,GPT-Live 会把这部分工作委托出去,语音对话同时继续。委托方式在创建会话时通过 session.delegation 指定。

client 委托​

默认方式。data channel 收到 session.delegation.created(target 为 client)后,由您的应用完成工作,再用 session.thinking.append(静默上下文)或 session.commentary.append(让模型说出来)带上 delegation_id 回填结果。平台只按语音时长计费。

Responses 委托​

由 Responses 模型在服务端完成工作:

{
"delegation": {
"type": "responses",
"responses": {
"model": "gpt-6-sol",
"instructions": "Use tools when current information is required.",
"tools": [{ "type": "web_search" }]
}
}
}
  • 可用模型:gpt-6-sol、gpt-6-luna、gpt-6-astra、gpt-5.6-sol、gpt-5.6-terra、gpt-5.6-luna,也接受带 turing/ 前缀的写法。价格见模型列表。
  • 可用工具:function 与 web_search,其他工具类型会被拒绝(400,错误码 1002)。
  • 每次委托运行按所选模型计费,计费方式与调用 /responses 相同:包括缓存 token、web_search 按次计费;service_tier 为 priority 时按 Priority 价格计费,flex 按标准价格计费。
  • 委托的事件包在 response.event 信封里。遇到 function 调用时,从内层 response.output_item.done 取出 call_id 与参数,由您的应用执行,再用 response.item.create 提交 function_call_output,并发送 response.create 继续本轮委托。
  • 会话中途通过 session.update 把委托换成不支持的模型或工具时,平台会立即关闭会话。模型无法识别的委托运行按可用模型中最贵的价格计费。

结束会话​

以下两种方式都可以结束会话,平台随后按上游的最终用量结算:

  • 浏览器在 data channel 发送 {"type": "session.close"}。上游发出 session.closed 后会立即关闭 data channel,这条事件不一定能先送到浏览器,所以收到 session.closed 或 data channel 关闭都表示会话已结束,之后再关闭 RTCPeerConnection。
  • 服务端调用停止接口。会话创建者或管理员可以调用,平台通常在 5 秒内关闭会话。这时浏览器收不到 session.closed,只会看到 data channel 和连接关闭。
curl -X POST "https://live-turing.cn.llm.tcljd.com/api/v1/live/sessions/$SESSION_ID/close" \
-H "Authorization: Bearer $TURING_API_KEY"

停止接口返回 202,data.status 为 closing(已通知关闭,等待上游确认)或 closed(会话已经结束)。

计费与限额​

  • 按语音会话时长计费:$0.05 / 分钟,按秒计。计费时长覆盖整个会话,包括静音和模型处理委托工作的时间。
  • 会话结束后异步结算。用创建会话时返回的 x-turing-trace-id 调用 /trace/{trace_id}/billing,可以查到 gpt-live-1 的计费记录。
  • 会话进行中,上游每次上报累计用量(约每分钟一次)以及每次委托运行结束时,平台会先把这部分费用计入当月花费,会话结束后再结算剩余部分;计费记录仍是整场会话。
  • 上游没有返回最终用量时,平台按会话从创建到结束的时长结算。
  • Responses 委托的每次运行按所选模型另行计费,与语音记录在同一个 trace 中,可以在 /trace/{trace_id}/billing 看到对应模型的计费记录。
  • 创建会话前平台会检查预算与限流(包括委托模型);已超出时返回 429(错误码 1110 / 1104 / 1115),不会创建会话。会话进行中,每次计入花费后平台都按用户当前的额度检查预算,当月预算用完(包括会话期间额度被调低)时主动关闭会话。
  • 每个用户最多同时进行 3 个会话。超出时创建会话返回 429(错误码 1115),WebSocket 连接则收到同一错误码的错误消息后断开;会话结束后名额自动释放。
  • 静音同样计费,因此会话中连续 1 小时没有人说话(没有转写事件)时,平台主动关闭会话;创建会话时可以用 idle_timeout_seconds 设置更短的空闲超时。
  • 单个会话最长约 3 小时 10 分钟(11,400 秒,约 $9.50);单会话费用上限 $10,按语音与委托费用合计。达到任一上限时平台主动关闭会话。单次委托运行在结束后才计入上限,因此最后一次运行可能让会话略超过 $10。
  • 平台主动关闭会话时,WebSocket 调用方会收到 session.closed,WebRTC 浏览器只会看到 data channel 和连接关闭。关闭原因记录在 trace 的 extra_info.gpt_live_terminated_by:max_duration / max_cost(单会话上限)、over_budget(预算用完)、idle(空闲超时)、manual(停止接口)、delegation_policy(委托超出允许范围)。

计费口径与查询方式见 计费与用量。

限制​

  • WebRTC 媒体直连服务端的 3478 端口(UDP / TCP);网络不放行时 data channel 无法建立,请改用 WebSocket 传输。
  • Responses 委托只支持上文列出的模型和 function / web_search 工具。
  • 上游按订阅限制 GPT-Live 的并发会话数,高峰期创建会话可能返回上游的限流错误。

错误处理​

  • 401:缺少或无效的 Turing API Key。
  • 400:委托的模型或工具不受支持(错误码 1002)、委托配置格式错误(错误码 1050),或 idle_timeout_seconds 不是正整数(错误码 1004),不会创建会话。
  • 429:超出预算、限流或同时进行的会话数上限,不会创建会话。
  • 其他 4xx:上游拒绝了请求(例如 SDP 无法解析、会话配置包含未知字段),状态码与错误体原样透传。
  • 停止接口:403 表示只能停止自己创建的会话,404 表示会话不存在或已结算完成。

错误响应中的 trace_id 可用于请求追踪,错误码含义见错误码参考。

相关链接​