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

@easemob-community/callkit-core

v2.0.7

Published

Framework-agnostic call signaling core for Easemob IM

Downloads

967

Readme

@easemob-community/callkit-core

框架无关的通话信令核心库,仅依赖环信 IM SDK 作为信令通道,RTC 层通过抽象接口由上层自行接入。

特性

  • 零 UI 依赖:纯信令核心,不绑定任何前端框架
  • 零 RTC 依赖:通过 RtcAdapter 接口或事件回调接入 Agora 等 RTC SDK
  • 单聊状态机:确定性有限状态机管理 INVITING → ALERTING → IN_CALL → IDLE
  • 群聊会话模型:分布式参与者集合,支持邀请、加入、离开、追加邀请
  • 注册式信令路由SignalRouter + SingleCallSignalHandler / GroupCallSignalHandler
  • 事件驱动:所有状态变更和 RTC 指令通过事件总线通知上层

安装

pnpm add @easemob-community/callkit-core easemob-websdk

快速开始

import { CallKitCore, CALL_TYPE, CALL_STATUS } from '@easemob-community/callkit-core'
import type { CallKitEvent } from '@easemob-community/callkit-core'

const core = new CallKitCore({
  imClient: conn,              // 环信 IM SDK Connection 实例
  inviteTimeout: 30000,        // 邀请超时时间(毫秒),默认 30000
  onEvent: (event: CallKitEvent) => {
    console.log('[callkit-core]', event.type, event.payload)
  }
})

// 发起单聊视频通话
await core.inviteCall({
  calleeUserId: 'user123',
  callType: CALL_TYPE.VIDEO_1V1,
  callerInfo: {
    nickname: '张三',
    avatarURL: 'https://example.com/avatar.png'
  }
})

核心概念

CallKitCore

核心控制器,暴露所有通话 API:

| 方法 | 说明 | |---|---| | inviteCall(params) | 发起单聊通话 | | answerCall(params) | 接听 / 拒绝 / 忙线拒绝 | | hangup(params?) | 挂断 / 取消通话 | | inviteGroupCall(params) | 发起群聊通话 | | inviteMoreParticipants(ids) | 群聊中追加邀请成员 | | toggleAudio() | 切换本地音频开关 | | toggleVideo() | 切换本地视频开关 | | reportRtcEvent(report) | 向上层上报 RTC 事件 | | destroy() | 销毁实例并移除 IM 监听 |

单聊状态机

IDLE ──inviteCall──► INVITING ───────────────► IN_CALL
       ▲                │    │                    │
       │                │    └─answerCall(refuse)─┘
       │                │
       │                └──incomingCall / alert
       │
       └───────────────────────────────────────hangup

完整状态:IDLE | INVITING | ALERTING | CONFIRM_RING | RECEIVED_CONFIRM_RING | ANSWER_CALL | CONFIRM_CALLEE | IN_CALL

群聊会话

群聊没有全局状态机,只有:

  • session:会话元数据(callId、groupId、channel、callerUserId)
  • participants:参与者列表,每人状态为 invited → accepted → joinedRtc → left

RTC 接入方式

方式一:RtcAdapter(推荐)

实现 RtcAdapter 接口并传入 CallKitCoreConfig.rtcAdapter,Core 会自动处理 shouldJoinRtc / shouldLeaveRtc / shouldPublishTracks / localAudioChanged / localVideoChanged 等指令事件。

import type { RtcAdapter, JoinRtcParams } from '@easemob-community/callkit-core'

class AgoraRtcAdapter implements RtcAdapter {
  private client = AgoraRTC.createClient({ mode: 'rtc', codec: 'vp8' })

  async joinChannel(params: JoinRtcParams): Promise<void> {
    await this.client.join(params.appId, params.channel, params.token, params.uid)
  }

  async leaveChannel(): Promise<void> {
    await this.client.leave()
  }

  async publishLocalTracks(types: ('audio' | 'video')[]): Promise<void> { /* ... */ }
  async unpublishLocalTracks(types: ('audio' | 'video')[]): Promise<void> { /* ... */ }
  async subscribeRemoteUser(userId: string, mediaType: 'audio' | 'video'): Promise<void> { /* ... */ }
  async unsubscribeRemoteUser(userId: string, mediaType: 'audio' | 'video'): Promise<void> { /* ... */ }
  async setAudioEnabled(enabled: boolean): Promise<void> { /* ... */ }
  async setVideoEnabled(enabled: boolean): Promise<void> { /* ... */ }
}

const core = new CallKitCore({
  imClient: conn,
  rtcAdapter: new AgoraRtcAdapter()
})

方式二:事件回调

监听 onEvent / onRtcEvent 手动调用 RTC SDK:

const core = new CallKitCore({
  imClient: conn,
  onEvent: async (event) => {
    switch (event.type) {
      case 'shouldJoinRtc': {
        const { channel, token, uid, appId } = event.payload
        await agoraClient.join(appId, channel, token, uid)
        break
      }
      case 'shouldLeaveRtc': {
        await agoraClient.leave()
        break
      }
      // ...
    }
  }
})

完整接口定义与示例参见 docs/integration.md

文档导航

  • 架构说明 — 模块设计、状态机、信令路由
  • 信令交互 — 消息格式、交互流程、超时处理
  • RTC 接入 — RtcAdapter 实现、事件回调、平台差异
  • 事件参考 — 完整事件类型、payload 结构、使用示例
  • API 参考 — TypeDoc 自动生成的完整 API 文档

平台支持

| 平台 | 状态 | |------|------| | Web (Vue3 / React / Angular) | 已支持 | | UniApp | 计划中 | | 小程序 | 计划中 |

License

MIT