English
主导航

旧版 API

实时翻译

实时翻译语音并输出流式音频和文本记录。

通过实时翻译功能,您可以将源音频流式传输到专属的翻译会话中,并在讲话者仍在发言时接收翻译后的音频及文本记录增量。它适用于现场口译、多语言通话、广播、会议、教学以及视频会议室等场景。

使用 gpt-realtime-translate 适用于您的应用程序需要翻译人类语音的情况。如果您需要一个能够回答问题、调用工具并管理对话的助手,请改用 gpt-realtime-2 并结合标准的 Realtime 会话。

翻译会话的区别

Realtime 翻译会话采用了与语音代理会话不同的架构:

语音代理会话翻译会话
连接至 /v1/realtime.连接至 /v1/realtime/translations.
模型充当助手。模型充当翻译员。
使用对话和响应生命周期。从传入的音频持续流式传输。
可能会调用工具并生成助手轮次。生成翻译后的音频和文本记录增量。
您可以调用 response.create.您不能调用 response.create.

翻译直接从音频流本身开始。持续追加音频(包括短语之间的静音),并在输出事件到达时对其进行处理。

选择传输方式

当浏览器需要捕获或播放音频时,请使用 WebRTC。WebRTC 将源音频作为媒体轨道发送,并将翻译后的语音作为远程音频轨道接收,因此您无需手动重采样或播放 PCM 数据块。

当您的服务器已经接收到原始音频时(例如来自 Twilio Media Streams、SIP 媒体、广播输入源或媒体工作器),请使用 WebSockets。使用 WebSockets 时,发送 base64 编码的 24 kHz PCM16 音频并自行播放返回的音频增量。

创建浏览器 WebRTC 会话

对于浏览器应用,请在您的服务器上创建一个短期有效的客户端密钥。切勿在浏览器中暴露您的标准 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
app.post("/session", async (req, res) => {
  const language = req.body.targetLanguage ?? "es";

  const response = await fetch(
    "https://api.openai.com/v1/realtime/translations/client_secrets",
    {
      method: "POST",
      headers: {
        Authorization: `Bearer ${process.env.OPENAI_API_KEY}`,
        "Content-Type": "application/json",
        "OpenAI-Safety-Identifier": "hashed-user-id",
      },
      body: JSON.stringify({
        session: {
          model: "gpt-realtime-translate",
          audio: {
            output: { language },
          },
        },
      }),
    }
  );

  res.status(response.status).json(await response.json());
});

在浏览器中,捕获音频、创建对等连接,并将 SDP offer 发布到翻译调用端点:

连接浏览器翻译调用
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
43
44
45
46
47
48
49
50
const { value: clientSecret } = await fetch("/session", {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({ targetLanguage: "es" }),
}).then((response) => response.json());

const sourceStream = await navigator.mediaDevices.getUserMedia({
  audio: true,
});

const pc = new RTCPeerConnection();
pc.addTrack(sourceStream.getAudioTracks()[0], sourceStream);

const translatedAudio = new Audio();
translatedAudio.autoplay = true;
pc.ontrack = ({ streams }) => {
  translatedAudio.srcObject = streams[0];
};

const events = pc.createDataChannel("oai-events");
events.onmessage = ({ data }) => {
  const event = JSON.parse(data);
  if (event.type === "session.output_transcript.delta") {
    subtitles.textContent += event.delta;
  }
};

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

const sdpResponse = await fetch(
  "https://api.openai.com/v1/realtime/translations/calls",
  {
    method: "POST",
    headers: {
      Authorization: `Bearer ${clientSecret}`,
      "Content-Type": "application/sdp",
    },
    body: offer.sdp,
  }
);

if (!sdpResponse.ok) {
  throw new Error(await sdpResponse.text());
}

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

创建 WebSocket 会话

连接到专属的翻译端点并在 URL 中选择模型:

安装 ws Node.js 的 websocket-client Python 包后再运行此示例。

连接到翻译会话
1
2
3
4
5
6
7
8
9
10
11
import WebSocket from "ws";

const ws = new WebSocket(
  "wss://api.openai.com/v1/realtime/translations?model=gpt-realtime-translate",
  {
    headers: {
      Authorization: `Bearer ${process.env.OPENAI_API_KEY}`,
      "OpenAI-Safety-Identifier": "hashed-user-id",
    },
  }
);

在 Socket 打开后配置目标语言:

配置目标语言
1
2
3
4
5
6
7
8
9
10
11
12
13
14
ws.on("open", () => {
  ws.send(
    JSON.stringify({
      type: "session.update",
      session: {
        audio: {
          output: {
            language: "es",
          },
        },
      },
    })
  );
});

然后持续追加音频:

追加源音频
1
2
3
4
5
6
ws.send(
  JSON.stringify({
    type: "session.input_audio_buffer.append",
    audio: base64Pcm16,
  })
);

