主导航

遗留 API

通过 WebRTC 使用 Realtime API

使用 WebRTC 连接到 Realtime API。

WebRTC 是一组强大的标准接口,用于构建实时应用程序。OpenAI Realtime API 支持通过 WebRTC 对等连接连接到实时模型。

对于基于浏览器的语音到语音应用程序,我们建议从语音智能体 (Voice agents) 开始,其中涵盖了用于管理 Realtime 会话的智能体 SDK (Agents SDK) 高级辅助工具和 API。WebRTC 接口功能强大且灵活,但相对于智能体 SDK 而言更底层。

当从客户端(如网页浏览器或移动设备)连接到 Realtime 模型时,我们建议使用 WebRTC 而不是 WebSocket,以获得更一致的性能。

有关在 WebRTC 之上构建用户界面的更多指导,请参阅 MDN 上的文档

概述

Realtime API 支持两种从浏览器连接的机制:使用临时 API 密钥(通过 OpenAI REST API 生成),或通过新的统一接口。通常,使用统一接口更简单,但会将您的应用程序服务器置于会话初始化的关键路径上。

使用统一接口连接

使用统一接口初始化 WebRTC 连接的过程如下(假设客户端为网页浏览器):

  1. 浏览器使用其 WebRTC 对等连接中的 SDP 数据向开发者控制的服务器发出请求。
  2. 服务器将该 SDP 与其会话配置组合在一个多部分表单 (multipart form) 中,并将其发送到 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);

使用临时令牌 (Ephemeral Token) 连接

使用临时 API 密钥初始化 WebRTC 连接的过程如下(假设客户端为网页浏览器):

  1. 浏览器向开发者控制的服务器发出请求以获取临时 API 密钥。
  2. 开发者的服务器使用标准 API 密钥OpenAI REST API 请求临时密钥,并将该新密钥返回给浏览器。
  3. 浏览器使用该临时密钥作为 WebRTC 对等连接,直接向 OpenAI Realtime API 进行身份验证并建立会话。

connect to realtime via 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 模型时,您不必像处理 WebSocket 那样以相同的细粒度方式处理来自模型的音频事件。如果按上述方式配置,WebRTC 对等连接对象将为您完成所有这些工作。

要发送和接收其他客户端及服务器事件,您可以使用 WebRTC 对等连接的数据通道 (data channel)

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 Console)

查看此轻量级示例应用,了解 WebRTC Realtime API 的使用方法。

© . This website operates independently and is not affiliated with or endorsed by OpenAI, Inc. All brand names, logos, and trademarks are the property of their respective owners.