通过 WebRTC 或 WebSocket 连接到 Realtime API 后,您就可以调用实时模型(例如 gpt-realtime-2.1)进行语音到语音对话。为此,您需要 发送客户端事件 来发起操作,并 监听服务器事件 ,以响应 Realtime API 执行的操作。
本指南将介绍使用音频和文本生成、图像输入、函数调用等模型能力所需的事件流程,以及如何理解实时会话的状态。
如果您不需要与模型对话,也就是说不期望模型返回任何响应, 可以在转录 模式下使用 Realtime API。
实时语音到语音会话
实时会话是模型与已连接的客户端之间的有状态交互。会话的主要组成部分包括:
- 会话 对象,用于控制交互参数,例如所用的模型、生成输出时使用的音色以及其他配置。
- 对话,表示当前会话期间产生的用户输入条目和模型输出条目。
- 响应,即模型生成并添加到对话中的音频或文本条目。
输入音频缓冲区与 WebSockets
如果您使用 WebRTC,向模型发送音频和接收模型音频所需的大部分媒体处理工作都由 WebRTC API 协助完成。
如果您使用 WebSockets 处理音频,则需要通过包含 base64 编码音频的 JSON 事件向服务器发送音频,手动与 输入音频缓冲区 交互。
这些组件共同构成一个实时会话。您将使用客户端事件更新会话状态,并监听服务器事件,以便对会话中的状态变化作出响应。
会话生命周期事件
通过 WebRTC 或 WebSockets 启动会话后,服务器会发送 session.created 事件,表示会话已就绪。在客户端,您可以通过 session.update 事件更新当前会话配置。大多数会话属性都可以随时更新,但模型在会话中首次以音频响应后,就不能再更改用于音频输出的 voice。实时会话的最长持续时间为 60 分钟。
以下示例展示了如何使用 session.update 客户端事件更新会话。有关通过这些通道发送客户端事件的更多信息,请参阅 WebRTC 或 WebSocket 指南。
const event = {
type: "session.update",
session: {
type: "realtime",
model: "gpt-realtime-2.1",
// Lock the output to audio (set to ["text"] if you want text without audio)
output_modalities: ["audio"],
audio: {
input: {
format: {
type: "audio/pcm",
rate: 24000,
},
turn_detection: {
type: "semantic_vad",
},
},
output: {
format: {
type: "audio/pcm",
},
voice: "marin",
},
},
// Use a server-stored prompt by ID. Optionally pin a version and pass variables.
prompt: {
id: "pmpt_123", // your stored prompt ID
version: "89", // optional: pin a specific version
variables: {
city: "Paris", // example variable used by your prompt
},
},
// You can still set direct session fields; these override prompt fields if they overlap:
instructions:
"Speak clearly and briefly. Confirm understanding before taking actions.",
},
};
// WebRTC data channel and WebSocket both have .send()
dataChannel.send(JSON.stringify(event));会话更新后,服务器会发出 session.updated 事件,其中包含会话的新状态。
| 相关客户端事件 | 相关服务器事件 |
|---|---|
文本输入和输出
要使用实时模型生成文本,您可以向当前对话添加文本输入,请求模型生成响应,并监听服务器发送的事件以了解模型响应的生成进度。要生成文本,必须将会话配置为支持 text 模态(默认已启用)。
使用 conversation.item.create 客户端事件创建新的文本对话条目。这类似于在 REST API 中通过 Chat Completions 发送用户消息(提示)。
const event = {
type: "conversation.item.create",
item: {
type: "message",
role: "user",
content: [
{
type: "input_text",
text: "What Prince album sold the most copies?",
},
],
},
};
// WebRTC data channel and WebSocket both have .send()
dataChannel.send(JSON.stringify(event));将用户消息添加到对话后,发送 response.create 事件以触发模型响应。如果当前会话同时启用了音频和文本,模型的响应将同时包含音频和文本内容。如果您只想生成文本,可以在发送 response.create 客户端事件时指定,如下所示。
const event = {
type: "response.create",
response: {
output_modalities: ["text"],
},
};
// WebRTC data channel and WebSocket both have .send()
dataChannel.send(JSON.stringify(event));响应完全生成后,服务器会发出 response.done 事件。此事件将包含模型生成的完整文本,如下所示。
function handleEvent(message) {
const data = "data" in message ? message.data : message.toString();
const serverEvent = JSON.parse(data);
if (serverEvent.type === "response.done") {
console.log(serverEvent.response.output[0]);
}
}
// Listen for server messages (WebRTC)
dataChannel.addEventListener("message", handleEvent);
// Listen for server messages (WebSocket)
// ws.on("message", handleEvent);在模型生成响应的过程中,服务器会发出多个生命周期事件。您可以监听这些事件,例如 response.output_text.delta,在响应生成期间向用户提供实时反馈。服务器发出的完整事件列表见下方的 相关服务器事件。这些事件大致按发出顺序排列,同时列出了与文本生成相关的客户端事件。
| 相关客户端事件 | 相关服务器事件 |
|---|---|
音频输入和输出
Realtime API 最强大的功能之一是可以直接与模型进行语音交互,无需经过文本转语音或语音转文本的中间步骤。这可以降低语音界面的延迟,同时让模型获得更多语音输入中的语气和语调信息。
音色选项
您可以为实时会话配置多种内置音色之一,用于生成音频输出。在创建会话时(或在 response.create 中),您可以设置 voice 来控制模型的声音。目前可选的音色包括 alloy、ash、ballad、coral、echo、sage、shimmer、verse、marin 和 cedar。一旦模型在会话中输出了音频,就无法再修改该会话的 voice。为获得最佳质量,我们建议使用 marin 或 cedar。
使用 WebRTC 处理音频
如果您使用 WebRTC 连接到 Realtime API,Realtime API 就会与您的客户端建立对等连接。模型的音频输出以远程媒体流的形式传送到客户端。输入模型的音频通过音频设备采集(getUserMedia),媒体流则以轨道的形式添加到对等连接中。
WebRTC 连接指南中的示例代码展示了如何使用浏览器 API 对本地和远程音频进行基本配置:
// Create a peer connection
const pc = new RTCPeerConnection();
// Set up to play remote audio from the model
const audioEl = document.createElement("audio");
audioEl.autoplay = true;
pc.ontrack = (e) => (audioEl.srcObject = e.streams[0]);
// Add local audio track for microphone input in the browser
const ms = await navigator.mediaDevices.getUserMedia({
audio: true,
});
pc.addTrack(ms.getTracks()[0]);上述代码片段可以实现与 Realtime API 的交互,您还可以在此基础上实现更多功能。如需了解不同类型用户界面的更多示例,请查看 WebRTC 示例代码仓库。您也可以在此查看这些示例的在线演示。
在浏览器中使用媒体捕获和流功能,您可以将麦克风静音或取消静音、选择用于采集输入的设备等。
WebRTC 中的音频客户端和服务器事件
默认情况下,WebRTC 客户端在发送音频输入之前,无需向 Realtime API 发送任何客户端事件。将本地音轨添加到对等连接后,您的用户就可以直接开始说话了!
不过,当音频通过对等连接在客户端与服务器之间双向传输时,WebRTC 客户端仍会收到服务器发送的多个生命周期事件。例如:
- 通过本地媒体轨道发送输入时,您会收到服务器发送的
input_audio_buffer.speech_started事件。 - 本地音频输入停止时,您会收到
input_audio_buffer.speech_stopped事件。 - 您会收到正在生成的音频转录文本的增量事件。
- 模型完成转录并发送完响应后,您会收到
response.done事件。
通过 WebRTC API 操作媒体流,可能就能满足您所有的控制需求。不过,有时您可能需要使用更底层的接口来处理音频输入和输出。请参阅下方的 WebSockets 部分,了解更多信息,以及精细处理音频输入所需的事件列表。
使用 WebSockets 处理音频
通过 WebSocket 发送和接收音频时,您需要完成更多工作,才能从客户端发送媒体并接收服务器返回的媒体。下表介绍了 WebSocket 会话中通过 WebSocket 收发音频所需的事件流程。
以下事件按生命周期顺序列出,但某些事件(例如 delta 事件)可能会并发发生。
| 生命周期阶段 | 客户端事件 | 服务器事件 |
|---|---|---|
| 会话初始化 | ||
| 用户音频输入 | (发送完整的音频消息) (分块流式传输音频) (禁用 VAD 时使用) (禁用 VAD 时使用) |
|
| 服务器音频输出 | (禁用 VAD 时使用) |
|
向服务器流式传输音频输入
要向服务器流式传输音频输入,您可以使用 input_audio_buffer.append 客户端事件。此事件要求您通过套接字向 Realtime API 分块发送 经过 Base64 编码的音频字节 。每个数据块的大小不得超过 15 MB。
您可以为整个会话统一配置输入数据块的格式,也可以针对每个响应单独配置。
- 会话:
session.update中的session.input_audio_format - 响应:
response.create中的response.input_audio_format
import fs from "fs";
import decodeAudio from "audio-decode";
// Converts Float32Array of audio data to PCM16 ArrayBuffer
function floatTo16BitPCM(float32Array) {
const buffer = new ArrayBuffer(float32Array.length * 2);
const view = new DataView(buffer);
let offset = 0;
for (let i = 0; i < float32Array.length; i++, offset += 2) {
let s = Math.max(-1, Math.min(1, float32Array[i]));
view.setInt16(offset, s < 0 ? s * 0x8000 : s * 0x7fff, true);
}
return buffer;
}
// Converts a Float32Array to base64-encoded PCM16 data
function base64EncodeAudio(float32Array) {
const arrayBuffer = floatTo16BitPCM(float32Array);
let binary = "";
let bytes = new Uint8Array(arrayBuffer);
const chunkSize = 0x8000; // 32KB chunk size
for (let i = 0; i < bytes.length; i += chunkSize) {
let chunk = bytes.subarray(i, i + chunkSize);
binary += String.fromCharCode(...chunk);
}
return btoa(binary);
}
// Fills the audio buffer with the contents of three files,
// then asks the model to generate a response.
const files = [
"fixtures/sample1.wav",
"fixtures/sample2.wav",
"fixtures/sample3.wav",
];
for (const filename of files) {
const audioFile = fs.readFileSync(filename);
const audioBuffer = await decodeAudio(audioFile);
const channelData = audioBuffer.channelData[0];
const base64Chunk = base64EncodeAudio(channelData);
ws.send(
JSON.stringify({
type: "input_audio_buffer.append",
audio: base64Chunk,
})
);
}
ws.send(JSON.stringify({ type: "input_audio_buffer.commit" }));
ws.send(JSON.stringify({ type: "response.create" }));发送完整的音频消息
您也可以使用完整的录音创建对话消息。使用 conversation.item.create 客户端事件创建包含 input_audio 内容的消息。
const fullAudio = "<a base64-encoded string of audio bytes>";
const event = {
type: "conversation.item.create",
item: {
type: "message",
role: "user",
content: [
{
type: "input_audio",
audio: fullAudio,
},
],
},
};
// WebRTC data channel and WebSocket both have .send()
dataChannel.send(JSON.stringify(event));处理通过 WebSocket 接收的音频输出
要在网页浏览器等客户端上播放输出音频,我们建议使用 WebRTC,而非 WebSockets。在网络状况不稳定时,WebRTC 能更可靠地向客户端设备发送媒体。
但如果您要在服务器间通信的应用中使用 WebSocket 处理音频输出,就需要监听 response.output_audio.delta 事件,其中包含模型生成的、经过 Base64 编码的音频数据块。您需要缓冲这些数据块并将其写入文件,或者立即将其流式传输到其他目标,例如 Twilio 电话通话。
请注意,response.output_audio.done 和 response.done 事件实际上不包含音频数据,只包含音频内容的转录文本。要获取实际的字节数据,您需要监听 response.output_audio.delta 事件。
您可以为整个会话统一配置输出数据块的格式,也可以针对每个响应单独配置。
- 会话:
session.update中的session.audio.output.format - 响应:
response.create中的response.audio.output.format
function handleEvent(message) {
const serverEvent = JSON.parse(message.toString());
if (serverEvent.type === "response.output_audio.delta") {
// Access Base64-encoded audio chunks
// console.log(serverEvent.delta);
}
}
// Listen for server messages (WebSocket)
ws.on("message", handleEvent);图像输入
gpt-realtime-2 和 gpt-realtime 也支持图像输入。您可以将图像作为用户消息的一个内容部分附加到消息中,模型在响应时便可结合图像中的内容。
const base64Image = "<a base64-encoded string of image bytes>";
const event = {
type: "conversation.item.create",
item: {
type: "message",
role: "user",
content: [
{
type: "input_image",
image_url: `data:image/{format};base64,${base64Image}`,
},
],
},
};
// WebRTC data channel and WebSocket both have .send()
dataChannel.send(JSON.stringify(event));语音活动检测
实时会话默认启用 语音活动检测(VAD) ,这意味着 API 会判断用户何时开始或停止说话,并自动响应。
有关如何配置 VAD 的更多信息,请参阅我们的语音活动检测指南。
禁用 VAD
您可以通过 session.update 客户端事件将 turn_detection 设置为 null,以禁用 VAD。这适用于需要精细控制音频输入的界面,例如按键通话界面。
禁用 VAD 后,客户端必须手动发送一些额外的客户端事件,才能触发音频响应:
- 手动发送
input_audio_buffer.commit,这会为对话创建一个新的用户输入项。 - 手动发送
response.create,以触发模型的音频响应。 - 在开始新的用户输入之前,发送
input_audio_buffer.clear。
保留 VAD,但禁用自动响应
如果您希望保持 VAD 模式启用,同时手动决定何时生成响应,可以通过 session.update 客户端事件将 turn_detection.interrupt_response 和 turn_detection.create_response 设置为 false。这样会保留 VAD 的所有行为,但不会自动创建新的响应。客户端可以通过 response.create 事件手动触发响应。
这适用于内容审核、输入验证或 RAG 模式等场景,前提是您可以接受稍高的交互延迟,以换取对输入的控制。
在默认对话之外创建响应
默认情况下,会话期间生成的所有响应都会添加到该会话的对话状态(即“默认对话”)中。不过,您可能希望在会话的默认对话上下文之外生成模型响应,或并发生成多个响应。您也可能希望更精细地控制模型生成响应时参考哪些对话条目(例如,仅参考最近 N 轮对话)。
使用 response.create 客户端事件创建响应时,将 response.conversation 字段设置为字符串 none,即可生成不会添加到默认对话状态中的“带外”响应。
创建带外响应时,您可能还需要一种方式来识别服务器发送的哪些事件与此响应有关。您可以为模型响应提供 metadata,以便识别哪个响应是针对该客户端发送的事件生成的。
const prompt = `
Analyze the conversation so far. If it is related to support, output
"support". If it is related to sales, output "sales".
`;
const event = {
type: "response.create",
response: {
// Setting to "none" indicates the response is out of band
// and will not be added to the default conversation
conversation: "none",
// Set metadata to help identify responses sent back from the model
metadata: { topic: "classification" },
// Set any other available response fields
output_modalities: ["text"],
instructions: prompt,
},
};
// WebRTC data channel and WebSocket both have .send()
dataChannel.send(JSON.stringify(event));现在,监听 response.done 服务器事件时,您就可以识别带外响应的结果。
function handleEvent(message) {
const data = "data" in message ? message.data : message.toString();
const serverEvent = JSON.parse(data);
if (
serverEvent.type === "response.done" &&
serverEvent.response.metadata?.topic === "classification"
) {
// this server event pertained to our OOB model response
console.log(serverEvent.response.output[0]);
}
}
// Listen for server messages (WebRTC)
dataChannel.addEventListener("message", handleEvent);
// Listen for server messages (WebSocket)
// ws.on("message", handleEvent);为响应创建自定义上下文
您还可以在默认或当前对话之外构建自定义上下文,供模型生成响应时使用。这可以通过 response.create 客户端事件中的 input 数组实现。您可以使用新的输入,也可以通过 ID 引用对话中已有的输入项。
const event = {
type: "response.create",
response: {
conversation: "none",
metadata: { topic: "pizza" },
output_modalities: ["text"],
// Create a custom input array for this request with whatever context
// is appropriate
input: [
// potentially include existing conversation items:
{
type: "item_reference",
id: "some_conversation_item_id",
},
{
type: "message",
role: "user",
content: [
{
type: "input_text",
text: "Is it okay to put pineapple on pizza?",
},
],
},
],
},
};
// WebRTC data channel and WebSocket both have .send()
dataChannel.send(JSON.stringify(event));创建无上下文的响应
您也可以将响应插入默认对话,同时忽略所有其他指令和上下文。只需将 input 设为空数组。
const prompt = `
Say exactly the following:
I'm a little teapot, short and stout!
This is my handle, this is my spout!
`;
const event = {
type: "response.create",
response: {
// An empty input array removes existing context
input: [],
instructions: prompt,
},
};
// WebRTC data channel and WebSocket both have .send()
dataChannel.send(JSON.stringify(event));函数调用
Realtime 模型还支持 函数调用,让您能够执行自定义代码来扩展模型的能力。其基本工作流程如下:
- 在更新会话或创建响应时,您可以指定可供模型调用的函数列表。
- 如果模型在处理输入时判断需要调用函数,就会向对话中添加表示函数调用参数的条目。
- 当客户端检测到包含函数调用参数的对话条目时,就会使用这些参数执行自定义代码。
- 自定义代码执行完毕后,客户端会创建包含函数调用输出的新对话条目,并请求模型生成响应。
下面添加一个可调用的函数,为模型用户提供今日星座运势,以此展示实际工作流程。我们将展示需要发送的客户端事件对象的结构,以及服务器相应发送的事件。
配置可调用的函数
首先,我们必须向模型提供一组函数,供其根据用户输入选择调用。可用函数既可以在会话级别配置,也可以为单个响应配置。
- 会话:
session.update中的session.tools属性 - 响应:
response.create中的response.tools属性
以下是 session.update 客户端事件的负载示例,用于配置星座运势生成函数。该函数接受一个参数,即要生成运势的星座:
{
"type": "session.update",
"session": {
"tools": [
{
"type": "function",
"name": "generate_horoscope",
"description": "Give today's horoscope for an astrological sign.",
"parameters": {
"type": "object",
"properties": {
"sign": {
"type": "string",
"description": "The sign for the horoscope.",
"enum": [
"Aries",
"Taurus",
"Gemini",
"Cancer",
"Leo",
"Virgo",
"Libra",
"Scorpio",
"Sagittarius",
"Capricorn",
"Aquarius",
"Pisces"
]
}
},
"required": ["sign"]
}
}
],
"tool_choice": "auto"
}
}
函数和参数的 description 字段可帮助模型决定是否调用该函数,以及为每个参数提供什么数据。如果模型收到的输入表明用户想了解自己的星座运势,就会调用此函数并传入 sign 参数。
检测模型何时想要调用函数
模型可能会根据收到的输入,决定调用函数以生成最佳响应。假设我们的应用通过 conversation.item.create 事件添加以下对话条目,然后创建响应:
{
"type": "conversation.item.create",
"item": {
"type": "message",
"role": "user",
"content": [
{
"type": "input_text",
"text": "What is my horoscope? I am an aquarius."
}
]
}
}
接着发送 response.create 客户端事件来生成响应:
{
"type": "response.create"
}
模型不会立即返回文本或音频响应,而是会生成包含参数的响应,这些参数应传递给开发者应用中的函数。您可以监听 response.function_call_arguments.delta 服务器事件,获取函数调用参数的实时更新;response.done 也会包含调用函数所需的完整数据。
{
"type": "response.done",
"event_id": "event_AeqLA8iR6FK20L4XZs2P6",
"response": {
"object": "realtime.response",
"id": "resp_AeqL8XwMUOri9OhcQJIu9",
"status": "completed",
"status_details": null,
"output": [
{
"object": "realtime.item",
"id": "item_AeqL8gmRWDn9bIsUM2T35",
"type": "function_call",
"status": "completed",
"name": "generate_horoscope",
"call_id": "call_sHlR7iaFwQ2YQOqm",
"arguments": "{\"sign\":\"Aquarius\"}"
}
],
...
}
}
通过服务器发送的 JSON,我们可以检测到模型想要调用自定义函数:
| 属性 | 在函数调用中的作用 |
|---|---|
response.output[0].type | 设为 function_call 时,表示此响应包含调用指定名称的函数所需的参数。 |
response.output[0].name | 要调用的已配置函数的名称,此处为 generate_horoscope。 |
response.output[0].arguments | 包含函数参数的 JSON 字符串。在本例中为 "{\"sign\":\"Aquarius\"}"。 |
response.output[0].call_id | 系统为此次函数调用生成的 ID。 您需要使用此 ID 将函数调用结果传回模型。 |
有了这些信息,我们就可以在应用中执行代码来生成星座运势,然后将结果传回模型,以便模型生成响应。
将函数调用结果提供给模型
收到模型返回的包含函数调用参数的响应后,您的应用就可以执行代码来完成该函数调用。具体操作可以按您的需要实现,例如调用外部 API 或访问数据库。
准备好将自定义代码的结果提供给模型后,您可以通过 conversation.item.create 客户端事件,创建包含该结果的新对话条目。
{
"type": "conversation.item.create",
"item": {
"type": "function_call_output",
"call_id": "call_sHlR7iaFwQ2YQOqm",
"output": "{\"horoscope\": \"You will soon meet a new friend.\"}"
}
}
- 对话条目的类型为
function_call_output。 item.call_id与上文response.done事件返回的 ID 相同。item.output是包含函数调用结果的 JSON 字符串。
添加包含函数调用结果的对话条目后,我们再次从客户端发送 response.create 事件。这会触发模型使用函数调用返回的数据生成响应。
{
"type": "response.create"
}
错误处理
会话期间,每当服务器遇到错误时,就会发送 error 事件。有时,这些错误可以追溯到您的应用发送的某个客户端事件。
在 HTTP 请求和响应中,响应与客户端请求隐式关联。而在这里,我们需要通过客户端事件的 event_id 属性,确定是哪个事件触发了服务器错误。下面的代码演示了这一方法,其中客户端尝试发送一种不受支持的事件类型。
const event = {
event_id: "my_awesome_event",
type: "scooby.dooby.doo",
};
dataChannel.send(JSON.stringify(event));客户端发送的这个未能成功处理的事件会触发如下错误事件:
{
"type": "invalid_request_error",
"code": "invalid_value",
"message": "Invalid value: 'scooby.dooby.doo' ...",
"param": "type",
"event_id": "my_awesome_event"
}
打断与截断
在许多语音应用中,用户可以在模型说话时打断它。启用 VAD 后,Realtime API 会处理这类打断:检测到用户说话时,取消正在进行的响应,并开始新的响应。不过,在这种情况下,您需要让模型知道它在哪里被打断,以便自然地继续对话(例如,用户问“刚才最后说的是什么?”时)。我们将这一操作称为 截断 模型的上一条响应,即从对话中移除模型上一条响应中尚未播放的部分。
在 WebRTC 和 SIP 连接中,服务器管理输出音频缓冲区,因此知道任一时刻音频已播放到哪里。用户打断时,服务器会自动截断尚未播放的音频。
使用 WebSocket 连接时,音频播放由客户端管理,因此客户端必须停止播放并处理截断。具体流程如下:
- 客户端监听服务器发送的新
input_audio_buffer.speech_started事件,该事件表示用户已开始说话。服务器会自动取消正在进行的模型响应,并发送response.cancelled事件。 - 客户端检测到此事件后,应立即停止播放当前正在播放的模型音频,并记录上一条音频响应在被打断前已播放到哪里。
- 客户端应发送
conversation.item.truncate事件,从对话中移除模型上一条响应尚未播放的部分。
示例如下:
{
"type": "conversation.item.truncate",
"item_id": "item_1234", # this is the item ID of the model's last response
"content_index": 0,
"audio_end_ms": 1500 # truncate audio after 1.5 seconds
}
转录文本也会一并截断吗?Realtime 模型没有足够的信息来精确对齐转录文本和音频,因此 conversation.item.truncate 会在指定位置截断音频,并移除未播放部分的转录文本。这解决了移除未播放音频的问题,但不会提供截断后的转录文本。
按住说话
Realtime API 默认使用语音活动检测(VAD),这意味着音频输入会触发模型响应。您也可以禁用 VAD,并在应用层控制何时向模型发送音频输入,从而实现按住说话的交互方式。例如,按住空格键采集音频,松开时触发响应。对于某些应用,这种方式的效果出乎意料地好:用户可以掌控交互过程,也能避免 VAD 检测失败,而且由于无需等待 VAD 超时,交互感觉更灵敏。
通过 WebSockets 和 WebRTC 实现按住说话的方式略有不同。在 Realtime API 的 WebSocket 连接中,所有事件都通过同一通道按相同的顺序发送;而 WebRTC 连接则使用独立的通道分别传输音频和控制事件。
WebSockets
要通过 WebSocket 连接实现按住说话,您需要让客户端停止音频播放、处理打断并发起新的响应。详细步骤如下:
- 在
session.update事件中设置"turn_detection": null,以关闭 VAD。 - 按下时,在客户端开始录制音频。
- 如果模型有正在进行的响应,请发送
response.cancel事件将其取消。 - 如果模型的输出音频仍在播放,请立即停止播放,并发送
conversation.item.truncate事件,从对话中移除所有尚未播放的音频。
- 如果模型有正在进行的响应,请发送
- 松开时,发送包含音频的
input_audio_buffer.append消息,将新音频放入输入缓冲区。 - 发送
input_audio_buffer.commit事件,提交已写入输入缓冲区的音频,并启动输入转录(如果已启用)。 - 然后通过
response.create事件触发响应。
WebRTC 和 SIP
使用 WebRTC 实现按住说话的方式类似,但必须显式清空输入音频缓冲区。具体步骤如下:
- 在
session.update事件中设置"turn_detection": null,以关闭 VAD。 - 按下按钮时,发送
input_audio_buffer.clear事件,清空之前的所有音频输入。- 如果模型有正在进行的响应,请发送
response.cancel事件将其取消。 - 如果模型的输出音频仍在播放,请发送
output_audio_buffer.clear事件,清除尚未播放的音频,同时也会截断对话。
- 如果模型有正在进行的响应,请发送
- 松开按钮时,发送
input_audio_buffer.commit事件,提交已写入输入缓冲区的音频,并启动输入音频转录(如果已启用)。 - 然后通过
response.create事件触发响应。