Skip to content

A web phone aiming to ease real time communication between your contacts

License

Notifications You must be signed in to change notification settings

shervin-ghajar/react-sip-kit

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

198 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

react-sip-kit

A modern React SIP.js toolkit for building web softphones and SIP clients.
Supports audio/video calls, call recording, screen sharing, and device management, all with a clean, extensible, TypeScript-first architecture.


✨ Features

  • πŸ“ž Audio & Video Calls β€” with device auto-detection
  • πŸŽ₯ Video Support β€” render local & remote streams easily
  • πŸ”΄ Call Recording β€” audio/video capture
  • πŸ–₯️ Screen Sharing β€” during video calls
  • 🎧 Device Management β€” choose input/output devices
  • πŸ”„ Multi-Account & Multi-Line Support β€” concurrent calls
  • ⚑ TypeScript-first API β€” safe and clean
  • πŸ› οΈ Configurable & Extensible

πŸ“¦ Installation

npm install react-sip-kit
# or
yarn add react-sip-kit

πŸš€ Quick Start

1️⃣ Create a SipManager Instance

// main.tsx
import App from './App';
import { SipManager } from 'react-sip-kit';
import { StrictMode, useEffect } from 'react';
import { createRoot } from 'react-dom/client';

export const SipConnection = new SipManager();

const Providers = () => {
  const configs = [
    {
      key: 'support-01', // Optional β†’ If omitted, defaults to account.username
      account: {
        domain: 'sip.example.com',
        username: '1010',
        password: 'password',
        wssServer: 'sip.example.com',
        webSocketPort: '8089',
        serverPath: '/ws',
      },
    },
  ];

  useEffect(() => {
    configs.forEach((config) => SipConnection.add(config));
  }, []);

  return (
    <StrictMode>
      <App />
    </StrictMode>
  );
};

createRoot(document.getElementById('root')!).render(<Providers />);

πŸ”‘ Resolving Accounts & Sessions

All lookups use one of the following keys:

Key Purpose Example
configKey Refers to a specific SIP account instance { configKey: 'support-01' }
lineKey Refers to an active call / line { lineKey: 1 }
remoteNumber Refers to peer phone number β€” must be paired with configKey { configKey: 'support-01', remoteNumber: '1001' }

2️⃣ Access Methods (Dial, Hold, Mute, etc.)

// Using configKey
const { dialByNumber } = SipConnection.getSessionMethodsBy({ configKey: 'support-01' });
dialByNumber('audio', '1002');

// Using lineKey (after a call is active)
SipConnection.getSessionMethodsBy({ lineKey: 1 }).hold();

3️⃣ Read Account State (Reactive)

const { watch, status } = SipConnection.getAccountBy({ configKey: 'support-01' });
const account = watch(); // contains lines, registration, media devices, etc.

4️⃣ Track Session State (useWatchSessionData)

const isRecording = SipConnection.useWatchSessionData({
  key: { lineKey: 1 },
  name: 'recordMedia.recording',
});

const [mediaStatus, isMuted] = SipConnection.useWatchSessionData({
  key: { configKey: 'support-01', remoteNumber: '1002' },
  name: ['localMediaStreamStatus', 'localMediaStreamStatus.muted'],
});

5️⃣ Resolver Helper Methods

SipConnection.getLineBy({ lineKey: 1 });
SipConnection.getLineBy({ configKey: 'support-01', remoteNumber: '1002' });

SipConnection.getSessionBy({ lineKey: 1 });
SipConnection.getUsernameBy({ configKey: 'support-01', remoteNumber: '1002' });

6️⃣ Render Media Streams

import { VideoStream, AudioStream } from 'react-sip-kit';

<VideoStream type="local" lineKey={1} />
<VideoStream type="remote" lineKey={1} />
<AudioStream type="local" lineKey={1} />
<AudioStream type="remote" lineKey={1} />

🧠 Managing Config Keys & Dynamic Rendering

const configs = SipConnection.useWatchConfigs();
// β†’ [{ key: 'support-01', account: {...} }, { key: 'sales-02', ... }]

βœ… When to use useWatchConfigs()

Scenario Should you use it? Reason
Static single account ❌ Not required configKey is constant
You manually track configs in your own state ❌ Optional You already control the list
Rendering UI for each config account dynamically βœ… Yes β€” recommended Ensures you always use the correct configKey, even if keys are auto-generated
Configs can be added or removed at runtime βœ… Always Prevents mismatched lookups or stale references

βœ” Best Practice: Always call useWatchConfigs() when rendering lists of lines or accounts, to ensure that each component receives the correct and current configKey.


Example (Rendering a phone UI for every config dynamically):

const App = () => {
  const configs = SipConnection.useWatchConfigs();

  return (
    <>
      {configs.map((config) => (
        <Lines key={config.key} configKey={config.key} />
      ))}
    </>
  );
};

βš™οΈ Configuration Schema

{
  key?: string; // optional β†’ falls back to account.username
  account: {
    domain: 'your.sip.domain',
    username: 'user',
    password: 'secret',
    wssServer: 'your.sip.domain',
    webSocketPort: '8089',
    serverPath: '/ws',
  },
  features?: { enableVideo?: boolean },
  media?: {
    audioInputDeviceId?: string;
    audioOutputDeviceId?: string;
    videoInputDeviceId?: string;
  },
  registration?: { registerExpires?: number },
}

βœ… Best Practices

Task Recommended Approach
Reference active call Use lineKey when available
Reference account Use configKey
Lookup by phone number Use { configKey, remoteNumber }
Track config keys Use useWatchConfigs()
Watch configs state useWatchConfigs()
Watch account state getAccountBy().watch()
Watch session props useWatchSessionData()

πŸ“‚ Examples

Check /example for:

  • Multi-account softphone
  • Audio/video calls
  • Hold / mute / attended transfer
  • Call recording & screen sharing
  • Stream rendering

πŸ“„ License

MIT


πŸ‘€ Author

Shervin Ghajar

About

A web phone aiming to ease real time communication between your contacts

Resources

License

Stars

Watchers

Forks

Packages

No packages published