Files
Genarrative/docs/technical/VOLCENGINE_SPEECH_STREAMING_INTEGRATION_2026-05-08.md
2026-05-10 13:18:46 +08:00

7.6 KiB
Raw Blame History

火山引擎大模型语音流式接入 2026-05-08

背景

本次接入火山引擎豆包语音能力,覆盖两类运行态语音链路:

  1. 大模型流式语音识别 ASR使用 WebSocket 双向流式优化模式。
  2. 大模型语音合成 TTS使用实时交互场景的 WebSocket 双向流式接口,并提供一次性文本输入的 HTTP SSE 单向流式接口。

语音能力属于外部副作用,按 server-rs DDD 分层落在 platform-speechapi-server 只负责平台账号鉴权、环境配置校验、协议代理和错误映射。前端不得直接持有火山引擎密钥。

官方文档依据

  • ASRhttps://www.volcengine.com/docs/6561/1354869?lang=zh
  • TTS WebSocket 双向流式:https://www.volcengine.com/docs/6561/1329505?lang=zh
  • TTS WebSocket 单向流式:https://www.volcengine.com/docs/6561/1719100?lang=zh
  • TTS HTTP Chunked / SSE 单向流式:https://www.volcengine.com/docs/6561/1598757?lang=zh

环境变量

真实值只能放在本地未提交的 .env.local / .env.secrets.local 或生产服务器环境文件,禁止提交到仓库。

VOLCENGINE_SPEECH_API_KEY=
VOLCENGINE_SPEECH_APP_ID=
VOLCENGINE_SPEECH_ACCESS_KEY=
VOLCENGINE_SPEECH_ASR_RESOURCE_ID=volc.seedasr.sauc.concurrent
VOLCENGINE_SPEECH_TTS_RESOURCE_ID=seed-tts-2.0
VOLCENGINE_SPEECH_REQUEST_TIMEOUT_MS=180000
VOLCENGINE_SPEECH_ASR_WS_URL=wss://openspeech.bytedance.com/api/v3/sauc/bigmodel_async
VOLCENGINE_SPEECH_TTS_BIDIRECTION_WS_URL=wss://openspeech.bytedance.com/api/v3/tts/bidirection
VOLCENGINE_SPEECH_TTS_SSE_URL=https://openspeech.bytedance.com/api/v3/tts/unidirectional/sse

配置规则:

  1. 优先使用新版控制台 VOLCENGINE_SPEECH_API_KEY,上游请求头写 X-Api-Key
  2. 若只配置旧版控制台信息,则使用 VOLCENGINE_SPEECH_APP_IDVOLCENGINE_SPEECH_ACCESS_KEY,上游请求头写 X-Api-App-KeyX-Api-Access-Key
  3. ASR 默认资源 ID 选 ASR 2.0 并发版;如账号是小时版,部署时改成 volc.seedasr.sauc.duration
  4. TTS 默认资源 ID 选 seed-tts-2.0;旧音色或 1.0 计费资源由部署环境覆盖。

ASR 协议边界

客户端连接:

GET /api/speech/volcengine/asr/stream
Authorization: Bearer <Genarrative JWT>

浏览器与 api-server 使用 WebSocket 二进制帧透传:

  1. 首包必须是 JSON 文本,表示 ASR full client request 的业务参数。
  2. 后续二进制帧是音频分片。
  3. 浏览器发送文本帧 {"type":"finish"} 时,后端把最后一个空音频包按负包发送给火山。
  4. 后端把火山 full server response 解析成 JSON 文本帧发回浏览器。

ASR 上游连接:

wss://openspeech.bytedance.com/api/v3/sauc/bigmodel_async
X-Api-Key: <VOLCENGINE_SPEECH_API_KEY>
X-Api-Resource-Id: <VOLCENGINE_SPEECH_ASR_RESOURCE_ID>
X-Api-Request-Id: <uuid>
X-Api-Sequence: -1

ASR 二进制协议:

  1. 4 字节 header大端整数。
  2. full client requestmessage type 0b0001JSON 序列化gzip 压缩。
  3. audio only requestmessage type 0b0010raw payloadgzip 压缩。
  4. 最后一包音频使用 flags 0b0010
  5. full server responsemessage type 0b1001payload 为 gzip JSON。
  6. error responsemessage type 0b1111payload 为错误 JSON 或 UTF-8 文本。

首包参数由前端传入,但后端会兜底:

{
  "user": { "uid": "current-user-id" },
  "audio": {
    "format": "pcm",
    "codec": "raw",
    "rate": 16000,
    "bits": 16,
    "channel": 1
  },
  "request": {
    "model_name": "bigmodel",
    "enable_itn": true,
    "enable_punc": true,
    "show_utterances": true,
    "result_type": "full"
  }
}

