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 🙏

© 2025 – Pkg Stats / Ryan Hefner

@nzmedet/voice-sdk

v1.0.20

Published

Production-grade WebRTC voice calling SDK for React Native with Firebase signaling, CallKeep UI, VoIP push, metered billing, and auto-reconnect.

Downloads

1,163

Readme

voice-sdk

Production-grade WebRTC voice calling SDK for React Native with Firebase signaling, CallKeep UI, VoIP push, metered billing, and auto-reconnect.

⚠️ Breaking Change: Context Provider Required

As of v1.0.6+, the SDK uses React Context instead of global variables. You must wrap your app with VoiceSDKProvider after initialization. See the Setup section below for details.

Installation

npm install @nzmedet/voice-sdk

Peer Dependencies

This package requires the following peer dependencies:

npm install react react-native @react-native-firebase/app @react-native-firebase/firestore react-native-webrtc react-native-callkeep react-native-pushkit

Setup

1. Initialize the SDK

import { VoiceSDK, VoiceSDKProvider } from 'voice-sdk';
// Initialize @react-native-firebase/app first
// initializeApp();

// Initialize the SDK
await VoiceSDK.init({
  appName: 'MyApp',
  turnServers: [
    { urls: 'stun:stun.l.google.com:19302' },
    {
      urls: 'turn:your-turn-server.com:3478',
      username: 'your-username',
      credential: 'your-password',
    },
  ],
  callbacks: {
    // Optional: Store push tokens in your database
    onTokenUpdate: async (platform, token) => {
      // Store token in your backend
    },
    // Optional: Client-side call event handlers
    onCallStarted: async (callId, callerId, calleeId) => {
      // Client-side logic when call starts
    },
    onCallStateChanged: async (callId, state) => {
      // Client-side logic when call state changes
    },
    onCallEnded: async (callId, startTime, endTime) => {
      // Client-side logic when call ends
      // Note: For server-side billing, implement Cloud Functions
    },
  },
});

2. Wrap Your App with VoiceSDKProvider

Important: The SDK uses React Context to provide functionality to hooks. You must wrap your app with VoiceSDKProvider after initialization:

import React from 'react';
import { VoiceSDK, VoiceSDKProvider } from 'voice-sdk';

function App() {
  const [initialized, setInitialized] = React.useState(false);

  React.useEffect(() => {
    VoiceSDK.init({
      appName: 'MyApp',
      turnServers: [/* ... */],
    })
      .then(() => {
        setInitialized(true);
        VoiceSDK.enableDebugMode(); // Optional
      })
      .catch((error) => {
        console.error('Failed to initialize VoiceSDK:', error);
      });
  }, []);

  if (!initialized) {
    return <LoadingScreen />;
  }

  // Wrap your app with VoiceSDKProvider
  return (
    <VoiceSDKProvider value={VoiceSDK.getContextValue()}>
      <YourAppContent />
    </VoiceSDKProvider>
  );
}

Why? The SDK uses React Context instead of global variables for better React patterns, type safety, and testability. The useCall() and useIncomingCall() hooks require this provider to function.

3. Enable Debug Mode (Optional)

VoiceSDK.enableDebugMode();

4. Token Management

The SDK automatically handles VoIP push token registration (iOS) and FCM token registration (Android). Tokens are automatically received and passed to your onTokenUpdate callback, where you should store them in your database.

Usage

Starting a Call

Note: Components using hooks must be within a VoiceSDKProvider.

import { useCall } from 'voice-sdk';

function MyComponent() {
  // This component must be rendered within <VoiceSDKProvider>
  const { startCall, callState, isConnected, endCall } = useCall();

  const handleCall = async () => {
    try {
      await startCall('callee-user-id');
    } catch (error) {
      console.error('Failed to start call:', error);
    }
  };

  return (
    <>
      <Button title="Call" onPress={handleCall} />
      <Button title="End Call" onPress={endCall} />
      <Text>Status: {callState}</Text>
      <Text>Connected: {isConnected ? 'Yes' : 'No'}</Text>
    </>
  );
}

