Skip to content

安装与测试

本文档介绍如何集成火山云语音服务并完成基础测试。火山引擎提供多端 SDK,本文以 Web 端(@volcengine/rtc)为例说明集成流程。

前置准备

开始集成前,请确保已完成火山引擎服务开通和凭证配置。详细步骤参考快速开始 - 火山引擎凭证

需要准备的凭证:

凭证用途
AppId / AppKeyRTC 房间连接和 Token 生成
AccessKeyId / SecretKeyOpenAPI 请求签名
ASR AppId语音识别服务
TTS AppId / TTS Token / TTS ResourceId语音合成服务

认证代理服务

客户端加入 RTC 房间需要 Token,而 Token 由 AppKey 生成;启动语音会话需要调用 StartVoiceChat API,而该 API 需要 AccessKey 签名。这些密钥都不能暴露给客户端,因此需要搭建一个代理服务来处理认证。

代理服务负责:

  • 使用 AppKey 生成 RTC Token
  • 使用 AccessKey 调用火山引擎 OpenAPI
  • Token 和房间信息返回给客户端

生成 RTC Token

Token 使用 AppKey 通过 HMAC-SHA256 算法生成:

语言参考实现
Node.js / Buntoken.ts
typescript
import { AccessToken, Privileges } from './rtctoken'

const token = new AccessToken(appId, appKey, roomId, userId)
token.addPrivilege(Privileges.PrivPublishStream, expireTime)
const tokenString = token.serialize()  // 返回给客户端

调用火山引擎 OpenAPI

StartVoiceChatStopVoiceChat 等 API 需要使用 AccessKeyIdSecretKey 进行 V4 签名。官方 OpenAPI SDK 提供 Signer 类帮助生成签名头:

bash
# Node.js / Bun
npm install @volcengine/openapi

# Python
pip install volcengine-python-sdk

# Go
go get github.com/volcengine/volc-sdk-golang
typescript
// Node.js 示例
import { Signer } from '@volcengine/openapi'

const body = { AppId: appId, RoomId: roomId, /* ... */ }

// 构造请求数据
const openApiRequestData = {
  region: 'cn-north-1',
  method: 'POST',
  params: {
    Action: 'StartVoiceChat',
    Version: '2024-12-01',
  },
  headers: {
    Host: 'rtc.volcengineapi.com',
    'Content-Type': 'application/json',
  },
  body,
}

// 创建 Signer 并添加认证头
const signer = new Signer(openApiRequestData, 'rtc')
signer.addAuthorization({
  accessKeyId: process.env.ACCESS_KEY_ID,
  secretKey: process.env.SECRET_KEY,
})

// 发起请求(headers 已包含签名)
const response = await fetch(
  'https://rtc.volcengineapi.com?Action=StartVoiceChat&Version=2024-12-01',
  {
    method: 'POST',
    headers: openApiRequestData.headers,
    body: JSON.stringify(body),
  }
)

详细签名规范参考:火山引擎 V4 签名算法

API 设计示例

代理服务需要暴露接口供客户端调用:

typescript
// 获取场景配置 - 返回 Token 和房间信息
GET /api/scenes
Response: {
  scenes: [{
    id: string,
    rtcConfig: { appId: string, roomId: string, userId: string, token: string }
  }]
}

// 启动语音会话
POST /api/voice/start
Request:  { sceneId: string }
Response: { success: boolean }

// 停止语音会话
POST /api/voice/stop
Request:  { sceneId: string }
Response: { success: boolean }

服务端实现说明:

  • 场景配置:服务端在初始化时为每个场景生成 roomId(UUID)和 userId,并使用 AppKey 生成对应的 RTC Token(24 小时有效)。客户端通过 /api/scenes 获取这些信息用于加入 RTC 房间。
  • Token 用途:客户端调用 RTC SDK 的 joinRoom 方法时需要传入 Token 进行身份认证。
  • 启动/停止语音会话:服务端根据 sceneId 查找对应的场景配置,获取 roomId 等参数后调用火山引擎 OpenAPI(StartVoiceChatStopVoiceChat)。

