@kookapp/voice-rtc-core
v0.1.0
Published
Environment-neutral KOOK QuickJoin and InitSpeaking RTC core
Keywords
Readme
@kookapp/voice-rtc-core
voice-rtc-core 是 KOOK RTC 的环境无关核心包,负责 QuickJoin、InitSpeaking、Protoo 信令、mediasoup Transport、Producer/Consumer 和重连资源生命周期。
它不负责麦克风采集、远端音频播放、UI,也不绑定具体的 Node 原生 WebRTC 实现。大多数业务应直接使用 @kookapp/voice-web-sdk 或 @kookapp/voice-bot-sdk;只有开发新的运行时适配层时才需要直接使用 Core。
安装
pnpm add @kookapp/voice-rtc-core适用场景
- 为新的浏览器壳、桌面端或 Node WebRTC 实现编写适配层。
- 直接控制 QuickJoin、InitSpeaking 和媒体 Transport 生命周期。
- 自定义信令传输、mediasoup Device 或静音占位音轨。
- 在不引入浏览器采集和 UI 代码的环境中接收 RTC 音轨。
如果只是网页语音,请使用 @kookapp/voice-web-sdk;如果是机器人,请使用 @kookapp/voice-bot-sdk。
核心流程
join()
-> 建立 Protoo WebSocket
-> quickJoin
-> Device.load()
-> 创建发送和接收 Transport
-> 准备 DTLS
-> publishTrack() 或静音占位音轨
-> initSpeaking普通发言模式下,join() 会返回 { pendingSpeaking: true },第一次 publishTrack() 才触发 initSpeaking。只收听模式下,Core 会使用注入的静音音轨在 join() 阶段完成 initSpeaking。
创建客户端
下面的 runtime 代表调用方提供的环境适配对象。它至少需要能够创建 mediasoup Device;使用只收听模式时还必须创建静音音频源。
import { RtcCoreClient, normalizeVoiceTokenConfig } from '@kookapp/voice-rtc-core'
const token = normalizeVoiceTokenConfig(tokenResponse)
const client = new RtcCoreClient({
uid: 'user-123',
joinId: `join-${Date.now()}`,
createDevice: () => runtime.createDevice(),
createSilentAudioSource: () => runtime.createSilentAudioSource(),
logger: console,
})
client.tokenConfig = token构造参数:
| 参数 | 说明 |
| --- | --- |
| uid | 当前 RTC 用户 ID |
| joinId | 本次连接的唯一标识 |
| tokenConfig | 已归一化的 Token 配置,可在构造后再赋值 |
| createDevice | 自定义 mediasoup Device 创建函数 |
| createSignalingPeer | 自定义 Protoo Peer;未提供时使用内置 WebSocket 实现 |
| createSilentAudioSource | 只收听模式需要的静音音轨工厂 |
| deviceOptions | 传给内置 Device 的选项 |
| logger | 可选的 debug/info/warn/error 日志实现 |
发言模式
const pending = await client.join('channel-123', {
gateway_url: token.gateway_url,
iceServers: token.iceServers,
iceTransportPolicy: token.iceTransportPolicy,
rtcConfig: token.rtcConfig,
forceRelay: token.forceRelay,
quickJoinListenOnly: false,
joinMuted: false,
joinDeafened: false,
})
console.log(pending.pendingSpeaking) // true
const producer = await client.publishTrack(audioTrack, {
stopTracks: false,
codecOptions: { opusStereo: 0 },
})
console.log(producer.id, client.lastJoinData)audioTrack 必须是 kind === 'audio' 的 MediaStreamTrack。Core 不负责创建该音轨。
只收听模式
const joinData = await client.join('channel-123', {
gateway_url: token.gateway_url,
iceServers: token.iceServers,
quickJoinListenOnly: true,
joinMuted: true,
})只收听模式要求构造时提供 createSilentAudioSource()。返回对象必须包含:
{
track: MediaStreamTrack,
close(): void
}之后调用 publishTrack(realTrack) 时,Core 会尝试把静音占位 Producer 升级为真实音轨,避免重复创建 Producer。
接收远端音轨
client.on('consumer', ({ consumerId, peerId, peerInfo, track }) => {
audioRuntime.playRemoteTrack(track, { consumerId, peerId, peerInfo })
})
client.on('consumer-close', ({ consumerId }) => {
audioRuntime.stopRemoteTrack(consumerId)
})Core 只派发音轨,不创建 <audio> 元素,也不自动建立 PCM Sink。
常用事件
| 事件 | 说明 |
| --- | --- |
| connection-state-change | RTC 连接状态变化 |
| signaling-state-change | Protoo 信令连接状态变化 |
| join-pending | QuickJoin 完成,等待首次发布音轨 |
| join-succeed | InitSpeaking 完成并取得入会数据 |
| consumer | 收到新的远端 Consumer 和音轨 |
| consumer-close | 远端 Consumer 被关闭 |
| peer-join / peer-leave | 成员加入或离开 |
| audio-mute / audio-unmute | 远端成员麦克风状态变化 |
| transport-state-change | 发送或接收 Transport 状态变化 |
| transportError | Transport 连接异常状态 |
| reconnect / disconnect | 服务端重连或断开通知 |
| error | Core 内部异步错误 |
媒体控制
await client.pauseProducer()
await client.resumeProducer()
await client.replaceTrack(nextAudioTrack)
await client.unpublishTrack()
await client.pauseHeadset()
await client.resumeHeadset()pauseHeadset() 和 resumeHeadset() 只发送协议请求;实际停止播放远端声音仍由适配层负责。
重载与关闭
// 保留信令连接,重新建立媒体资源
await client.reload({ quickJoinListenOnly: true })
// 仅销毁当前媒体 Transport 和 Producer/Consumer
client.destroyMedia()
// 离开频道并关闭整个客户端
await client.leave()leave() 最终会关闭客户端。需要再次连接时,应创建新的 RtcCoreClient 实例。
Token 归一化
const token = normalizeVoiceTokenConfig(tokenResponse, {
ipDiscovery: ['203.0.113.10'],
})归一化后会保留 gateway_url、iceServers、iceTransportPolicy、rtc_config、call_id、join_voice、startAins 和原始响应 raw。不要把完整 gateway_url 输出到日志。
协议工具
包还导出了 normalizeIceServers、shouldForceRelay、buildWebrtcRouterRtpCapabilities、buildInitSpeakingData 等协议辅助函数。它们主要供适配层和协议测试使用,普通业务不应依赖其内部数据结构。
开发与发布检查
在仓库根目录执行:
pnpm --filter @kookapp/voice-rtc-core test
pnpm --filter @kookapp/voice-rtc-core typecheck
pnpm --filter @kookapp/voice-rtc-core build
pnpm --filter @kookapp/voice-rtc-core dev
pnpm --dir packages/rtc-core pack --pack-destination packsdev 会持续构建 ESM、CommonJS 和类型声明,供相邻包或通过本地链接接入的项目使用。
