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

usc-rtc-client

v2.3.0

Published

usc rtc client

Readme

音视频通话 webrtc sdk 开发手册

1.安装

//使用yarn安装
yarn add usc-rtc-client
//使用npm安装
npm install usc-rtc-client

2.简单使用 demo

//用户A,演示主叫端的逻辑
import { RtcClient, createRtcClient, RtcSessionEvent, RtcClientEvent } from "usc-rtc-client"
const startClientA = async () => {
    //初始化一个webrtc的sdk客户端,这里的本地号码是7001,server对应的是信令服务器地址由线下对接进行提供
    let client  = await createRtcClient({ server: "xxxxxxx", localNumber: "7001" })
    //创建一个针对于7002的视频会话
    let session = client.createSession("7002")
    //这里演示给会话注册一个接受到远端视频流的事件监听
    session.on(RtcSessionEvent.stream, (data) => {
        //data 的stream 属性就是视频流信息,你可以像下面这样把他放到一个视频容器下进行播放
        let playerContainer = document.getElementById("player")
        playerContainer.srcObject = data.stream
        playerContainer.play()
    })
    //给会话注册断开事件,
    session.on(RtcSessionEvent.bye, () => alert("BYE!!!!!!"))
    //给会话选择本端所提供的流,这里使用的是摄像头的流信息
    await session.useDefaultDevice(document.getElementById("localPalyer") as HTMLVideoElement)
    //开始呼叫
    session.start()
}
startClientA()


//====================================
//用户B,演示被叫端的逻辑
const startClientB = async (client: RtcClient) => {
     //初始化一个webrtc的sdk客户端,这里的本地号码是7021,server对应的是信令服务器地址由线下对接进行提供
    let client  = await createRtcClient({ server: "xxxxxxx", localNumber: "7002" })
    //给客户端注册一个接收到视频通话邀请的事件监听
    client.on(RtcClientEvent.invite, async (session) => {
        //注册接受到远端流信息的事件监听
        session.on(RtcSessionEvent.stream, (data: any) => {
            //播放流信息的代码,如上面的主叫端一样
        })
        ////给会话注册断开事件,
        session.on(RtcSessionEvent.bye, () => alert("BYE!!!!!!"))
        //给会话选择本端所提供的流,这里使用的是摄像头的流信息
        await session.useDefaultDevice(document.getElementById("localPalyer") as HTMLVideoElement);
        //接受会话
        await session.acceptCall();
    })
}
startClientB()

3.sdk 说明

此项目为 typescript 项目,按照 npm 的约定生成了 type 描述文件,具体 api 说明请在 type 描述文件中进行查看,以下是一些重要的 Api 说明:

1.createRtcClient

此方法用来创建一个 webrtc 的终端,内部已经封装了心跳,信令交互,以及视频处理的逻辑,api 描述如下:

declare const createRtcClient: (config: {
    server: string; //信令服务器的地址
    localNumber: string; //自己的号码
    heartTime?: number; //向信令服务器的发送心跳的间隔时间,默认是30s
    expireTime?: number; //注册信令的过期时间,默认是60s
}) => Promise<RtcClient>; //注意,这里返回的是Promise的对象,resolve前置是在创建websocket链接之后发送一次心跳信息,等待服务器返回确认信息

使用事例:

import { createRtcClient } from 'usc-rtc-client'
let client = await createRtcClient({ server: 'wss://xxxxxx.com/', localNumber: '7001' })

2.RtcClient

RtcClient 是用来实例化 webrtc 终端的对象,内部主要方法如下

  • createSession(remoteNumber?: string): RtcSession 用来来创建一个会话
  • destroy() 销毁客户端,会销毁所有创建的会话以及断开与信令服务器的链接,与信令服务器断开链接之后也会自动触发此方法
  • reConnect() 重新连接信令服务器,如果之前处于连接状态会自动调用 destory 的方法
  • on(event:RtcClientEvent,cb:Function) 注册相关监听事件
  • sendPttMessage() 此方法是后续添加,是用来发送 ptt 消息,消息具体格式请参考 ptt 对讲以及 ims 开发文档