Web 端集成

火山引擎提供 @volcengine/rtc SDK 用于 Web 端集成。客户端与服务端的交互流程如下:

调用流程

安装 SDK

bash
npm install @volcengine/rtc

如需 AI 降噪功能,SDK 已内置 @volcengine/rtc/extension-ainr 扩展。

基础集成流程

1. 获取场景配置

使用 RTC SDK 前,先调用服务端接口获取场景配置,包含 Token 和房间信息:

typescript
// 调用服务端 API 获取场景配置
const response = await fetch('/api/scenes')
const { scenes } = await response.json()

// 选择目标场景
const scene = scenes.find(s => s.id === 'your-scene-id') || scenes[0]
const { appId, roomId, token, userId } = scene.rtcConfig

2. 创建 RTC 引擎

typescript
import VERTC, { RoomProfileType, MediaType } from '@volcengine/rtc'

// 使用服务端返回的 appId 创建引擎实例
const engine = VERTC.createEngine(appId)

3. 注册事件监听

typescript
// 监听错误
engine.on(VERTC.events.onError, (event) => {
  console.error('RTC error:', event.errorCode)
})

// 监听远端用户发布流(AI 语音回复)
engine.on(VERTC.events.onUserPublishStream, async (event) => {
  const { userId, mediaType } = event
  // 订阅远端音频流
  await engine.subscribeStream(userId, mediaType)
})

// 监听二进制消息(字幕、状态等)
engine.on(VERTC.events.onRoomBinaryMessageReceived, (event) => {
  const { message } = event
  // message 为 ArrayBuffer,需解析 TLV 格式
  // 包含 ASR 识别结果、TTS 文本、智能体状态等
})

4. 加入房间

typescript
// 使用步骤 1 获取的 token、roomId、userId 加入房间
await engine.joinRoom(
  token,
  roomId,
  {
    userId: userId,
    extraInfo: JSON.stringify({
      call_scene: 'RTC-AIGC',
      user_name: userId,
    }),
  },
  {
    isAutoPublish: false,
    isAutoSubscribeAudio: false,
    roomProfileType: RoomProfileType.chat,
  }
)

5. 开启麦克风并发布音频

typescript
// 开启麦克风采集
await engine.startAudioCapture()

// 发布音频流到房间
await engine.publishStream(MediaType.AUDIO)

6. 启动语音会话

发布音频流后,调用服务端 API 启动 AI 语音会话:

typescript
// 启动语音会话
await fetch('/api/voice/start', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({ sceneId: scene.id }),
})

此时语音交互已经开始,用户说话会被 ASR 识别,LLM 处理后通过 TTS 播放回复。

7. 离开房间

typescript
// 停止发布
await engine.unpublishStream(MediaType.AUDIO)

// 停止采集
await engine.stopAudioCapture()

// 离开房间
await engine.leaveRoom()

// 销毁引擎
VERTC.destroyEngine(engine)

// 调用服务端 API 停止语音会话
await fetch('/api/voice/stop', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({ sceneId: scene.id }),
})

AI 降噪(可选)

火山引擎 RTC SDK 内置 AI 降噪扩展,可有效过滤环境噪音:

typescript
import RTCAIAnsExtension, { AnsMode } from '@volcengine/rtc/extension-ainr'

// 创建并注册扩展
const aiAnsExtension = new RTCAIAnsExtension()
engine.registerExtension(aiAnsExtension)

// 检查是否支持
const supported = await aiAnsExtension.isSupported()
if (supported) {
  // 设置降噪模式:LOW / MEDIUM / HIGH
  await aiAnsExtension.setAnsMode(AnsMode.MEDIUM)
  // 启用降噪
  aiAnsExtension.enable()
}

获取远端音频流

订阅远端流后,可获取 MediaStream 用于播放:

