WebRTC 是一套用于构建实时应用的强大标准接口。OpenAI Realtime API 支持通过 WebRTC 对等连接来连接实时模型。
对于基于浏览器的端到端语音应用,我们建议从 语音智能体, 涵盖了 Agents SDK 中用于管理 Realtime 会话的更高级辅助工具和 API。WebRTC 接口功能强大且灵活,但级别低于 Agents SDK。
当从客户端(例如 Web 浏览器或移动设备)连接到 Realtime 模型时,我们建议使用 WebRTC 而非 WebSockets,以获得更稳定的性能。
有关在 WebRTC 之上构建用户界面的更多指南, 请参阅 MDN 上的文档.
概览
Realtime API 支持两种从浏览器连接到 Realtime API 的机制:使用临时 API 密钥(通过 OpenAI REST API 生成),或通过全新的统一接口。通常,使用统一接口更简单,但会让你的应用服务器处于会话初始化的关键路径上。
使用统一接口进行连接
使用统一接口初始化 WebRTC 连接的过程如下(假设客户端为 Web 浏览器):
- 浏览器使用其 WebRTC 对等连接中的 SDP 数据,向开发者控制的服务器发起请求。
- 服务器将该 SDP 数据与其会话配置组合成 multipart 表单,并将其发送到 OpenAI Realtime API,同时使用其 标准 API 密钥进行身份验证.
通过统一接口创建会话
要通过统一接口创建 Realtime API 会话,你需要构建一个小型的服务器端应用程序(或与现有的应用程序集成),以向其发起请求 /v1/realtime/calls。你将使用 标准 API 密钥进行身份验证 以便在你的后端服务器上对此请求进行身份验证。
以下是一个简单的 Node.js express 服务器示例,用于创建 Realtime API 会话:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
import express from "express";
const app = express();
// Parse raw SDP payloads posted from the browser
app.use(express.text({ type: ["application/sdp", "text/plain"] }));
const sessionConfig = JSON.stringify({
type: "realtime",
model: "gpt-realtime-2",
audio: { output: { voice: "marin" } },
});
// An endpoint which creates a Realtime API session.
app.post("/session", async (req, res) => {
const fd = new FormData();
fd.set("sdp", req.body);
fd.set("session", sessionConfig);
try {
const r = await fetch("https://api.openai.com/v1/realtime/calls", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.OPENAI_API_KEY}`,
"OpenAI-Safety-Identifier": "hashed-user-id",
},
body: fd,
});
// Send back the SDP we received from the OpenAI REST API
const sdp = await r.text();
res.send(sdp);
} catch (error) {
console.error("Token generation error:", error);
res.status(500).json({ error: "Failed to generate token" });
}
});
app.listen(3000);如果你的应用程序为 安全标识符
每个最终用户分配了安全标识符,请将其作为 OpenAI-Safety-Identifier 请求头包含在此服务器端请求中。请使用稳定的、保护隐私的值,例如经过哈希处理的内部用户 ID。该请求头应由你受信任的后端设置,而不是由浏览器设置。
连接到服务器
在浏览器中,你可以使用标准的 WebRTC API 通过应用服务器连接到 Realtime API。客户端直接将其 SDP 数据 POST 到你的服务器。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
// Create a peer connection
const pc = new RTCPeerConnection();
// Set up to play remote audio from the model
audioElement.current = document.createElement("audio");
audioElement.current.autoplay = true;
pc.ontrack = (e) => (audioElement.current.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]);
// Set up data channel for sending and receiving events
const dc = pc.createDataChannel("oai-events");
// Start the session using the Session Description Protocol (SDP)
const offer = await pc.createOffer();
await pc.setLocalDescription(offer);
const sdpResponse = await fetch("/session", {
method: "POST",
body: offer.sdp,
headers: {
"Content-Type": "application/sdp",
},
});
const answer = {
type: "answer",
sdp: await sdpResponse.text(),
};
await pc.setRemoteDescription(answer);使用临时令牌进行连接
使用临时 API 密钥初始化 WebRTC 连接的过程如下(假设客户端为 Web 浏览器):
- 浏览器向开发者控制的服务器发起请求,以生成临时 API 密钥。
- 开发者的服务器使用 标准 API 密钥进行身份验证 向 OpenAI REST API 请求临时密钥, 并将该新密钥返回给浏览器。
- 浏览器使用临时密钥直接与 OpenAI Realtime API 作为 WebRTC 对等连接.
创建临时令牌
要创建一个在客户端使用的临时令牌,您需要构建一个小型服务端应用程序(或集成到现有应用中),以发起对 OpenAI REST API 请求临时密钥 临时密钥的请求。您将使用一个 标准 API 密钥进行身份验证 以便在你的后端服务器上对此请求进行身份验证。
以下是一个简单的 Node.js express 服务器,通过 REST API 生成临时 API 密钥:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
import express from "express";
const app = express();
const sessionConfig = JSON.stringify({
session: {
type: "realtime",
model: "gpt-realtime-2",
audio: {
output: {
voice: "marin",
},
},
},
});
// An endpoint which would work with the client code above - it returns
// the contents of a REST API request to this protected endpoint
app.get("/token", async (req, res) => {
try {
const response = await fetch(
"https://api.openai.com/v1/realtime/client_secrets",
{
method: "POST",
headers: {
Authorization: `Bearer ${apiKey}`,
"Content-Type": "application/json",
"OpenAI-Safety-Identifier": "hashed-user-id",
},
body: sessionConfig,
}
);
const data = await response.json();
res.json(data);
} catch (error) {
console.error("Token generation error:", error);
res.status(500).json({ error: "Failed to generate token" });
}
});
app.listen(3000);您可以在任何能够发送和接收 HTTP 请求的平台上创建类似这样的服务器端点。只需确保 您仅在服务器上使用标准的 OpenAI API 密钥,而不要在浏览器中使用。
在使用临时令牌时,请在 OpenAI-Safety-Identifier 创建客户端密钥的服务端请求上进行设置。Realtime API 会将标识符与生成的临时令牌绑定,因此浏览器在随后使用该令牌进行连接时,无需再发送安全标识符。
连接到服务器
在浏览器中,你可以使用标准的 WebRTC API 通过临时令牌连接到 Realtime API。客户端首先从你的服务端接口获取令牌,然后将其 SDP 数据(连同临时令牌)POST 到 Realtime API。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
// Get a session token for OpenAI Realtime API
const tokenResponse = await fetch("/token");
const data = await tokenResponse.json();
const EPHEMERAL_KEY = data.value;
// Create a peer connection
const pc = new RTCPeerConnection();
// Set up to play remote audio from the model
audioElement.current = document.createElement("audio");
audioElement.current.autoplay = true;
pc.ontrack = (e) => (audioElement.current.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]);
// Set up data channel for sending and receiving events
const dc = pc.createDataChannel("oai-events");
// Start the session using the Session Description Protocol (SDP)
const offer = await pc.createOffer();
await pc.setLocalDescription(offer);
const sdpResponse = await fetch("https://api.openai.com/v1/realtime/calls", {
method: "POST",
body: offer.sdp,
headers: {
Authorization: `Bearer ${EPHEMERAL_KEY}`,
"Content-Type": "application/sdp",
},
});
const answer = {
type: "answer",
sdp: await sdpResponse.text(),
};
await pc.setRemoteDescription(answer);发送和接收事件
Realtime API 会话通过结合使用以下两者来进行管理: 客户端发送的事件 (由你作为开发者发出)以及 服务器发送事件 由 Realtime API 创建,用于指示会话生命周期事件。
通过 WebRTC 连接到 Realtime 模型时,您不必像在使用 WebSockets. 如上所述配置后,WebRTC 对等连接对象将为你完成所有这些工作。
要发送和接收其他客户端和服务器事件,您可以使用 WebRTC 对等连接的 数据通道.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// This is the data channel set up in the browser code above...
const dc = pc.createDataChannel("oai-events");
// Listen for server events
dc.addEventListener("message", (e) => {
const event = JSON.parse(e.data);
console.log(event);
});
// Send client events
const event = {
type: "conversation.item.create",
item: {
type: "message",
role: "user",
content: [
{
type: "input_text",
text: "hello there!",
},
],
},
};
dc.send(JSON.stringify(event));要了解有关管理 Realtime 对话的更多信息,请参阅 Realtime 对话指南.
请在这个轻量级示例应用中查看 WebRTC Realtime API。