监听翻译后的音频和文本:

监听翻译后的音频和文本
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
ws.on("message", (data) => {
  const event = JSON.parse(data);

  if (event.type === "session.output_audio.delta") {
    playPcm16(event.delta);
  }

  if (event.type === "session.output_transcript.delta") {
    process.stdout.write(event.delta);
  }

  if (event.type === "session.input_transcript.delta") {
    updateSourceTranscript(event.delta);
  }
});

关闭 WebSocket 会话

当源流结束时,在关闭 WebSocket 之前发送一个 session.close 事件。该事件会通知服务刷新待处理的输入音频,发出所有剩余的翻译音频和文本输出,然后发送一个 session.closed 事件。 session.close 事件仅支持翻译会话。

发送 session.close,停止追加音频,并在正常的接收循环中继续读取事件,直到收到 session.closed。立即关闭套接字可能会导致仍在从会话中排出的翻译输出丢失。

关闭翻译会话
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
let translationSessionClosing = false;

function closeTranslationSession() {
  if (translationSessionClosing) {
    return;
  }

  translationSessionClosing = true;
  ws.send(
    JSON.stringify({
      type: "session.close",
    })
  );
}

ws.on("message", (data) => {
  const event = JSON.parse(data);

  if (event.type === "session.output_audio.delta") {
    playPcm16(event.delta);
  }

  if (event.type === "session.output_transcript.delta") {
    process.stdout.write(event.delta);
  }

  if (event.type === "session.input_transcript.delta") {
    updateSourceTranscript(event.delta);
  }

  if (event.type === "session.closed") {
    ws.close();
  }
});

// Call this when the source stream ends.
closeTranslationSession();

构建同声传译翻译

当单个源发言者或流需要为听众提供翻译后的音频时,请使用同声传译翻译。示例场景包括直播、会议演讲、网络研讨会、财报电话会议、讲座和视频。

The typical architecture is:

source audio -> translation session -> translated audio + subtitles

为每种目标语言创建一个翻译会话。如果同一个英文源需要西班牙文和法文输出,请创建一个英译西会话和一个英译法会话。

对于浏览器同声传译应用,请使用以下方法捕获标签页音频: getDisplayMedia(),通过 WebRTC 将其发送,并播放远程翻译后的音频轨道。对于生产环境的广播,请在服务器媒体工作器中运行翻译,并将翻译后的音频轨道或字幕发布给听众。

构建对话翻译

当两个或多个参与者跨语言交流时,请使用对话翻译。示例场景包括客服电话、销售电话、辅导和视频会议室。

保持参与者音轨独立。将多个发言者混入同一个流会使发言者身份识别、发言者字幕和重叠语音的处理变得更加困难。

对于双人通话,每个方向创建一个翻译会话:

Caller A audio -> translate into Caller B language -> play to Caller B
Caller B audio -> translate into Caller A language -> play to Caller A

对于群聊室,会话数量取决于活跃发言者和目标语言:

translation sessions ~= active source speaker tracks x distinct target languages

对于小型房间,每个听众可以为其想要翻译的远程发言者创建浏览器端的翻译侧车(sidecar)。对于较大的房间,请使用服务器端参与者或媒体 Worker,它订阅每个源发言者一次,为每个目标语言创建一个翻译会话,然后重新发布翻译后的音轨。

测试质量和延迟

使用真实音频和双语审查来测试翻译。自动化指标会有所帮助,但它们无法捕捉到用户注意到的所有错误。

Test:

  • 语言对质量;
  • 姓名、数字、日期、货币和电话号码;
  • 特定领域的术语;
  • 语码转换和多语言混合对话;
  • 口音、语速过快以及语音重叠;
  • 首次翻译音频延迟;
  • 话语结束延迟;
  • 字幕时间轴;
  • 语音一致性;
  • 重连行为。

如果你的用例依赖于确切的名称或领域术语,请在发布前建立黄金标准集并手动检查错误。

生产检查清单

  • 浏览器媒体选择 WebRTC,服务器媒体选择 WebSockets。
  • 使用专用的 /v1/realtime/translations endpoint.
  • 连续流式传输音频,包括短语之间的静音。
  • 使用 session.close and wait for session.closed ,然后再关闭 WebSocket 会话。
  • 在对话翻译中保持说话人音轨独立。
  • 每种输出语言使用一个会话。
  • 在有用时同时渲染源文本和目标转录文本。
  • 提供原始音频、翻译音频、字幕、静音和音量的控制选项。
  • 向用户显示重连、延迟和不可用状态。
  • 独立于翻译质量来跟踪延迟。
实时与音频概述

对比语音代理、翻译和转录会话。

WebRTC 连接

将浏览器媒体连接到实时会话。

WebSocket 连接

通过服务端媒体管道传输原始音频。

实时转录

从实时音频流式传输转录增量。