You need to enable JavaScript to run this app.
文档中心
实时音视频

实时音视频

复制全文
下载 pdf
开发指南
实时通话字幕和翻译
复制全文
下载 pdf
实时通话字幕和翻译
注意​
对于 AI 音视频互动方案(即通过接口 StartVoiceChat 实现字幕),请参见实时字幕(对话记录)。​
功能介绍​
通过实时字幕功能,可以将用户的语音实时转换为文字,并支持将文字翻译成其他语言,可用于直播字幕、会议记录生成、跨语言沟通实时翻译等场景。​
  • 支持通过客户端或服务端实现该功能。​
  • 根据使用场景的不同,可生成以下 2 种类型的字幕:​
  • ​
  • ​
    特性​
    按源语言生成字幕(无需翻译)​
    生成指定语言的字幕(将语音转为文字后并翻译)​
    作用​
    识别用户语音,直接按照源语言转为文字,适用于实时字幕显示场景。​
    识别用户语音,先按照源语言转为文字,再被翻译为指定目标语言,适用于跨语言实时翻译场景。​
    所用服务​
    火山的流式语音识别​
    火山的机器翻译​
    可识别的语种​
    不同场景,支持的语言不同,具体请参见豆包语音控制台-流式语音识别-服务详情​
    仅支持 zh、ja、en​
    翻译字幕​
    不支持​
    支持。支持翻译为的目标语言,请参见语言支持​
    返回的字幕数据​
    仅返回字幕原文​
    同时返回字幕原文和字幕译文​
    费用​
    音频订阅费、流式语音识别费​
    音频订阅费、实时语音翻译费​
    ​
计费说明​
使用实时字幕功能除基础音视频通话费以外,还会产生以下费用:​
​
​
费用​
说明​
启动实时字幕任务后,系统会自动分配一个机器人加入房间,订阅需要生成字幕的音频流,产生音频订阅费。​
若使用了流式语音识别服务(即识别模式),会产生流式语音识别费。​
若是使用了机器翻译(即翻译模式),会产生实时语音翻译费。​
​
生成字幕​
按源语言生成字幕(识别模式)​
  1. 开通服务。​
  1. 开通流式语音识别服务:前往豆包语音控制台_流式语音识别,创建流式语音识别应用,服务类型选择 流式语音识别,并记录 APP ID,Access Token,和语言的 Cluster ID,以备使用。​
  1. 开启实时字幕:前往 RTC 控制台_实时字幕进行以下操作:​
  • 实时字幕:开启开关。​
  • 流式语音识别:开启开关,并按照提示填入 APP ID、Access Token 和语言的 Cluster ID。​
注意​
  • 语种的 Cluster ID:即设置待识别的源语种代号,系统已经预设了 4 种常用语言。若不满足需求,可自定义语种代号。​
  1. 生成字幕并接收字幕。​
  • 通过客户端实现:字幕结果仅可返回至客户端,但是无需解析。​
  • 通过服务端实现:字幕结果仅可返回至客户端或服务端,字幕为二进制数据,使用前需先解析。​
  • ​
    通过客户端实现
    通过服务端(OpenAPI)实现
    ​
    相关接口说明,请参见相关API。​
    1. (可选)调用 joinRoom 接口进房时,设置源语言。​
    1. 进房后,调用 startSubtitle 启动字幕服务。模式(mode)选择翻译模式,并指定字幕要翻译的语言。​
    1. 通过 onSubtitleStateChanged 回调接收字幕生成结果。​
    ​
生成指定语言的字幕(翻译模式)​
  1. 开通服务。​
  1. 开通机器翻译服务:具体操作,请参见开通服务。​
  1. 开通实时字幕服务:前往 RTC 控制台_实时字幕,开启实时字幕和实时语音翻译的开关。​
  1. 生成字幕并接收字幕结果。​
  • 客户端生成:字幕结果仅可返回至客户端,但是无需解析。​
  • 服务端生成:字幕结果仅可返回至客户端或服务端,字幕为二进制数据,使用前需先解析。​
  • ​
    通过客户端实现
    通过服务端(OpenAPI)实现
    ​
    相关接口说明,请参见相关API。​
    1. (可选)调用 joinRoom 接口进房时,设置源语言。​
    1. 进房后,调用 startSubtitle 启动字幕服务。模式(mode)选择翻译模式,并指定字幕要翻译的语言。​
    1. 通过 onSubtitleStateChanged 回调接收字幕生成结果。​
    1. 当不再需要字幕功能时,调用 stopSubtitle 关闭字幕。​
    ​