TTS 协议边界

WebSocket 双向流式

客户端连接:

GET /api/speech/volcengine/tts/bidirection
Authorization: Bearer <Genarrative JWT>

浏览器向后端发送 JSON 文本帧:

{ "type": "start_connection" }
{ "type": "start_session", "sessionId": "...", "payload": { "user": {}, "req_params": {} } }
{ "type": "task_request", "sessionId": "...", "payload": { "req_params": { "text": "..." } } }
{ "type": "finish_session", "sessionId": "..." }
{ "type": "finish_connection" }

后端转成火山 WebSocket V3 二进制帧,并把上游返回帧统一解析成 JSON 文本或音频二进制帧回传浏览器。

TTS 双向上游连接:

wss://openspeech.bytedance.com/api/v3/tts/bidirection
X-Api-Key: <VOLCENGINE_SPEECH_API_KEY>
X-Api-Resource-Id: <VOLCENGINE_SPEECH_TTS_RESOURCE_ID>
X-Api-Connect-Id: <uuid>

V3 事件帧:

  1. Full-client request + event number 用于 StartConnectionStartSessionTaskRequestFinishSessionFinishConnection
  2. Full-server response + event number 用于 ConnectionStartedSessionStartedSessionFinished 等状态事件。
  3. Audio-only response + event number 用于返回音频二进制。
  4. 错误帧必须转成结构化 JSON 错误,不把上游密钥或完整请求头写入日志。

HTTP SSE 单向流式

客户端请求:

POST /api/speech/volcengine/tts/sse
Authorization: Bearer <Genarrative JWT>
Content-Type: application/json
Accept: text/event-stream

请求体:

{
  "text": "你好,欢迎来到百梦。",
  "speaker": "zh_female_cancan_mars_bigtts",
  "audioParams": {
    "format": "mp3",
    "sampleRate": 24000
  }
}

后端转换为火山 HTTP SSE 请求体:

{
  "user": { "uid": "current-user-id" },
  "req_params": {
    "text": "...",
    "speaker": "...",
    "audio_params": {
      "format": "mp3",
      "sample_rate": 24000
    }
  }
}

上游 SSE 的常见事件:

  1. 352TTSResponsedata 为 base64 音频片段。
  2. 351TTSSentenceEndsentence 为字幕或时间戳数据。
  3. 152SessionFinish合成完成可含 usage.text_words
  4. 153SessionFailed合成失败。

后端保持 SSE 形态透传,但会补齐平台 requestId 与上游 X-Tt-Logid 作为排障信息。

api-server 路由

方法 路由 说明
GET /api/speech/volcengine/config 返回前端可见的默认资源和推荐音频参数,不返回密钥
GET /api/speech/volcengine/asr/stream ASR WebSocket 双向流式代理
GET /api/speech/volcengine/tts/bidirection TTS WebSocket 双向流式代理
POST /api/speech/volcengine/tts/sse TTS HTTP SSE 单向流式代理

所有路由必须走 require_bearer_auth

验收

代码级验收:

cargo fmt --manifest-path server-rs/Cargo.toml --all --check
cargo test --manifest-path server-rs/Cargo.toml -p platform-speech
cargo test --manifest-path server-rs/Cargo.toml -p api-server volcengine_speech
cargo check --manifest-path server-rs/Cargo.toml -p api-server
npm run check:encoding

联调验收:

  1. 启动 npm run api-server
  2. 检查 /healthz 返回 200。
  3. 未登录访问语音路由返回 401。
  4. 已登录后 /api/speech/volcengine/config 不返回任何密钥字段。
  5. ASR WebSocket 发送首包和 200ms PCM 分片后能收到识别 JSON。
  6. TTS SSE 能收到 352 音频事件与最终 152 完成事件。
  7. TTS 双向 WebSocket 能复用连接完成至少一个 session。

注意事项

  1. 不把 VOLCENGINE_ACCESS_KEY_IDVOLCENGINE_SECRET_ACCESS_KEY、API Key、Access Token 或完整 Authorization 写入文档、日志、测试快照或前端状态。
  2. 中文语音默认使用 16k 单声道 PCM ASRTTS 默认使用 24k mp3运行时可按玩法需要改为 pcm。
  3. 火山返回的 X-Tt-Logid 是排障关键信息,应记录 logid但不能记录密钥。
  4. 语音流式能力是平台副作用,不涉及 SpacetimeDB 表结构变更,本次无需修改 migration.rs