事例代码:

import { createRtcClient, RtcClientEvent, RtcSession, RtcCalledSession } from 'usc-rtc-client'
let client = await createRtcClient({ server: 'wss://xxxxxx.com/', localNumber: '7001' })
let session: RtcSession = client.createSession('7002')
client.on(RtcClientEvent.invite, (calledSession: RtcCalledSession) => {})

3.RtcClientEvent

RtcClientEvent 表示底层封装向上抛出的一些业务与非业务的生命周期事件,具体如下

  • connected 信令服务器连接成功事件
  • disconnected 信令服务器断开事件,连接失败这里也可以触发
  • invite 收到音视频通话邀请的事件
  • FPREInfo 收到 ptt 消息通知事件(目前主要为 ptt 组在线用户查询消息,具体格式参考 ptt 对讲以及 ims 开发文档)

事例代码

import { createRtcClient , RtcClientEvent,RtcCalledSession } from "usc-rtc-client"
let client  = await createRtcClient({server:"wss://xxxxxx.com/",localNumber:"7001"})

client.on(RtcClientEvent.disconnected,()=>{
    console.log("socket is closed")
})

client.on(RtcClientEvent.invite,(session:RtcCalledSession)=>{
    console.log("revice invite,do something plz...")
})

4.RtcSession

RtcSession 是用来实例化 RtcClient 所创建的音视频会话的对象,内部主要方法如下

  • addRemote(remoteNumber: string) 修改需要呼叫的用户
  • rejectCall() 拒绝邀请,使用于创建会话过程中的会议类型变更
  • acceptCall() 接受邀请,使用于创建会话过程中的会议类型变更
  • start() 开始呼叫
  • destroy() 销毁会话,如果呼叫已经开始,会先向被叫端发送 bye 请求
  • getAllInputResource() 获取所有的音视频输入源
  • useDefaultDevice(container: HTMLVideoElement) 使用默认的本地音视频输入设备(麦克风与摄像头),并将本地的流媒体渲染到对应的 video 上(可以不传),实际上是下面几个方法的组合使用
  • useAudio(deviceId) 使用对应 deviceId 的麦克风设备作为音频流,如果 deviceId 为 undefined,那么使用默认的设备作为音频源
  • useDeviceVideo(deviceId) 使用对应 deviceid 摄像头设备的视频流,如果 deviceId 为 undefined,那么使用默认的设备作为视频源
  • useDeskTopVideo() 使用桌面流作为视频流输入
  • disableAudio() 禁用本地流的音频输入,本地音频静音
  • disableVideo() 禁用本地流的视频输入,关闭本地视频画面
  • enableAudio() 启用本地音频输入
  • enableVideo() 启用本地视频输入
  • renderLocalStreamToContainer(container:HTMLVideoElement|HTMLAudioElement) 将本地的流媒体使用对应的 video 或者 audio 元素进行播放
  • on(event:RtcSessionEvent,cb:Function) 注册相关监听事件
  • addDeviceChangeListener(listener) 注册物理输入设备变化监听事件,如摄像头拔线之类的操作
  • removeDeviceChangeListener(listener) 删除物理输入设备变化监听事件(组件化的框架如 react 之类的,在组件销毁的时候使用这个方法进行回收)

事例代码

...
session.addRemote("7003")
await session.useDefaultDevice(document.getElementById("localplayer"))
session.start()

5.RtcCalledSession