Handling Incoming Calls

Note: Components using hooks must be within a VoiceSDKProvider.

import { useIncomingCall } from 'voice-sdk';

function IncomingCallComponent() {
  // This component must be rendered within <VoiceSDKProvider>
  const { incomingCall, answer, decline, getCallMetadata } = useIncomingCall();

  if (incomingCall) {
    // Access participant info
    const caller = incomingCall.caller;
    const callee = incomingCall.callee;
    
    // Or get full metadata including any backend-provided fields
    const metadata = getCallMetadata(incomingCall.callId);
    
    return (
      <View>
        <Text>{caller.displayName} is calling...</Text>
        {caller.photoURL && <Image source={{ uri: caller.photoURL }} />}
        <Button title="Answer" onPress={answer} />
        <Button title="Decline" onPress={decline} />
      </View>
    );
  }

  return null;
}

Using UI Components

import { IncomingCallScreen, ActiveCallScreen } from 'voice-sdk';

// In your navigation
<Stack.Screen
  name="IncomingCall"
  component={IncomingCallScreen}
/>

<Stack.Screen
  name="ActiveCall"
  component={ActiveCallScreen}
/>

Firebase Setup

Firestore Rules

Deploy the included Firestore rules:

firebase deploy --only firestore:rules

Cloud Functions

Important: This SDK does NOT include complete Cloud Functions. You must implement your own Cloud Functions to handle:

  • Call Initiation: Creating call records, sending push notifications, validation
  • Call Termination: Processing ended calls, calculating duration
  • Billing: Calculating costs, updating user balances, processing payments (Stripe, etc.)
  • Cleanup: Removing stale calls, handling abandoned calls

The SDK provides reusable helper functions that you can import into your own Cloud Functions. See firebase/functions/README.md for documentation and usage examples.

You are responsible for:

  • Implementing your own Cloud Functions based on your requirements
  • Setting up your billing logic (Stripe, in-app purchases, subscription models, etc.)
  • Defining your database schema and collection structure
  • Implementing authentication, authorization, and security rules
  • Customizing push notification delivery

Copy the helper utilities to your Firebase Functions project:

mkdir -p your-firebase-project/functions/utils
cp firebase/functions/utils/callHelpers.ts your-firebase-project/functions/utils/

Push Notification Payload Format

When sending push notifications to trigger incoming calls, use this structure:

iOS (VoIP Push)

{
  "callId": "call-uuid-123",
  "caller": {
    "id": "user-123",
    "displayName": "John Doe",
    "photoURL": "https://example.com/photo.jpg"
    // Backend can add additional fields here
  },
  "callee": {
    "id": "user-456",
    "displayName": "Jane Smith",
    "photoURL": "https://example.com/jane.jpg"
  },
  // Optional: additional metadata
  "metadata": {
    "customField": "value"
  }
}

Android (FCM)

The caller and callee objects can be sent as:

  • Direct JSON objects in the data payload
  • JSON strings that will be parsed
{
  "callId": "call-uuid-123",
  "caller": "{\"id\":\"user-123\",\"displayName\":\"John Doe\",\"photoURL\":\"https://example.com/photo.jpg\"}",
  "callee": "{\"id\":\"user-456\",\"displayName\":\"Jane Smith\"}"
}

Important: The SDK expects exactly id, displayName, and photoURL (optional) fields in CallParticipant objects. No backward compatibility for flattened fields like callerId, callerName, etc.

Features

  • ✅ WebRTC voice calling with auto-reconnect
  • ✅ Firebase Cloud Firestore signaling
  • ✅ CallKeep integration for native call UI
  • ✅ VoIP push notifications (iOS)
  • ✅ FCM push notifications (Android)
  • ✅ Call metadata storage (no backend refetch needed)
  • ✅ Billing helpers (you implement your own billing logic)
  • ✅ TypeScript support
  • ✅ React hooks API

License

MIT