OpenAI 实时转录
Go示例在转录会话配置完成后发送24 kHz单声道PCM16、提交语音轮次,并以item_id匹配该提交项目的最终转录;不同轮次的完成事件可能乱序。 应用需要从麦克风、通话或其他实时音频流获取文字,而不需要助手语音回答时,使用实时转录。推荐模型会随讲话到达返回转录增量,并在应用提交每个音频轮次后返回最终转录。
从 gpt-live-transcribe 开始。音频已录制完成时使用文件转录,工作流比较见转录概览。
创建转录会话
服务端使用标准 API 密钥通过 WebSocket 转录时,连接 wss://api.openai.com/v1/realtime?intent=transcription。认证头见 WebSocket 指南,但 URL 中不要提供 model。该指南带模型的 URL 创建的是对话会话,不能接受下面的转录更新。
连接打开后,发送 type: "transcription" 的 session.update,在会话配置选择 gpt-live-transcribe。浏览器音频见 WebRTC。
来源示例 1(json):字段名、事件类型和示意值保留原样,含义见相邻正文;片段中的省略号不表示完整可运行程序。
{
"type": "session.update",
"session": {
"type": "transcription",
"audio": {
"input": {
"format": {
"type": "audio/pcm",
"rate": 24000
},
"transcription": {
"model": "gpt-live-transcribe"
},
"turn_detection": null
}
}
}
}
示例使用 24 kHz PCM。gpt-live-transcribe 转录会话中,省略 audio.input.turn_detection 或设为 null;模型不支持 server_vad 或 semantic_vad。完整配置见 Realtime 会话参考。
流式发送音频
通过 input_audio_buffer.append 发送音频块:
来源示例 2(javascript):
// [中文] 示例 2:流式发送音频;以下保留本语言原始示例。
// [中文] 本段构造的事件类型:input_audio_buffer.append;不要将构造载荷等同于收到成功确认。
// [中文] 沿原示例执行这些方法:ws.send;异步调用及事件接收顺序保留。
ws.send(
JSON.stringify({
type: "input_audio_buffer.append",
audio: base64Pcm16,
})
);
在每个音频轮次结束时发送 input_audio_buffer.commit,取得最终转录:
来源示例 3(javascript):
// [中文] 示例 3:流式发送音频;以下保留本语言原始示例。
// [中文] 本段构造的事件类型:input_audio_buffer.commit;不要将构造载荷等同于收到成功确认。
// [中文] 沿原示例执行这些方法:ws.send;异步调用及事件接收顺序保留。
ws.send(
JSON.stringify({
type: "input_audio_buffer.commit",
})
);
使用客户端 VAD 检测讲话结束,然后发送 input_audio_buffer.commit。
处理转录事件
监听增量转录和完成事件:
来源示例 4(javascript):
程序文字译释107:最终转录文字。
// [中文] 示例 4:处理转录事件;以下保留本语言原始示例。
// [中文] 沿原示例执行这些方法:ws.on;异步调用及事件接收顺序保留。
ws.on("message", (data) => {
const event = JSON.parse(data);
if (event.type === "conversation.item.input_audio_transcription.delta") {
process.stdout.write(event.delta);
}
if (event.type === "conversation.item.input_audio_transcription.completed") {
console.log("\nFinal transcript:", event.transcript);
}
});
增量事件包含新获得的转录文字:
来源示例 5(json):字段名、事件类型和示意值保留原样,含义见相邻正文;片段中的省略号不表示完整可运行程序。
{
"type": "conversation.item.input_audio_transcription.delta",
"item_id": "item_003",
"content_index": 0,
"delta": "Hello,"
}
完成事件包含已提交项目的最终转录:
来源示例 6(json):
程序文字译释108:你好,你怎么样?
{
"type": "conversation.item.input_audio_transcription.completed",
"item_id": "item_003",
"content_index": 0,
"transcript": "Hello, how are you?"
}
// [中文] 按会话配置发送输入音频并处理提交或转录事件;音频字节格式必须匹配配置,不能仅修改参数而不转换采样数据。
// [中文] 本段为配置或调用片段,需结合外层程序与已建立连接使用;不作为独立完整程序宣称编译通过。
func transcribeTurn(ctx context.Context, conn *realtime.RealtimeConnection, audio []byte) error {
for start := 0; start < len(audio); start += 9600 {
end := min(start+9600, len(audio))
if err := conn.Send(ctx, realtime.RealtimeClientEventParamOfInputAudioBufferAppend(base64.StdEncoding.EncodeToString(audio[start:end]))); err != nil {
return err
}
}
if err := conn.Send(ctx, realtime.RealtimeClientEventUnionParam{
OfInputAudioBufferCommit: &realtime.InputAudioBufferCommitEventParam{},
}); err != nil {
return err
}
// Match the final transcript to the committed item, not event arrival order.
var itemID string
for {
event, err := conn.Recv(ctx)
if err != nil {
return err
}
switch event.Type {
case "input_audio_buffer.committed":
itemID = event.OfInputAudioBufferCommittedEvent.ItemID
case "conversation.item.input_audio_transcription.delta":
delta := event.OfConversationItemInputAudioTranscriptionDeltaEvent
if itemID != "" && delta.ItemID == itemID {
fmt.Fprintf(os.Stderr, "Partial transcript (%s): %s\n", delta.ItemID, delta.Delta)
}
case "conversation.item.input_audio_transcription.completed":
completed := event.OfConversationItemInputAudioTranscriptionCompletedEvent
if itemID == "" || completed.ItemID != itemID {
continue
}
fmt.Println("Final transcript:", completed.Transcript)
return nil
case "conversation.item.input_audio_transcription.failed":
if itemID != "" && event.OfConversationItemInputAudioTranscriptionFailedEvent.ItemID == itemID {
return fmt.Errorf("transcription failed")
}
case "error":
return fmt.Errorf("Realtime API error: %s", event.OfRealtimeErrorEvent.Error.Message)
}
}
}
不同讲话轮次的完成事件不保证按顺序到达。使用 item_id 将转录事件匹配到已提交输入项。
添加转录上下文
音频包含专业词汇或预计会出现多种语言时,可以补充上下文。在已有会话中再发送 session.update,即可更改转录配置。
来源示例 7(json):
程序文字译释109:一段涉及高级套餐及账户AC-42的客服通话。
程序文字译释110:高级套餐。
{
"type": "session.update",
"session": {
"type": "transcription",
"audio": {
"input": {
"format": {
"type": "audio/pcm",
"rate": 24000
},
"transcription": {
"model": "gpt-live-transcribe",
"prompt": "A customer support call about a premium plan and account AC-42.",
"keywords": ["premium plan", "AC-42", "billing"],
"languages": ["en", "fr"],
"delay": "low"
},
"turn_detection": null
}
}
}
}
prompt:描述录音及其场景。keywords:提供可能出现的产品名、缩写或其他字面术语。languages:指定预计的输入语言。
支持的语言代码格式包括:
- ISO 639-1,如
en、es、fr。 - 部分 ISO 639-3,如
eng、spa、yue、cmn。 zh地区语言代码,如zh-cn、zh-tw、zh-hk。
Realtime API 会拒绝不支持或格式错误的语言代码。
关键词是提示,不是强制输出。每个关键词保持一行,不含 <、>、回车或换行。关键词包含这些字符,或 prompt 超出模型长度限制时,会话更新会被拒绝。
gpt-live-transcribe 使用 languages,而不是单数 language 字段,不要同时发送两者。
转录已提交轮次
只有明确需要提交音频轮次之后才开始转录,或需要输出检测到的语言时,才在 Realtime 会话使用 gpt-transcribe。这种专用工作流要求 WebSocket 连接。
gpt-transcribe 无论在 Realtime API 会话中做输入转录,还是在专用转录会话中运行,都会自动把较早已转录轮次作为上下文。
来源示例 8(json):字段名、事件类型和示意值保留原样,含义见相邻正文;片段中的省略号不表示完整可运行程序。
{
"type": "session.update",
"session": {
"type": "transcription",
"audio": {
"input": {
"format": {
"type": "audio/pcm",
"rate": 24000
},
"transcription": {
"model": "gpt-transcribe"
},
"turn_detection": null
}
}
}
}
追加音频并发送 input_audio_buffer.commit,模型随后可在最终完成事件之前发出转录增量。完成事件还包含检测到的语言:
来源示例 9(json):字段名、事件类型和示意值保留原样,含义见相邻正文;片段中的省略号不表示完整可运行程序。
{
"type": "conversation.item.input_audio_transcription.completed",
"item_id": "item_003",
"content_index": 0,
"transcript": "Bonjour, pouvez-vous m'entendre ?",
"languages": [{ "code": "fr" }]
}
gpt-transcribe 无法可靠预测语言时,languages 是空数组。gpt-live-transcribe 不返回检测语言预测。
调整延迟与准确性
流式转录需要在延迟与质量间权衡。较低延迟设置可更早产生部分文字;较高设置让模型发出文字前获得更多音频上下文,可能改善词错误率。
从 audio.input.transcription.delay 开始,使用实际音频测试。可参考以下起点:
minimal:最敏感于延迟的交互。low:低延迟实时字幕。medium:平衡延迟与准确性。high:准确性比立即显示更重要。xhigh:能容忍最多等待时间,以获得更多上下文。
实际毫秒延迟随模型配置变化,应用代表性音频做基准测试,不要假定每级对应固定时间。
不要只根据合成音频选设置。测试实际麦克风、电话音频、口音、背景噪声、语码切换、领域词汇和长会话。
处理置信度、时间戳与说话人标签
gpt-live-transcribe 不返回词级时间戳、说话人标签或转录置信度。需要时间戳或说话人标签时,使用兼容的文件转录模型,或增加应用级回退方案。
生产检查清单
- 调参前确定目标延迟和准确性阈值。
- 使用真实生产音频测试,而不只是干净样本。
- 逐一测试目标语言。
- 评估集中加入数字、日期、货币、电子邮箱、产品名与领域术语。
- 除词错误率外,分别追踪空转录、截断和延迟。
- 决定后续增量纠正较早文字时,界面如何修订部分文本。
- 用
item_id排序并协调最终转录。 - 为不支持的时间戳、说话人标签或置信度字段保留回退路径。
相关指南
- Realtime 与音频概览:比较语音智能体、翻译与转录会话。
- 实时翻译:通过专用翻译会话翻译实时语音。
- WebSocket 连接:在服务端媒体流水线中传输原始音频。
- 语音活动检测:配置实时音频流的轮次检测。

TRAE-AI编程


更多建议: