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

rtccalling

v1.3.3

Published

the specificted ringrtc for didi app

Readme

1V1音视频通话SDK

NPM集成

  1. 您需要在项目中使用npm安装SDK包。

    npm install rtccalling --save
  2. 在项目脚本里引入模块。

    import { calling } from 'rtccalling';

音视频系统初始化

  1. 初始化引入对象。

    calling.initialize();					// 初始化引入对象
  2. 绑定对应的回调函数(共计五个回调函数)

    • onReceiveIncomingCall(payload: IncomingCallType)

      // 接收来电
           
      // 参数说明
      type IncomingCallType = {
        uuid: string;			// 来电用户唯一标识ID
        isVideoCall: boolean;	// 是否是视频通话
      };
           
      // 绑定方法
      calling.onReceiveIncomingCall = onReceiveIncomingCall.bind(this);
    • onAddCallHistory(uuid: string, callHistoryDetails: CallHistoryDetailsType)

      // 添加来电纪录
           
      // 参数说明
      uuid: string					// 来电用户唯一标识ID
      type DirectCallHistoryDetailsType = {
        callMode: CallMode.Direct;	// 呼叫模式:直呼或群呼
        wasIncoming: boolean;			// 是否为呼入
        wasVideoCall: boolean;		// 是否是视频通话
        wasDeclined: boolean;			// 是否被拒
        callEndedReason?: CallEndedReason		// 通话中断原因
        acceptedTime?: number;		// 接通时间
        endedTime: number;			// 挂断时间
      };
      // 可以根据上述参数判断是接通,拒接,失败等多种情况
           
      // 绑定方法
      calling.onAddCallHistory = onAddCallHistory.bind(this);
    • onHandleCallStateChanged(payload: CallStateChangeType)

      // 通话状态变更
           
      // 参数说明
      type CallStateChangeType = {
        uuid: string;				// 来电用户唯一标识ID
        acceptedTime?: number;	// 接通时间
        callId: CallId;			// 当前通话唯一标识ID
        callState: CallState;		// 当前通话状态,见下方定义
        callEndedReason?: CallEndedReason; // 当前通话结束原因,见下方定义
        isIncoming: boolean;		// 是否为呼入来电
        isVideoCall: boolean;		// 是否是视频通话
        reservation: string;		// 预留字段
      };
           
      declare enum CallState {
          Prering = "init",
          Ringing = "ringing",
          Accepted = "connected",
          Reconnecting = "connecting",
          Ended = "ended"
      }
           
      declare enum CallEndedReason {
          LocalHangup = "LocalHangup",
          RemoteHangup = "RemoteHangup",
          RemoteHangupNeedPermission = "RemoteHangupNeedPermission",
          Declined = "Declined",
          Busy = "Busy",
          Glare = "Glare",
          ReceivedOfferExpired = "ReceivedOfferExpired",
          ReceivedOfferWhileActive = "ReceivedOfferWhileActive",
          ReceivedOfferWithGlare = "ReceivedOfferWithGlare",
          SignalingFailure = "SignalingFailure",
          ConnectionFailure = "ConnectionFailure",
          InternalFailure = "InternalFailure",
          Timeout = "Timeout",
          AcceptedOnAnotherDevice = "AcceptedOnAnotherDevice",
          DeclinedOnAnotherDevice = "DeclinedOnAnotherDevice",
          BusyOnAnotherDevice = "BusyOnAnotherDevice",
          CallerIsNotMultiring = "CallerIsNotMultiring"
      }
           
      // 绑定方法
      calling.onHandleCallStateChanged = onHandleCallStateChanged.bind(this);
    • onRefreshIODevices(payload: MediaDeviceSettings)

      // 刷新输入输出设备
           
      // 参数说明
      type MediaDeviceSettings = {
        availableMicrophones: Array<AudioDevice>;		// 可使用的麦克风
        selectedMicrophone: AudioDevice | undefined;	// 正在使用的麦克风
        availableSpeakers: Array<AudioDevice>;		// 可使用的音箱
        selectedSpeaker: AudioDevice | undefined;		// 正在使用的音箱
        availableCameras: Array<MediaDeviceInfo>;		// 可使用的摄像头
        selectedCamera: string | undefined;			// 正在使用的摄像头
      };
           
      export type AudioDevice = {
        name: string;			// 设备名字
        index: number;		// 设备索引号
        uniqueId: string;		// 设备唯一序列号
        i18nKey?: string;		// 如果存在,该字段用来代替设备名字字段
      };
           
      // 绑定方法
      calling.onRefreshIODevices = onRefreshIODevices.bind(this);
    • async onSendCallingMessage(localUserId: string, remoteUserId: string, callId: string,callingMessage: Proto.ICallingMessage)

      // 发送连接前的握手信息
           
      // 参数说明
      localUserId: string							// 本地用户唯一标识ID
      remoteUserId: string						// 接收用户唯一标识ID
      callId: string								// 通话线路唯一标识ID
      callingMessage: Proto.ICallingMessage		// 握手信息包
           
      // 绑定方法
      calling.onSendCallingMessage = onSendCallingMessage.bind(this);
  3. 完整初始化代码

    function onReceiveIncomingCall(payload: IncomingCallType) {
        // 实现代码
    }
       
    function onAddCallHistory(uuid: string, callHistoryDetails: CallHistoryDetailsType) {
        // 实现代码
    }
       
    function onHandleCallStateChanged(payload: CallStateChangeType) {
        // 实现代码
    }
       
    function onRefreshIODevices(payload: MediaDeviceSettings) {
        // 实现代码
    }
       
    async function onSendCallingMessage(localUserId: string, remoteUserId:string, callId: string, callingMessage: Proto.ICallingMessage) {
        // 实现代码					
    }
       
    calling.initialize();
    calling.sdkUrl = "https://test500.zhidianjh.com/";	// 载入配置表
    calling.localUserId = "10086"; // 当前本地用户的唯一标识符
    calling.localDeviceId = 2;	// 当前设备的设备号,建议赋值2
    calling.onAddCallHistory = onAddCallHistory.bind(this);
    calling.onAddCallHistory = onAddCallHistory.bind(this);
    calling.onHandleCallStateChanged = onHandleCallStateChanged.bind(this);
    calling.onRefreshIODevices = onRefreshIODevices.bind(this);
    calling.onSendCallingMessage = onSendCallingMessage.bind(this);

音视频系统连接前的握手

在两端尚未直接打通前,您需要通过几次握手才能尝试打通双方的直连线路。握手消息的发送参考绑定onSendCallingMessage实现与对方通信。接收你只需要将对象内的成员函数套在你的消息接受函数里面即可。

  • async handleCallingMessage(localUserId: string, remoteUserId: string, departTimeStamp: number, arriveTimeStamp: number, callingMessage: Proto.ICallingMessage)

    // 处理接收到的握手消息
      
    // 参数说明
    localUserId: string						// 本地用户唯一标识ID
    remoteUserId: string					// 远程用户唯一标识ID
    departTimeStamp: number					// 消息发送时间戳
    arriveTimeStamp:number					// 消息到达时间戳
    callingMessage: Proto.ICallingMessage	// 握手消息

完整示例代码

async function onMessage(departTimestamp: number, arriveTimeStamp: number, content: Message) {
    // 直接将对象内的成员函数套在您的处理消息函数里
    await calling.handleCallingMessage(content.localUserId, content.remoteUserId, departTimestamp, arriveTimeStamp, content.callingMessage);
}

音视频系统的呼叫、接受、拒绝

  • directCall(uuid: string, hasLocalAudio: boolean, hasLocalVideo: boolean): DirectCallResult

    // 主动呼叫对方
      
    // 参数说明
    uuid: string						// 远程用户唯一标识ID
    hasLocalAudio: boolean				// 是否是音频通话
    hasLocalVideo: boolean				// 是否是视频通话
      
    // 返回值说明
    enum DirectCallResult {
      AlreadyInProgress = 'AlreadyInProgress',			// 已有正在通话的线路
      MissingLocalUserId = 'MissingLocalUserId',		// 缺少本地用户的唯一标识符
      MissingSdkUrl = 'MissingSdkUrl',					// 缺少初始化配置表
      CallSettingsError = 'CallSettingsError',			// 获得turn/stun服务器出错
      Success = 'Success'								// 成功
    }
  • acceptDirectcall(uuid: string, asVideoCall: boolean)

    // 接受通话
      
    // 参数说明
    uuid: string						// 远程用户唯一标识ID
    asVideoCall: boolean				// 是否是音频通话
  • declineDirectcall(uuid: string)

    // 拒绝通话
      
    // 参数说明
    uuid: string						// 远程用户唯一标识ID
  • setOutgoingAudio(uuid: string, enabled: boolean)

    // 开启关闭音频
      
    // 参数说明
    uuid: string						// 远程用户唯一标识ID
    enabled: boolean					// 是否开启
  • setOutgoingVideo(uuid: string, enabled: boolean)

    // 开启关闭视频
      
    // 参数说明
    uuid: string						// 远程用户唯一标识ID
    enabled: boolean					// 是否开启

关于配置表

在初始化时,您需要载入初始化配置表,配置表里涉及stun/turn服务器地址(获取与目标IP地址所有的数据通路)和ntp服务器地址(获取时间戳)。需要注意的是,SDK会根据传进来的https网址后自动加入SDKSettings作为二级目录。如:https://test500.zhidianjh.com/SDKSettings

{
	"Rtc": {
	    "stun": {
		    "address": "stun:turn.zhidianjh.com:31225"
	    },
	    "turn1":  {
		    "address": "turn:turn.zhidianjh.com:31225",
		    "name": "shwl",
		    "password": "IrX82xAH"  
	    },
	    "turn2":  {
		    "address": "turn:turn.zhidianjh.com:31225?transport=udp",
		    "name": "shwl",
		    "password": "IrX82xAH"  
	    },
	    "turn3":  {
		    "address": "turn:turn.zhidianjh.com:31225?transport=tcp",
		    "name": "shwl",
		    "password": "IrX82xAH"  
	    }
    },
    "NTP": {
		"address": "time1.aliyun.com"
	}
}