typescript
import { StreamIndex } from '@volcengine/rtc'

// 获取远端用户的音频轨道
const audioTrack = engine.getRemoteStreamTrack(userId, StreamIndex.STREAM_INDEX_MAIN, 'audio')

// 创建 MediaStream 并播放
const stream = new MediaStream()
if (audioTrack) {
  stream.addTrack(audioTrack)
}

// 绑定到 audio 元素播放
const audioElement = document.querySelector('audio')
audioElement.srcObject = stream

其他端 SDK

火山引擎 RTC SDK 支持软件应用和硬件设备两类场景。

软件应用

详见:集成实时对话式 AI(软件应用)

平台SDK文档
Web@volcengine/rtcWeb SDK 文档
iOSVolcEngineRTCiOS SDK 文档
AndroidVolcEngineRTCAndroid SDK 文档
WindowsVolcEngineRTCWindows SDK 文档
macOSVolcEngineRTCmacOS SDK 文档
LinuxVolcEngineRTCLinux SDK 文档
Fluttervolc_engine_rtcFlutter SDK 文档
Electron@volcengine/rtcElectron SDK 文档

硬件设备

详见:集成实时对话式 AI(嵌入式硬件)

支持嵌入式 Linux、RTOS、Android 等硬件平台。硬件端 SDK 需联系火山引擎技术支持获取。

测试验证

验证 RTC 连接

成功加入房间后,可通过事件确认:

typescript
engine.on(VERTC.events.onUserJoined, (event) => {
  console.log('User joined:', event.userInfo.userId)
})

验证语音识别

对着麦克风说话,通过 onRoomBinaryMessageReceived 事件接收二进制消息。消息采用 TLV 格式编码,包含:

  • 字幕消息:ASR 识别结果和 LLM 回复文本
  • 状态消息:智能体状态(listening / thinking / speaking)
  • Function Call:工具调用请求

验证语音合成

AI 回复会通过远端音频流播放。确保:

  1. 已监听 onUserPublishStream 事件
  2. 已调用 subscribeStream 订阅远端音频
  3. 已将音频轨道绑定到 <audio> 元素

常见问题

连接与认证

问题可能原因解决方案
Token 无效 (token_error)Token 过期或参数不匹配检查生成 Token 时的 UserId、RoomId 是否与使用时一致,或重新生成 Token
无法加入房间网络问题或 AppId 错误检查网络连接,确认 AppId 正确
Invalid 'Authorization' headerAK/SK 配置错误检查服务端的 AccessKeyId 和 SecretKey 是否正确
跨服务调用失败未配置跨服务授权在 RTC 控制台完成跨服务授权配置

智能体启动

问题可能原因解决方案
StartVoiceChat 失败签名错误或参数缺失检查服务端 API 签名,确认必需参数已填写
The task has been started 报错RoomId/UserId 固定时重复调用先调用 StopVoiceChat,再重新调用 StartVoiceChat
一直停留在 "AI 准备中"权限未授予 / 参数错误 / 服务欠费1. 检查控制台权限配置
2. 检查参数大小写、类型
3. 确认服务已开通且余额充足
数字人一直停留在准备中并发限制或配置错误1. 检查数字人 AppId/Token 是否正确
2. 确认未超过并发限制

设备与媒体

问题可能原因解决方案
麦克风/摄像头开启失败非安全上下文确保页面使用 localhosthttps 协议访问
设备权限获取失败浏览器未授权参考 Web 排查设备权限问题
ASR 无识别结果麦克风未授权或服务未开通检查浏览器麦克风权限,确认 ASR 服务已开通
TTS 无声音未订阅远端音频确保调用了 subscribeStream 订阅远端音频流

模型配置

问题解决方案
如何使用第三方模型 / Coze Bot在 LLMConfig 中配置对应的模型参数,Mode 设为 CustomLLM 并填写回调地址
对话无反馈检查 LLM 配置是否正确,CustomLLM 模式需确保回调服务正常运行

相关资源