npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@kookapp/voice-rtc-core

v0.1.0

Published

Environment-neutral KOOK QuickJoin and InitSpeaking RTC core

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_urliceServersiceTransportPolicyrtc_configcall_idjoin_voicestartAins 和原始响应 raw。不要把完整 gateway_url 输出到日志。

协议工具

包还导出了 normalizeIceServersshouldForceRelaybuildWebrtcRouterRtpCapabilitiesbuildInitSpeakingData 等协议辅助函数。它们主要供适配层和协议测试使用,普通业务不应依赖其内部数据结构。

开发与发布检查

在仓库根目录执行:

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 packs

dev 会持续构建 ESM、CommonJS 和类型声明,供相邻包或通过本地链接接入的项目使用。