解析字幕​
解析回调到服务端的字幕​
字幕消息会通过 HTTP(S) POST 请求发送给您指定的 URL 地址。​
​
​
参数名​
类型​
描述​
message​
String​
生成的字幕数据,格式为 Base64 编码的二进制,具体说明参见字幕数据二进制格式。​
signature​
String​
鉴权签名。可与 startSubtitle 接口中传入的 signature 字段值进行对比,以进行鉴权验证。​
​
message 解析示例​
你可以参考以下示例代码对回调信息中的message内容进行解析。​
​
Golang
Python
​
​
const (​
subtitleHeader = "subc"​
exampleSignature = "example_signature"​
)​
​
type RtsMessage struct {​
Message string `json:"message"`​
Signature string `json:"signature"`​
}​
​
type subc struct {​
Type string `json:"type"`​
Data []Data `json:"data"`​
}​
​
type Data struct {​
Definite bool `json:"definite"`​
Paragraph bool `json:"paragraph"`​
Language string `json:"language"`​
Sequence int `json:"sequence"`​
Text string `json:"text"`​
UserID string `json:"userId"`​
}​
​
func HandleSubtitle(c *gin.Context) {​
msg := &RtsMessage{}​
if err := c.BindJSON(&msg); err != nil {​
fmt.Printf("BindJson failed,err:%v\\n", err)​
return​
}​
if msg.Signature != exampleSignature {​
fmt.Printf("Signature not match\\n")​
return​
}​
​
subc, err := Unpack(msg.Message)​
if err != nil {​
fmt.Printf("Unpack failed,err:%v\\n", err)​
return​
}​
​
fmt.Println(subc)​
​
//业务逻辑​
​
c.String(200, "ok")​
}​
​
func Unpack(msg string) (*subc, error) {​
data, err := base64.StdEncoding.DecodeString(msg)​
if err != nil {​
return nil, fmt.Errorf("DecodeString failed,err:%v", err)​
}​
if len(data) < 8 {​
return nil, fmt.Errorf("Data invalid")​
}​
dataHeader := string(data[:4])​
if dataHeader != subtitleHeader {​
return nil, fmt.Errorf("Header not match")​
}​
dataSize := binary.BigEndian.Uint32(data[4:8])​
if dataSize+8 != uint32(len(data)) {​
return nil, fmt.Errorf("Size not match")​
}​
​
subData := data[8:]​
subc := &subc{}​
err = json.Unmarshal(subData, subc)​
if err != nil {​
return nil, fmt.Errorf("Unmarshal failed,err:%v\\n", err)​
}​
return subc, nil​
}​
​
func main() {​
​
r := gin.Default()​
r.POST("/example_domain/vertc/subtitle", HandleSubtitle)​
r.Run()​
}​
​
​
解析回调到客户端的字幕​
字幕回调消息格式如下:​
​
​
参数名​
类型​
描述​
uid​
String​
消息发送者 ID。​
message​
String​
生成的字幕数据,格式为Base64 编码的二进制,具体说明参见字幕数据二进制格式。​
​
message 解析示例​
你可以参考以下示例代码对回调信息中的 message 内容进行解析。​
​
C++
Java
ObjectiveC
​
​
//定义结构体​
struct SubtitleMsgData {​
bool definite;​
std::string language;​
bool paragraph;​
int sequence;​
std::string text;​
std::string userId;​
};​
​
//回调事件​
void onRoomBinaryMessageReceived(const char* uid, int size, const uint8_t* message) {​
std::string subtitles;​
bool ret = Unpack(message, size, subtitles);​
if(ret) {​
ParseData(subtitles);​
}​
}​
​
//拆包校验​
bool Unpack(const uint8_t *message, int size, std::string& subtitles) {​
int kSubtitleHeaderSize = 8;​
if(size < kSubtitleHeaderSize) { ​
return false;​
}​
// magic number "subc"​
if(static_cast<uint32_t>((static_cast<uint32_t>(message[0]) << 24) ​
| (static_cast<uint32_t>(message[1]) << 16) ​
| (static_cast<uint32_t>(message[2]) << 8) ​
| static_cast<uint32_t>(message[3])) != 0x73756276U) {​
return false;​
}​
​
uint32_t length = static_cast<uint32_t>((static_cast<uint32_t>(message[4]) << 24) ​
| (static_cast<uint32_t>(message[5]) << 16) ​
| (static_cast<uint32_t>(message[6]) << 8) ​
| static_cast<uint32_t>(message[7]));​
​
if(size - kSubtitleHeaderSize != length) {​
return false;​
}​
​
if(length) {​
subtitles.assign((char*)message + kSubtitleHeaderSize, length);​
} else {​
subtitles = "";​
}​
return true;​
}​
​
//解析​
void ParseData(const std::string& msg) {​
// 解析 JSON 字符串​
nlohmann::json json_data = nlohmann::json::parse(subtitles);​
// 存储解析后的数据​
std::vector<SubtitleMsgData> subtitles;​
// 遍历 JSON 数据并填充结构体​
for (const auto& item : json_data["data"]) {​
SubtitleMsgData subData;​
subData.definite = item["definite"];​
subData.language = item["language"];​
subData.paragraph = item["paragraph"];​
subData.sequence = item["sequence"];​
subData.text = item["text"];​
subData.userId = item["userId"];​
subtitles.push_back(subData);​
}​
}​
​
​
​
​
停止字幕生成​
  • 单个房间停止字幕生成:调用 stopSubtitle 接口停止。​
  • 任务自动停止:为避免资源占用,若系统检测到房间内连续 3 分钟无音频上行,将自动停止房间内的实时字幕任务。​
