WebSocket接入文档

实时语音翻译 WebSocket 客户端接入文档

通过本文,您可以通过 WebSocket 接入实时语音翻译服务。

接口要求

内容 说明
请求协议 wss(WebSocket Protocol Version 13
请求地址 wss://rtvt-cn-app.ilivedata.com/gate/websocket
请求行 GET /gate/websocket HTTP/1.1
接口鉴权 签名机制,详情请参照 Token 鉴权,使用 HMAC 方法
字符编码 UTF-8
数据格式 控制消息使用 JSON 格式,音频数据使用 Binary 格式
音频格式 单声道、16kHz、16bit

1. 建立 WebSocket 连接

连接时将所有配置参数通过 URL 传递,一次完成连接和语音识别配置:

serverURL := "wss://rtvt-cn-app.ilivedata.com/gate/websocket"
pid := 81700002 // 项目 ID
ts := time.Now().Unix() // 当前时间戳(秒)
token := genHMACToken(pid, ts, secretKey) // 生成 token,见下方方法

// 构建包含完整配置的 URL
url := fmt.Sprintf("%s?pid=%d&token=%s&ts=%d&version=1.0&srcLanguage=%s&destLanguage=%s&asrResult=%t&asrTempResult=%t&transResult=%t&ttsResult=%t&codec=%d&userId=%s&vadSilenceTime=%s&asrModel=%s&hotWordListId=%s",
    serverURL, pid, token, ts,
    "zh",         // 源语言
    "en",         // 目标语言
    true,         // 返回最终 ASR 结果
    true,         // 返回临时 ASR 结果
    true,         // 返回翻译结果
    false,        // TTS 结果
    0,            // 编码格式(0=PCM)
    "test_user",  // 用户 ID
    "1000",       // VAD 静音时间(ms)
    "ViiTor",       // ASR 大模型;不启用时传空字符串或省略参数
    "<热词表ID>") // 热词表 ID;不使用热词时传空字符串或省略参数

语音识别配置

语音识别配置通过连接 URL 中的参数传入。

URL 参数说明

参数 类型 描述 默认值 示例值
srcLanguage string 源语言代码 "zh" "zh"
destLanguage string 目标语言代码 "en" "en"
asrResult bool 是否返回最终 ASR 结果 true "true"
asrTempResult bool 是否返回临时 ASR 结果 true "true"
transResult bool 是否返回翻译结果 true "true"
ttsResult bool 是否返回 TTS 结果 false "false"
codec int 音频编码格式,0=PCM,1=Opus 0 "0"
userId string 用户自定义 ID "test_user" "user123"
vadSilenceTime string VAD 静音时间(ms) "1000" "1000"
srcAltLanguage string[] 备选源语言列表 空数组 ["en","ja"]
asrModel string 启用 ViiTor ASR大模型,空值或不传保持默认识别流程 空字符串 "ViiTor"
hotWordListId string 热词表 ID 空字符串 "<热词表ID>"

Token 生成方法

func genHMACToken(pid int32, ts int64, key string) string {
    content := fmt.Sprintf("%d:%d", pid, ts)
    keyb, _ := base64.StdEncoding.DecodeString(key)
    h := hmac.New(sha256.New, keyb)
    h.Write([]byte(content))
    return base64.StdEncoding.EncodeToString(h.Sum(nil))
}

连接示例

conn, _, err := websocket.DefaultDialer.Dial(url, nil)

鉴权结果

如果握手成功,会返回 HTTP 101 状态码,表示协议升级成功;如果握手失败,则根据错误类型返回对应的 HTTP 状态码,并携带错误描述信息:

HTTP Code 说明 错误描述信息 解决方法
401 缺少参数或参数错误 {"message":"Missing parameters"} 检查是否缺少参数
401 签名参数解析失败 {"message":"failed to parse parameters"} 检查签名参数是否完整、正确,特别确认复制的 secret 是否正确
401 签名校验失败 {"message":"failed to verify"} 检查 secret 是否正确、签名参数是否按协议要求拼接,以及生成的 Base64 签名是否正常

2. 登录/握手

WebSocket 连接即登录,连接建立后直接进入业务流程。


3. 流式发送音频数据

使用 WebSocket Binary 消息直接发送原始音频字节:

// 读取音频数据(例如从文件或麦克风)
audioData := make([]byte, 640) // 20ms PCM 数据
err := conn.WriteMessage(websocket.BinaryMessage, audioData)

音频格式要求

  • 采样率:16kHz
  • 声道:单声道
  • 位深:16bit
  • 每帧:640 字节(20ms)
  • 格式:PCM 原始音频数据

4. 接收识别与翻译结果

服务端会返回 4 种类型的结果消息:

4.1 最终识别结果(recognizedResult)

type RecognizedResult struct {
    Method   string `json:"method"`           // "recognizedResult"
    StreamId int64  `json:"streamId,string"`  // 会话流 ID(JSON 中为字符串)
    StartTs  int64  `json:"startTs,string"`   // 句子开始时间(毫秒,JSON 中为字符串)
    EndTs    int64  `json:"endTs,string"`     // 句子结束时间(毫秒,JSON 中为字符串)
    Asr      string `json:"asr"`              // 识别文本
    Lang     string `json:"lang"`             // 语种
    RecTs    int64  `json:"recTs,string"`     // 识别时间戳(JSON 中为字符串)
    TaskId   int64  `json:"taskId,string"`    // 结果序号(JSON 中为字符串)
}

4.2 临时识别结果(recognizedTempResult)

type RecognizedResult struct {
    Method   string `json:"method"`           // "recognizedTempResult"
    StreamId int64  `json:"streamId,string"`  // 会话流 ID(JSON 中为字符串)
    StartTs  int64  `json:"startTs,string"`   // 句子开始时间(毫秒,JSON 中为字符串)
    EndTs    int64  `json:"endTs,string"`     // 0(临时结果无结束时间,JSON 中为字符串)
    Asr      string `json:"asr"`              // 识别文本
    Lang     string `json:"lang"`             // 语种
    RecTs    int64  `json:"recTs,string"`     // 识别时间戳(JSON 中为字符串)
    TaskId   int64  `json:"taskId,string"`    // 结果序号(JSON 中为字符串)
}

4.3 最终翻译结果(translatedResult)

type TranslatedResult struct {
    Method   string `json:"method"`           // "translatedResult"
    StreamId int64  `json:"streamId,string"`  // 会话流 ID(JSON 中为字符串)
    StartTs  int64  `json:"startTs,string"`   // 句子开始时间(毫秒,JSON 中为字符串)
    EndTs    int64  `json:"endTs,string"`     // 句子结束时间(毫秒,JSON 中为字符串)
    Trans    string `json:"trans"`            // 翻译文本
    Lang     string `json:"lang"`             // 目标语种
    RecTs    int64  `json:"recTs,string"`     // 识别时间戳(JSON 中为字符串)
    TaskId   int64  `json:"taskId,string"`    // 结果序号(JSON 中为字符串)
}

4.4 临时翻译结果(translatedTempResult)

type TranslatedResult struct {
    Method   string `json:"method"`           // "translatedTempResult"
    StreamId int64  `json:"streamId,string"`  // 会话流 ID(JSON 中为字符串)
    StartTs  int64  `json:"startTs,string"`   // 句子开始时间(毫秒,JSON 中为字符串)
    EndTs    int64  `json:"endTs,string"`     // 0(临时结果无结束时间,JSON 中为字符串)
    Trans    string `json:"trans"`            // 翻译文本
    Lang     string `json:"lang"`             // 目标语种
    RecTs    int64  `json:"recTs,string"`     // 识别时间戳(JSON 中为字符串)
    TaskId   int64  `json:"taskId,string"`    // 结果序号(JSON 中为字符串)
}

重要说明

  • JSON 字符串格式:所有数值字段(StreamIdStartTsEndTsRecTsTaskId)在 JSON 中以字符串形式传输。使用 ,string 标签可确保跨语言兼容,并避免大整数精度丢失。
  • 消息类型区分:通过 Method 字段区分消息类型。
    • recognizedResult / translatedResult:最终识别/翻译结果,包含完整的时间信息。
    • recognizedTempResult / translatedTempResult:临时识别/翻译结果,EndTs 通常为 0。

5. 结束语音识别

发送 voiceEnd 消息:

voiceEndReq := map[string]interface{}{
    "method": "voiceEnd",
}
msgBytes, _ := json.Marshal(voiceEndReq)
err := conn.WriteMessage(websocket.TextMessage, msgBytes)

说明:

  • 发送后服务端会处理剩余的音频数据并返回最终结果。
  • 建议等待结果返回后再关闭连接。

6. 断开连接与资源释放

  • 发送 voiceEnd 后,可关闭 WebSocket 连接,释放资源。

7. 完整流程时序图

sequenceDiagram
    participant Client
    participant Server

    Client->>Server: WebSocket 连接(带鉴权和语音识别参数)
    loop 音频流传输
        Client->>Server: Binary 音频数据(原始字节)
        Server-->>Client: recognizedTempResult(临时识别结果)
        Server-->>Client: translatedTempResult(临时翻译结果)
        Server-->>Client: recognizedResult(最终识别结果)
        Server-->>Client: translatedResult(最终翻译结果)
    end

    Client->>Server: voiceEnd(结束消息)
    Server-->>Client: 最终结果处理完成

    Client-->>Server: 断开连接

8. 使用示例(Golang)

完整使用示例

// 1. 创建客户端
client := NewASRClient()
defer client.Close()

// 2. 设置语音识别参数(模型和热词表可独立留空)
client.SetVoiceStartParams("zh", "en", "ViiTor", "<热词表ID>")
client.SetSrcAltLanguages([]string{"en", "ja"})

// 3. 构建认证 URL(包含语音识别配置)
ts := time.Now().Unix()
token := genHMACToken(pid, ts, secretKey)
baseURL := fmt.Sprintf("%s?pid=%d&token=%s&ts=%d&version=1.0", serverURL, pid, token, ts)

// 4. 建立连接
err := client.Connect(baseURL)
if err != nil {
    log.Fatal("连接失败:", err)
}

// 5. 发送音频数据
for {
    audioData := make([]byte, 640) // 20ms PCM 数据
    // 从麦克风或文件读取音频数据
    n, err := audioSource.Read(audioData)
    if err != nil {
        break // 音频结束
    }

    // 直接发送原始音频字节
    err = client.SendVoiceData(audioData[:n])
    if err != nil {
        log.Printf("发送音频失败: %v", err)
        break
    }

    time.Sleep(20 * time.Millisecond) // 20ms 间隔
}

// 6. 结束识别
err = client.EndVoiceRecognition()
if err != nil {
    log.Printf("结束识别失败: %v", err)
}

如需进一步字段说明或异常处理细节,请联系云上曲率技术支持。