RtcCalledSession 是用来实例化被叫会话的对象,主要方法如下

  • getRemoteNumber() 获取呼叫自己的远端号码
  • rejectCall() 拒绝邀请,使用于创建会话与会话过程中的会议类型变更
  • acceptCall() 接受邀请,使用于创建会话与会话过程中的会议类型变更
  • destroy() 销毁会话,如果呼叫已经开始,会先向被叫端发送 bye 请求
  • getAllInputResource() 获取所有的音视频输入源
  • useDefaultDevice(container: HTMLVideoElement) 使用默认的本地音视频输入设备(麦克风与摄像头),并将本地的流媒体渲染到对应的 video 上(可以不传),实际上是下面几个方法的组合使用
  • useAudio(deviceId) 使用对应 deviceId 的麦克风设备作为音频流,如果 deviceId 为 undefined,那么使用默认的设备作为音频源
  • useDeviceVideo(deviceId) 使用对应 deviceid 摄像头设备的视频流,如果 deviceId 为 undefined,那么使用默认的设备作为视频源
  • useDeskTopVideo() 使用桌面流作为视频流输入
  • disableAudio() 禁用本地流的音频输入,本地音频静音
  • disableVideo() 禁用本地流的视频输入,关闭本地视频画面
  • enableAudio() 启用本地音频输入
  • enableVideo() 启用本地视频输入
  • renderLocalStreamToContainer(container:HTMLVideoElement|HTMLAudioElement) 将本地的流媒体使用对应的 video 或者 audio 元素进行播放
  • on(event:RtcSessionEvent,cb:Function) 注册相关监听事件
  • addDeviceChangeListener(listener) 注册物理输入设备变化监听事件,如摄像头拔线之类的操作
  • removeDeviceChangeListener(listener) 删除物理输入设备变化监听事件(组件化的框架如 react 之类的,在组件销毁的时候使用这个方法进行回收

事例代码

...
client.on(RtcClientEvent.invite,async (session:RtcCalledSession)=>{
    await session.useDefaultDevice(document.getElementById("localplayer"))
    session.acceptCall()
})

6.RtcSessionEvent

会话流程事件

  • bye 会话结束事件
  • stream 会话收到流的事件
  • localAudioChange 本地音频流设备发生了变化
  • localVideoChange 本地视频流设备发生了变化
  • reInvite 会话过程中修改会话类型会重新发 invite 比如原先只是语音通话,然后变成视频会话
  • localStreamChange 本地流发生了变化

事例代码

...
session.on(RtcSessionEvent.stream,({audioOnly,stream})=>{
    if(audioOnly){
        //use audio to play
    }else{
        let playerContainer = document.getElementById("player")
        playerContainer.srcObject = stream
        playerContainer.play()
    }
})
...
session.on(RtcSessionEvent.bye,()=>{
    //close something
    alert("bye")
})

4.监控模式

监控模式是本 SDK 提供的一种特殊功能,允许在不建立完整通话会话的情况下,单向播放远程流。

1.使用 playRemote 函数

import { playRemote } from 'usc-rtc-client'

// 监控模式播放远程流
async function startMonitoring(remoteNumber) {
  try {
    // 创建监控播放器
    const monitorPlayer = document.getElementById('monitor-player')

    // 开始监控远程号码
    const player = await playRemote(
      'ws://your-signaling-server-url', // 信令服务器地址
      remoteNumber, // 要监控的远程号码
      monitorPlayer, // 视频容器
      {
        audioOnly: false, // 是否仅播放音频
        heartTime: 30, // 心跳间隔时间(秒)
        expireTime: 60, // 信令过期时间(秒)
        onerror: (error) => {
          console.error('监控错误:', error)
        }
      }
    )

    console.log('监控会话创建成功')

    // 5秒后结束监控
    setTimeout(() => {
      player.destroy()
      console.log('监控会话已结束')
    }, 5000)
  } catch (error) {
    console.error('监控会话创建失败:', error)
  }
}

2.playRemote 函数参数说明

| 参数名 | 类型 | 描述 | 是否必填 | | ------------ | ---------------- | ---------------- | -------- | | server | string | 信令服务器地址 | 是 | | remoteNumber | string | 要监控的远程号码 | 是 | | container | HTMLVideoElement | 视频播放容器 | 是 | | options | object | 可选配置项 | 否 |

options 配置项:

| 配置项 | 类型 | 默认值 | 描述 | |--------|------|--------|------| | audioOnly | boolean | false | 是否仅播放音频 | | expireTime | number | 60 | 注册信令的过期时间(秒) | | heartTime | number | 30 | 向信令服务器发送心跳的间隔时间(秒) | | onerror | function | undefined | 错误回调函数,在发生错误时调用 |

3.监控模式的特点

  • 监控模式使用'anonymous'作为本地号码,无需登录即可使用
  • 监控模式是单向的,被监控方不会收到任何通知
  • 监控模式支持配置心跳间隔和信令过期时间
  • 监控模式适合用于监控、预览等场景

5.ptt 消息接口

1.启用 ptt 客户端功能

本客户端(webrtc)集成了 ptt 对讲客户端的全部接口,功能等同于 usc-ptt-sdk 提供的功能,若想单独使用 ptt 功能,可直接安装 usc-ptt-sdk 即可;以下是集成的功能及用法说明:

await createRtcClient({
  server,
  localNumber,
  enablePtt: true, // 初始化客户端时,可传入enablePtt,true表示启用ptt客户端,不传或flase表示不使用ptt客户端,
  pttServer: 'ws://localhost:40000', //pttClient服务器地址,当enablePtt为true时,需要传入该字段,否则初始化失败
})

2.RtcClient 集成的 ptt 接口

当启用 ptt 客户端时,ptt 客户端提供的接口将可以在 RtcClient 上使用,接口说明如下: joinGroup('100114','10000008003','10.168.1.17',20023) //加入对讲组 quitGroup() //退出组 talk() //说话 stop() //停止说话

事例代码

const client = await createRtcClient({ server, localNumber, enablePtt: true, pttServer: 'ws://localhost:40000' })
// 加入组
client.joinGroup('100114', '10000008003', '10.168.1.17', 20023)
//退出组
client.quitGroup()
//本客户端用户需要说话时调用(须先加入一个对讲组)
client.talk()
//停止说话
client.stop()

以上接口只作为向服务器发送请求消息, 结果将以客户端事件的形式响应给用户, 开发人员只需要在初始化完客户端后监听相应的事件即可

3.PTTEvent

PTTEvent 表示底层封装向上抛出的一些业务与非业务的生命周期事件,具体如下
const clientEvent = {
  ERROR:'error',                  //错误事件
  SPEAKER:'speaker',              //有用户说话或停止说话时触发该事件
  TALKING:'talking',              //自己说话或停止说话时触发该事件
  ACTIVE_GROUP:'activeGroup',     //加入组或退出组时触发该事件
  JOIN_INFO:'joinInfo',           //有用户加入或退出组时触发该事件
}

事例代码

const client = await createRtcClient({ server, localNumber, enablePtt: true, pttServer: 'ws://localhost:40000' })
client.on(PTTEvent.ACTIVE_GROUP, (e) => {
  // e为空字符串时表示当前没有加入任何组,否则e为加入的组的组id
  if (e) console.log(`进入组:${e}`)
  else console.log('退出组')
})
client.on(PTTEvent.SPEAKER, (e) => {
  // e为空字符串时表示当前没有人在说话或当前说话人停止说话,否则e为说话人的ptt号
  if (e) console.log(`${e}正在说话`)
  else console.log(`停止说话`)
})
client.on(PTTEvent.TALKING, (e) => {
  // e为true时表示当前自己在说话,否则表示自己停止说话
  if (e) console.log(`您正在说话`)
  else console.log(`您已停止说话`)
})
client.on(PTTEvent.JOIN_INFO, (e) => {
  // 有用户加入组时通知,
  // e的结构如下
  // {
  //   user:8003, 加入的用户号
  //   group:100114, 组id
  //   code:1,  0表示退出组,1表示加入组
  // }
  console.log(`用户加入通知:${JSON.stringify(e)}`)
})

6.最佳实践

1.错误处理

在使用 SDK 时,建议添加适当的错误处理,以提高应用的稳定性:

try {
  const client = await createRtcClient({ server, localNumber })
  // 使用client
} catch (error) {
  console.error('创建RTC客户端失败:', error)
  // 处理错误,如提示用户重试
}

// 会话事件处理
session.on(RtcSessionEvent.stream, ({ stream }) => {
  if (stream) {
    const container = document.getElementById('player')
    container.srcObject = stream
    container.play().catch((error) => {
      console.error('播放流失败:', error)
      // 处理自动播放失败的情况
    })
  }
})

2.资源释放

在不需要使用 SDK 或会话结束时,建议释放相关资源:

// 销毁会话
session.destroy()

// 销毁客户端
client.destroy()

// 释放流资源
releaseStreamFromContainer(container)

3.设备管理

在使用音视频设备前,建议先检查设备是否可用:

const resources = await session.getAllInputResource()
if (resources.audio.length === 0) {
  console.error('没有检测到麦克风')
  // 处理没有麦克风的情况
}
if (resources.video.length === 0) {
  console.error('没有检测到摄像头')
  // 处理没有摄像头的情况
}

7.限制

  • 目前仅做了 chrome 浏览器的兼容支持,要求 chrome 内核版本在 90 以上
  • webrtc 接口调用的页面需要依赖 https 环境(本地地址如 localhost,127.0.0.1 除外),页面运行环境如果无法提供支持,请在 chrome 的 unsafely-treat-insecure 中添加白名单来让页面支持 webrtc(chrome 浏览器打开 chrome://flags/#unsafely-treat-insecure-origin-as-secure,在 Insecure origins treated as secure 下面的输入框中添加您的网页地址,选择右边的 enable,重启浏览器生效)

8.API 参考

核心函数

  • createRtcClient(config): 创建 RTC 客户端
  • playRemote(server, remoteNumber, container, options): 监控模式播放远程流
  • renderStreamToContainer(stream, container): 渲染流到容器
  • releaseStreamFromContainer(container): 从容器释放流
  • enableLog(): 启用日志

事件类型

  • RtcClientEvent: 客户端事件
  • RtcSessionEvent: 会话事件
  • PTTEvent: PTT 事件

  • RtcClient: RTC 客户端类
  • RtcSession: 会话类
  • RtcCalledSession: 被叫会话类

9. 声明导出

SDK 提供了完整的 TypeScript 类型声明,以下是所有可导出的内容列表:

核心函数声明

export function createRtcClient(config: { server: string; localNumber: string; heartTime?: number; expireTime?: number; enablePtt?: boolean; pttServer?: string }): Promise<RtcClient>

export function playRemote(
  server: string,
  remoteNumber: string,
  container: HTMLVideoElement,
  options?: {
    expireTime?: number;
    heartTime?: number;
    onerror?: (e: any) => void;
    audioOnly?: boolean;
  }
): Promise<{ 
  destroy: () => void;
}>

export function renderStreamToContainer(stream: MediaStream, container: HTMLVideoElement | HTMLAudioElement): void

export function releaseStreamFromContainer(container: HTMLVideoElement | HTMLAudioElement): void

export function enableLog(): void
export function disableLog(): void
export function setLogLevel(level: 'debug' | 'info' | 'warn' | 'error'): void

类和接口

export class RtcClient extends RtcClientBase {
  createSession(remoteNumber: string): RtcSession
  on(event: RtcClientEvent, callback: Function): void
  off(event: RtcClientEvent, callback: Function): void
  destroy(): void
  reConnect(): Promise<void>
  sendPttMessage(data: any): void
  // PTT 相关方法
  joinGroup(groupId: string, userId: string, ip: string, port: number): void
  quitGroup(): void
  talk(): void
  stop(): void
}

export class RtcSession extends RtcAbstractSession {
  addRemote(remoteNumber: string): void
  rejectCall(): void
  acceptCall(): void
  start(): void
  destroy(): void
  getAllInputResource(): Promise<{ audio: MediaDeviceInfo[]; video: MediaDeviceInfo[] }>
  useDefaultDevice(container?: HTMLVideoElement): Promise<void>
  useAudio(deviceId?: string): Promise<void>
  useDeviceVideo(deviceId?: string): Promise<void>
  useDeskTopVideo(): Promise<void>
  disableAudio(): void
  disableVideo(): void
  enableAudio(): void
  enableVideo(): void
  renderLocalStreamToContainer(container: HTMLVideoElement | HTMLAudioElement): void
  on(event: RtcSessionEvent, callback: Function): void
  off(event: RtcSessionEvent, callback: Function): void
  addDeviceChangeListener(listener: () => void): void
  removeDeviceChangeListener(listener: () => void): void
}

export class RtcCalledSession extends RtcAbstractSession {
  getRemoteNumber(): string | undefined
  rejectCall(): void
  acceptCall(): void
  destroy(): void
  getAllInputResource(): Promise<{ audio: MediaDeviceInfo[]; video: MediaDeviceInfo[] }>
  useDefaultDevice(container?: HTMLVideoElement): Promise<void>
  useAudio(deviceId?: string): Promise<void>
  useDeviceVideo(deviceId?: string): Promise<void>
  useDeskTopVideo(): Promise<void>
  disableAudio(): void
  disableVideo(): void
  enableAudio(): void
  enableVideo(): void
  renderLocalStreamToContainer(container: HTMLVideoElement | HTMLAudioElement): void
  on(event: RtcSessionEvent, callback: Function): void
  off(event: RtcSessionEvent, callback: Function): void
  addDeviceChangeListener(listener: () => void): void
  removeDeviceChangeListener(listener: () => void): void
}

export abstract class RtcAbstractSession {
  sessionId: string
  remoteNumber: string | undefined
  getRemoteNumber(): string | undefined
  destroy(): void
}

事件类型声明

export enum RtcClientEvent {
  connected = 'connected',
  disconnected = 'disconnected',
  invite = 'invite',
}

export enum RtcSessionEvent {
  bye = 'bye',
  stream = 'stream',
  localAudioChange = 'localAudioChange',
  localVideoChange = 'localVideoChange',
  reInvite = 'reInvite',
  localStreamChange = 'localStreamChange',
}

export enum PTTEvent {
  PTTInfo = 'PTTInfo',
  FPREInfo = 'FPREInfo',
  IMSInfo = 'IMSInfo',
  ERROR = 'error',
  SPEAKER = 'speaker',
  TALKING = 'talking',
  ACTIVE_GROUP = 'activeGroup',
  JOIN_INFO = 'joinInfo',
}

常量和工具类型

export enum RtcInviteStatus {
  timeout = 408,
  reject = 488,
  busy = 486,
  notfound = 404,
  notAllowedMedia = 415,
  ok = 200,
}

export enum RtcCalledType {
  audio = 'audio',
  video = 'video',
  audioVideo = 'audioVideo',
  unknown = 'unknown',
}

完整导入示例

// 导入所有内容
import * as UscRtcClient from 'usc-rtc-client'

// 按需导入
import {
  createRtcClient,
  playRemote,
  authDevice,
  RtcClient,
  RtcSession,
  RtcInviteStatus,
  RtcClientEvent,
  RtcSessionEvent,
  PTTEvent,
  RtcCalledType,
  renderStreamToContainer,
  releaseStreamFromContainer,
  closeStreamAndTrack,
  enableLog,
  disableLog,
} from 'usc-rtc-client'