@koi-video/voice-realtime-sdk
v4.1.0
Published
Voice realtime ChatClient: REST (webrtc/v1 start/stop) + Web RTC
Readme
@koi-video/voice-realtime-sdk
浏览器端实时语音 SDK:HTTP 会话(/start、/stop)配合 Robot-Key / Robot-Token,以及 WebRTC(麦克风、远端音频、流消息)。Agora Web SDK 为本包依赖,随安装一并拉取。
Installation
pnpm add @koi-video/voice-realtime-sdkimport { ChatClient, VoiceEvents } from '@koi-video/voice-realtime-sdk';| 导出 | 说明 |
|------|------|
| ChatClient | 主客户端。 |
| VoiceEvents | 事件名常量(见 Events)。 |
最小流程(方法与事件)
import { ChatClient, VoiceEvents } from '@koi-video/voice-realtime-sdk';
const client = new ChatClient(
{
robotKey: process.env.ROBOT_KEY,
robotToken: process.env.ROBOT_TOKEN
},
{
userName: 'demo-user-1'
}
);
client.on(VoiceEvents.SESSION_CREATED, ({ sessionId }) => {
console.log('SESSION_CREATED', sessionId);
});
client.on(VoiceEvents.SESSION_STARTED, ({ sessionId }) => {
console.log('SESSION_STARTED', sessionId);
});
client.on(VoiceEvents.SESSION_ENDED, ({ sessionId, reason }) => {
console.log('SESSION_ENDED', sessionId, reason);
});
client.on(VoiceEvents.USER_MESSAGE, ({ sessionId, content, segmentId, raw }) => {
console.log('user:', content, segmentId, raw);
});
client.on(VoiceEvents.ROBOT_MESSAGE, ({ sessionId, content, segmentId, raw }) => {
console.log('bot:', content, segmentId, raw);
});
client.on(VoiceEvents.INTERRUPT, ({ sessionId, code, message, raw }) => {
console.log('INTERRUPT', sessionId, code, message, raw);
});
client.on(VoiceEvents.AUDIO_MUTED, ({ sessionId }) => {
console.log('AUDIO_MUTED', sessionId);
});
client.on(VoiceEvents.AUDIO_UNMUTED, ({ sessionId }) => {
console.log('AUDIO_UNMUTED', sessionId);
});
client.on(VoiceEvents.ERROR, err => {
console.error(err.code, err.message);
});
client.on(VoiceEvents.ALL, (eventName, data) => {
console.log('ALL', eventName, data);
});
const sessionId = await client.startVoiceChat();
client.interrupt();
await client.setAudioEnabled({ bool: false });
await client.setAudioEnabled({ bool: true });
await client.stopVoiceChat();初始化与启动参数
new ChatClient(...) 用于保存客户端级配置:鉴权信息和当前用户标识。它不会发起通话;每次通话的参数需要传给 startVoiceChat(options?)。
startVoiceChat 的传参示例:
const sessionId = await client.startVoiceChat({
extraParams: {
variables: {
varA: ''
}
}
});也支持直接使用接口字段名 extra_params 作为兼容写法。
| SDK 参数名 | 类型 | 是否必填 | /start 字段 | 说明 |
|------|------|------|------|------|
| welcome | string | 否 | welcome | 欢迎语 |
| maxDuration | number | 否 | max_duration | 最大通话时长 |
| clientType | string | 否 | client_type | 客户端类型,默认 web_sdk |
| segmentCode | string | 否 | segment_code | 业务分段编码 |
| extraParams | object | 否 | extra_params | 原样透传的扩展参数 |
user_name 来自初始化时的 userName,version 由 SDK 自动填充,这两个字段无需在 startVoiceChat 中传入。
Events
使用 client.on(VoiceEvents.XXX, handler) 或 client.on(VoiceEvents.ALL, (eventName, data) => ...)。
VoiceEvents
| 常量 | 触发 / 载荷 |
|------|----------------|
| SESSION_CREATED | /start 成功且 RTC 就绪 — { sessionId }。 |
| SESSION_STARTED | 紧接 SESSION_CREATED,相同 { sessionId }。 |
| SESSION_ENDED | 挂断、RTC 断开、远端超时等 — { sessionId, reason }。含 user_stop、disconnected、remote_join_timeout、remote_rejoin_timeout 等。 |
| USER_MESSAGE | 流 topic === 'chat',用户 — { sessionId, content, segmentId?, timestamp?, raw }。raw 为该条消息的完整服务端 JSON;content / segmentId / timestamp 为便于使用的派生字段。 |
| ROBOT_MESSAGE | 流 topic === 'chat',助手 — 同上。 |
| AUDIO_MUTED / AUDIO_UNMUTED | setAudioEnabled 之后 — { sessionId }。 |
| INTERRUPT | 流 topic === 'interrupt' — { sessionId, code, message, raw }。 |
| ERROR | 接口 / RTC / 解析错误 — code、message 等。 |
| ALL | 所有事件:(eventName, data)。 |
订阅 ALL 时,第一个参数还可能是 FLOW_DEBUG、SIDE_INFO、STREAM_MESSAGE。
常见 ERROR.code:HTTP_*、NETWORK、RTC_ERROR、STREAM_PARSE、CHAT_ERROR、RTC_STOP、STOP_API,以及 REMOTE_JOIN_TIMEOUT(本地 RTC 进房后 15s 内仍无任何远端 user-joined)、REMOTE_REJOIN_TIMEOUT(最后一个远端离开后 30s 内无远端再次进房)。
INTERRUPT 业务码处理
INTERRUPT 是服务端业务通知,不属于 ERROR。SDK 只透传 code,不内置业务码常量,也不会根据业务码自动结束通话;接入方需要自行定义业务码并决定提示、结果处理和页面跳转。
| code | 常量 | 含义 | 建议处理 |
|--------|------|------|----------|
| 900007 | TERMINAL_SENTENCE | 命中结束语,业务正常完成 | 调用 stopVoiceChat(),再进入完成或结果流程 |
| 900008 | RISK_WORD_SENTENCE | 命中风险词,对话需要终止 | 展示合规提示并调用 stopVoiceChat(),不要按正常完成处理 |
const INTERRUPT_CODES = {
TERMINAL_SENTENCE: 900007,
RISK_WORD_SENTENCE: 900008
};
client.on(VoiceEvents.INTERRUPT, data => {
void handleInterrupt(data);
});
async function handleInterrupt({ code, message }) {
const interruptCode = Number(code);
if (interruptCode === INTERRUPT_CODES.TERMINAL_SENTENCE) {
await client.stopVoiceChat();
openResultPage();
return;
}
if (interruptCode === INTERRUPT_CODES.RISK_WORD_SENTENCE) {
showError(message || '聊天内容涉及违规内容,本次对话已终止');
await client.stopVoiceChat();
}
}Demo (this repo)
cd packages/voice-realtime-sdk
pnpm install
pnpm demo
pnpm demo:build
pnpm demo:preview完整示例见 demo/(demo/vite.config.js 中可选 HTTPS)。
