通过实时翻译功能,您可以将源音频流式传输到专属的翻译会话中,并在讲话者仍在发言时接收翻译后的音频及文本记录增量。它适用于现场口译、多语言通话、广播、会议、教学以及视频会议室等场景。
使用 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/translationsendpoint. - 连续流式传输音频,包括短语之间的静音。
- 使用
session.closeand wait forsession.closed,然后再关闭 WebSocket 会话。 - 在对话翻译中保持说话人音轨独立。
- 每种输出语言使用一个会话。
- 在有用时同时渲染源文本和目标转录文本。
- 提供原始音频、翻译音频、字幕、静音和音量的控制选项。
- 向用户显示重连、延迟和不可用状态。
- 独立于翻译质量来跟踪延迟。
相关指南
对比语音代理、翻译和转录会话。
将浏览器媒体连接到实时会话。
通过服务端媒体管道传输原始音频。
从实时音频流式传输转录增量。