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

juv-ksip-softphone

v1.0.53

Published

A React WebRTC SIP softphone component for FreePBX/Asterisk with audio/video calls, auto-recording, connection monitoring, and API upload support

Readme

juv-ksip-softphone

A professional, draggable, resizable, transparent React WebRTC SIP softphone component for FreePBX / Asterisk. Supports audio and video calls, incoming call handling, codec selection, and a global ksipcall API for triggering calls from anywhere in your app.

WEB DOCUMENTATION

Visit Documentation: php-ksip-telnet & juv-ksip-softphone Documentation

Author: Kenneth H. Gimpao

Published: April 21, 2026


What is this?

juv-ksip-softphone is a React-based WebRTC SIP softphone designed to be dropped into any existing web application as a transparent floating overlay. It connects to a FreePBX / Asterisk PBX server using the SIP protocol over WebSocket (ws:// or wss://) and enables real-time audio and video calling directly from the browser — no plugins, no downloads required.

What is it for?

This component is built for developers who need to add VoIP calling capabilities to their existing React web applications without rebuilding their UI from scratch. Common use cases include:

  • Call center dashboards — agents can make and receive calls directly from their browser-based CRM or ticketing system
  • Customer support portals — embed a softphone into a helpdesk app so support staff can call customers with one click
  • Dispatch and operations systems — field coordinators can communicate via audio/video without switching applications
  • Healthcare platforms — doctors and staff can conduct audio/video consultations from within a patient management system
  • Any web app that needs calling — simply drop <Softphone /> into your app and it floats transparently on top

How does it work?

  1. SIP over WebSocket — The component connects to your FreePBX/Asterisk server via a WebSocket connection (ws:// or wss://). FreePBX listens on port 8088 (ws) or 8089 (wss) for WebSocket SIP traffic.

  2. WebRTC for media — Once a call is established, the browser uses WebRTC (built into all modern browsers) to handle the actual audio and video streams. This means no additional software is needed — the browser handles microphone, camera, and speaker access natively.

  3. SIP registration — On connect, the component registers your extension with the PBX just like a physical desk phone would. Once registered, you can make outgoing calls and receive incoming calls.

  4. Transparent overlay — The softphone renders as a position: fixed transparent layer on top of your existing app. Your app's UI is completely unaffected — the softphone simply floats above it.

  5. Global ksipcall API — A global window.ksipcall object is exposed so you can trigger calls from anywhere in your codebase — even from plain JavaScript, Vue, Angular, or any other framework running on the same page.

Browser  ──WebSocket──▶  FreePBX/Asterisk  ──SIP──▶  Other Phone/Extension
           (SIP/WS)           (PBX)                    (IP Phone, Softphone)

Browser  ◀──WebRTC──▶  FreePBX/Asterisk  ◀──RTP──▶  Other Phone/Extension
           (Audio/Video)      (Media)                  (Audio/Video Stream)

Screenshots


Features

  • 🎙 Audio & video calls via WebRTC + SIP (FreePBX / Asterisk)
  • 📞 Incoming call notifications with accept/reject
  • 🪟 Draggable + resizable floating video panel (expandable to fullscreen)
  • 🔢 Draggable dialpad panel
  • 💾 Auto-saves config to localStorage and auto-connects on reload
  • 🔄 Auto-reconnects on WebSocket disconnect
  • 🌐 Transparent background — overlays any existing app
  • 🎛 Floating messenger-style FAB nav (settings, dialer, opacity)
  • 📡 Global ksipcall API — trigger calls from plain JS or any framework
  • 🔒 ws:// / wss:// protocol selector
  • 🎚 Audio & video codec selection
  • ⚙ Fully configurable via props and in-app settings panel
  • 🔔 Ringtones for incoming and end call

Installation

npm install juv-ksip-softphone

Quick Start

import { Softphone } from 'juv-ksip-softphone';
import 'juv-ksip-softphone/styles';

function App() {
  return (
    <>
      <YourExistingApp />
      <Softphone />
    </>
  );
}

The softphone renders as a transparent overlay with a floating phone button (top-right). Click it to open the nav menu.


Props

SIP Connection Props

| Prop | Type | Default | Description | |---|---|---|---| | server | string | "" | FreePBX server IP or hostname | | wsProtocol | "ws" | "wss" | "ws" | WebSocket protocol. Use wss for HTTPS pages | | wsPort | string | "8088" | WebSocket port (8088 for ws, 8089 for wss) | | extension | string | "" | SIP extension number | | password | string | "" | SIP extension password | | displayName | string | "" | Caller ID display name (optional) |

Recording Props

| Prop | Type | Default | Description | |---|---|---|---| | autoRecord | boolean | false | Enable automatic recording of all calls | | recordingDir | string | "video/recordings/Ksip" | Directory path for saved recordings | | uploadApiUrl | string | "" | API endpoint URL for uploading recordings (optional) |

Settings Configuration Props

| Prop | Type | Default | Description | |---|---|---|---| | settingConfigToggles | object | all true | Controls which toggles are visible in settings UI | | settingConfigTogglesActiveState | object | varies | Sets initial active state for toggles | | settingConfigCodecs | object | all visible | Controls codec visibility and available options |

UI Props

| Prop | Type | Default | Description | |---|---|---|---| | enabledBubble | boolean | true | Show or hide the entire softphone bubble | | showDialer | boolean | true | Show the dialer button in the FAB nav | | showSetting | boolean | true | Show the settings button in the FAB nav | | showOpacity | boolean | true | Show the opacity button in the FAB nav | | answerwithVideoCall | boolean | false | Auto-answer incoming calls with video. Forces ShowIncomingCallAudio to false | | ShowIncomingCallVideoBtn | boolean | true | Show the video answer button on incoming calls | | ShowIncomingCallAudio | boolean | true | Show the audio answer button on incoming calls. Forced false when answerwithVideoCall=true |

Priority Order

Props are used as initial defaults. If the user has previously saved a config via the settings panel, localStorage takes priority. This allows the user to override props from within the app.


Examples

Basic — manual config via settings panel

<Softphone />

Pre-configured — auto-connect on load

<Softphone
  server="192.168.1.100"
  wsProtocol="ws"
  wsPort="8088"
  extension="1001"
  password="mypassword"
  displayName="John Doe"
/>

Full configuration

<Softphone
  // SIP Connection
  server="192.168.1.100"
  wsProtocol="ws"
  wsPort="8088"
  extension="1001"
  password="mypassword"
  displayName="John Doe"
  // UI
  enabledBubble={true}
  showDialer={true}
  showSetting={true}
  showOpacity={true}
  answerwithVideoCall={false}
  ShowIncomingCallVideoBtn={true}
  ShowIncomingCallAudio={true}
/>

Audio-only mode (no video answer button)

<Softphone
  ShowIncomingCallVideoBtn={false}
  ShowIncomingCallAudio={true}
/>

Auto-answer with video

<Softphone
  answerwithVideoCall={true}
  // ShowIncomingCallAudio is automatically false
/>

wss:// for HTTPS pages

<Softphone
  server="pbx.yourdomain.com"
  wsProtocol="wss"
  wsPort="8089"
  extension="1001"
  password="mypassword"
/>

Settings Configuration

<Softphone
  settingConfigToggles={{
    bubble: true,
    dialer: true,
    settings: false,  // Hide settings toggle
    opacity: true,
    autoAnswerVideo: true,
    answerButtonVideo: false,  // Hide video answer button toggle
    answerButtonAudio: true,
    fullscreen: true,
    autoRecording: true,
  }}
  settingConfigTogglesActiveState={{
    bubble: true,
    dialer: true,
    settings: true,
    opacity: true,
    autoAnswerVideo: true,  // Start with auto-answer video ON
    answerButtonVideo: true,
    answerButtonAudio: false,
    fullscreen: false,
    autoRecording: true,  // Start with recording ON
  }}
  settingConfigCodecs={{
    audio: { visible: true, codecs: ["PCMU", "PCMA"] },  // Only show these 2
    video: { visible: false, codecs: ["VP8", "H264"] },  // Hide video codecs section
  }}
/>

Auto Recording with API Upload

<Softphone
  autoRecord={true}
  recordingDir="video/recordings/Ksip"
  uploadApiUrl="https://your-domain.com/api/recordings/upload"
/>

Complete Example with All Features

<Softphone
  // SIP Connection
  server="192.168.1.100"
  wsProtocol="ws"
  wsPort="8088"
  extension="1001"
  password="mypassword"
  displayName="John Doe"
  
  // UI Controls
  enabledBubble={true}
  showDialer={true}
  showSetting={true}
  showOpacity={true}
  answerwithVideoCall={false}
  ShowIncomingCallVideoBtn={true}
  ShowIncomingCallAudio={true}
  fullscreen={false}
  
  // Recording
  autoRecord={true}
  recordingDir="video/recordings/Ksip"
  uploadApiUrl="https://your-domain.com/api/recordings/upload"
  
  // Settings Configuration
  settingConfigToggles={{
    bubble: true,
    dialer: true,
    settings: true,
    opacity: true,
    autoAnswerVideo: true,
    answerButtonVideo: true,
    answerButtonAudio: true,
    fullscreen: true,
    autoRecording: true,
  }}
  settingConfigTogglesActiveState={{
    bubble: true,
    dialer: true,
    settings: true,
    opacity: true,
    autoAnswerVideo: false,
    answerButtonVideo: true,
    answerButtonAudio: true,
    fullscreen: false,
    autoRecording: true,
  }}
  settingConfigCodecs={{
    audio: { visible: true, codecs: ["PCMU", "PCMA", "opus"] },
    video: { visible: true, codecs: ["VP8", "H264"] },
  }}
/>

ksipcall API

The ksipcall global lets you trigger calls from anywhere — plain JavaScript, Vue, Angular, or any other framework.

Audio Call

ksipcall.audio("123");

Video Call

ksipcall.video("123");

Via window (plain HTML / vanilla JS)

<button onclick="ksipcall.audio('123')">Call Support</button>
<button onclick="ksipcall.video('456')">Video Call</button>

Import in React / other frameworks

import { ksipcall } from 'juv-ksip-softphone';

ksipcall.audio("123");
ksipcall.video("123");

Settings Panel

The in-app settings panel (accessible via the ⚙ button) has a 3-column layout:

Column 1 — SIP Configuration

| Field | Description | Example | |---|---|---| | FreePBX Server IP | IP or hostname | 192.168.1.100 | | Extension | SIP extension number | 1001 | | Password | Extension SIP password | mypassword | | Display Name | Caller ID name (optional) | John Doe | | Protocol | ws:// or wss:// | ws:// | | Port | WebSocket port | 8088 |

Column 2 — Codecs

Audio Codecs: PCMU, PCMA, G722, G729, opus

Video Codecs: VP8, VP9, H264, H265, AV1

Opacity: FAB bubble opacity slider (min 30%)

Column 3 — UI Preferences

All UI props are configurable as toggles:

  • Show Bubble
  • Show Dialer Button
  • Show Settings Button
  • Show Opacity Button
  • Answer with Video
  • Show Video Answer Button
  • Show Audio Answer Button

CDN Usage (Browser)

You can use this package directly in the browser via CDN — no build tools required.

1. Include scripts

<!-- Styles -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/juv-ksip-softphone.css">

<!-- Softphone — fully self-contained, no other scripts needed -->
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/juv-ksip-softphone.cdn.js"></script>

2. Mount the softphone

The CDN build exposes window.JuvKsipSoftphone with Softphone, createRoot, and ksipcall all included.

<div id="softphone"></div>

<script>
  const { Softphone, createRoot, createElement } = window.JuvKsipSoftphone;
  createRoot(document.getElementById('softphone')).render(
    createElement(Softphone, {
      server: "192.168.1.100",
      wsProtocol: "ws",
      wsPort: "8088",
      extension: "1001",
      password: "mypassword",
      displayName: "John Doe"
    })
  );
</script>

Minimal (zero-config — use the settings panel)

<div id="softphone"></div>

<script>
  const { Softphone, createRoot, createElement } = window.JuvKsipSoftphone;
  createRoot(document.getElementById('softphone')).render(
    createElement(Softphone)
  );
</script>

3. Trigger calls via ksipcall (CDN)

Once the softphone is mounted, window.ksipcall is automatically available:

<button onclick="window.ksipcall.audio('1002')">Audio Call</button>
<button onclick="window.ksipcall.video('1002')">Video Call</button>

Notes:

  • No React or ReactDOM scripts needed — everything is bundled in juv-ksip-softphone.cdn.js.
  • Use wss:// when your page is served over HTTPS.
  • All props from the Props section work the same way via React.createElement.

WebSocket Protocol

| Protocol | Port | Use Case | |---|---|---| | ws:// | 8088 | Local network, HTTP pages | | wss:// | 8089 | Production, HTTPS pages (requires SSL cert on FreePBX) |

Note: Browsers block ws:// (insecure) when the page is served over https://. Use wss:// with a valid SSL certificate for production.


FreePBX / Asterisk Requirements

For WebRTC to work, each SIP extension must have these settings:

| Setting | Value | |---|---| | webrtc | yes | | use_avpf | yes | | media_encryption | dtls | | ice_support | yes | | bundle | yes | | rtcp_mux | yes | | dtls_setup | actpass |

Enable via FreePBX Admin UI

  1. Applications → Extensions → [your extension]
  2. Tab: Advanced
  3. Set WebRTCYes
  4. Submit → Apply Config

Enable via CLI (pjsip.endpoint_custom.conf)

[1001](+)
webrtc=yes
asterisk -rx "pjsip reload"

Floating Nav Controls

| Button | Action | |---|---| | 📞 Phone (FAB) | Open / close the nav menu | | ⊞ Grid | Toggle dialpad panel | | ⚙ Settings | Toggle settings & SIP config panel | | ≡ Sliders | Quick opacity adjustment (min 30%) |

Keyboard Shortcuts

| Shortcut | Action | |---|---| | Ctrl + Shift + K | Toggle settings panel |


Status Toast Notification

A floating status indicator appears at the top-center of the screen showing the current connection state:

| Status | Color | Behavior | |---|---|---| | Connected | 🟢 Green | Auto-hides after 5 seconds | | Reconnecting | 🟡 Yellow | Stays visible until connected | | Not Connected | 🔴 Red | Stays visible until connected |

  • The status toast includes a settings icon button for quick access to the settings panel
  • Automatically appears when the app loads
  • Shows real-time connection status updates
  • Always visible even when bubble is hidden (can be accessed via Ctrl + Shift + K)

Connection Monitoring

The softphone includes robust connection monitoring to detect server failures:

  • Automatic Re-registration: SIP registration refreshes every 10 minutes to maintain active connection
  • Disconnect Detection: Immediately detects when WebSocket connection is lost
  • Auto-reconnect: Attempts to reconnect every 3 seconds when connection is lost
  • Unexpected Unregistration: Automatically attempts to re-register if server rejects registration
  • Long-running Sessions: Maintains connection health even after hours of being connected without page reload

Example Scenario:

  • App connected at 9:00 AM
  • Server goes down at 9:30 AM (30 minutes later)
  • Status toast immediately shows "Reconnecting..." (yellow)
  • Auto-retry every 3 seconds
  • When server comes back online → auto-reconnects → "Connected" (green)

localStorage

Config is automatically saved under the key sip_softphone_config and restored on next page load, including:

  • SIP credentials (server, extension, password, display name)
  • WebSocket protocol and port
  • Selected audio/video codecs
  • UI preferences (all toggle states including "Show Bubble")
  • Recording settings (autoRecord, recordingDir, uploadApiUrl)
  • Fullscreen preference
  • Directory access permission state

showSetting is never saved to localStorage — it is always controlled by props.

Example localStorage data:

{
  "server": "192.168.1.100",
  "extension": "1001",
  "password": "mypassword",
  "displayName": "John Doe",
  "wsProtocol": "ws",
  "wsPort": "8088",
  "audioCodecs": ["PCMU", "PCMA"],
  "videoCodecs": ["VP8", "H264"],
  "enabledBubble": true,
  "showDialer": true,
  "showOpacity": true,
  "answerwithVideoCall": false,
  "ShowIncomingCallVideoBtn": true,
  "ShowIncomingCallAudio": true,
  "fullscreen": false,
  "autoRecord": true,
  "recordingDir": "video/recordings/Ksip",
  "uploadApiUrl": "https://api.example.com/upload",
  "hasDirectoryAccess": true
}

Auto Recording Feature

Overview

The softphone now supports automatic recording of audio and video calls with configurable save directory.

Features

  • ✅ Auto-record toggle in settings panel
  • ✅ Configurable recording directory
  • ✅ Saves as WebM format (video/webm or audio/webm)
  • ✅ Automatic download after call ends
  • ✅ Filename format: {directory}_{timestamp}.webm
  • ✅ Props support for default configuration
  • ✅ localStorage persistence

Props

autoRecord (boolean)

  • Default: false
  • Description: Enable automatic recording of all calls
  • Example:
<Softphone autoRecord={true} />

recordingDir (string)

  • Default: "video/recordings/Ksip"
  • Description: Directory path for saved recordings (browser will suggest this path in download dialog)
  • Example:
<Softphone 
  autoRecord={true}
  recordingDir="video/recordings/Ksip"
/>

Settings Panel

Toggle

  • Location: Settings → UI Preferences → "Auto Record Calls"
  • Behavior: Enable/disable automatic recording

Directory Input

  • Location: Appears below toggle when auto-record is enabled
  • Placeholder: "video/recordings/Ksip"
  • Default: "video/recordings/Ksip"
  • Note: Browser downloads use this as suggested filename path. Actual folder creation depends on browser settings.

How It Works

  1. Directory Selection: When auto-record is enabled for the first time, a modal appears asking to select a directory
  2. Browser Permission: User selects a folder using the File System Access API (Chrome/Edge)
  3. Recording Start: When a call is established (state = "active"), recording starts automatically if enabled
  4. Recording Stop: When call ends (state = "idle"), recording stops and saves directly to the selected directory
  5. File Format: WebM container with VP8/Opus codecs (or fallback to audio-only)
  6. File Naming: {ISO-timestamp}.webm
    • Example: 2024-04-21T14-30-45-123Z.webm
  7. Persistent Access: Browser remembers the directory permission for future recordings

Technical Details

MediaRecorder API

  • Uses browser's native MediaRecorder API
  • Captures both local and remote audio/video tracks
  • Collects chunks every 1 second
  • Creates downloadable blob on stop

Codec Support

  • Preferred: video/webm;codecs=vp8,opus
  • Fallback 1: video/webm
  • Fallback 2: audio/webm

Browser Compatibility

  • Chrome/Edge: Full support
  • Firefox: Full support
  • Safari: Limited (may require polyfill)

Usage Examples

Basic Usage

<Softphone autoRecord={true} />

Custom Directory

<Softphone 
  autoRecord={true}
  recordingDir="video/recordings/Ksip"
/>

Full Configuration

<Softphone
  server="192.168.1.100"
  extension="1001"
  password="secret"
  autoRecord={true}
  recordingDir="video/recordings/Ksip"
/>

Runtime Toggle

Users can enable/disable recording via the settings panel without reloading the page.

Storage

Settings are saved to localStorage under key sip_softphone_config:

{
  "autoRecord": true,
  "recordingDir": "video/recordings/Ksip",
  ...
}

Notes

  • File System Access API (Chrome/Edge 86+, Opera):

    • Modal prompts user to select directory on first use
    • Files save directly to selected folder without download prompts
    • Browser remembers permission (persists across sessions)
    • User can revoke permission in browser settings
  • Fallback for unsupported browsers (Firefox, Safari):

    • Uses traditional download method
    • Files download to default Downloads folder
    • No automatic directory creation
  • Security:

    • User must explicitly grant directory access
    • Permission can be revoked anytime
    • No access to files outside selected directory
  • File size depends on call duration and quality

  • WebM format is widely supported and efficient

  • To convert to MP3, use external tools like FFmpeg:

    ffmpeg -i recording.webm -vn -ar 44100 -ac 2 -b:a 192k output.mp3

Author

Kenneth H. Gimpao Published: 2026

GitHub Repository: https://github.com/kitenebie/SoftPhone-FreePBX

php-ksip-telnet (laravel): https://github.com/kitenebie/FreePBX-Console.git

License

MIT