字幕数据二进制格式​
通过客户端和服务端接收的字幕回调,解码后的 message 字段均遵循以下二进制格式。​
​Image​​
​
​
参数名​
类型​
描述​
magic number​
binary​
消息格式标识,固定为 subc。​
length​
binary​
字幕消息(subtitle_message)的长度,单位为 bytes,存放方式为大端序(Big-Endian)。​
subtitle_message​
binary​
字幕详细信息,格式参看subtitle_message 。​
​
subtitle_message​
​
​
参数名​
类型​
描述​
type​
String​
消息类型,固定为 subtitle(表示消息类型为字幕)。​
data​
data​
字幕详细信息,包含字幕的文本、语言、说话人 ID 等具体信息。​
​
data​
​
​
参数名​
类型​
描述​
text​
String​
字幕文本。​
language​
String​
字幕语言。​
userId​
String​
说话人 ID。​
sequence​
Int​
字幕序号。​
definite​
Boolean​
字幕是否为完整的一句话:​
  • true:是​
  • false:否​
paragraph​
Boolean​
字幕是否为一段完整的文本:​
  • true:是​
  • false:否​
​
字幕使用建议​
实时 UI 展示​
​
​
字段组合状态​
UI 处理​
paragraph: false、definite: false​
用序号大的字幕覆盖序号小的。​
paragraph: false、definite: true​
重新开始新的一句话,覆盖前一句话。​
paragraph: true​
此时如果继续解析显示字幕,字幕会重复显示。​
​
存储字幕​
仅在解析到 paragraph: true 且 definite: true 时存储,减少存储的数据量,并确保保存的字幕是完整的。​
相关 API​
​
​
功能​
Android​
iOS​
macOS​
Windows​
Linux​
服务端 OpenAPI​
生成字幕​
停止字幕生成​
接收字幕结果​
通过 startSubtitle的 DistributionMode 字段指定​
​
FAQ​
  • **Q1:同一个房间内,不同用户可以分别调用服务端 OpenAPI **** StartSubtitle ** 吗?会互相覆盖吗?​
  • 可以,但需要保证每次调用使用不同的 TaskId。只要 AppId + RoomId + TaskId 唯一,不同字幕任务的配置不会因为 RoomId 相同而互相覆盖。​
  • Q2:服务端最多可以开启多少个实时字幕任务?​
  • 单账号下 OpenAPI QPS 不得超过 60。字幕任务的实际并发能力还受 RTC 资源、流式语音识别、机器翻译等依赖服务的并发额度影响。​
  • Q3:实时字幕无法生成时,客户端如何感知?​
  • 客户端调用 startSubtitle 接入时,可通过 onSubtitleStateChanged 监听字幕状态和错误码;服务端调用 StartSubtitle 接入时,请结合接口返回、客户端状态回调和业务服务端回调日志排查。​
​
最近更新时间:2026.10.08 11:23:36
这个页面对您有帮助吗?
有用
有用
无用
无用