# @serve.zone/siprouter A production-grade **SIP B2BUA + WebRTC bridge** built with TypeScript and Rust. Routes calls between SIP providers, SIP hardware devices, and browser softphones β€” with real-time codec transcoding, ML noise suppression, neural TTS announcements, and a slick web dashboard. ## Issue Reporting and Security For reporting bugs, issues, or security vulnerabilities, please visit [community.foss.global/](https://community.foss.global/). This is the central community hub for all issue reporting. Developers who sign and comply with our contribution agreement and go through identification can also get a [code.foss.global/](https://code.foss.global/) account to submit Pull Requests directly. --- ## πŸ”₯ What It Does siprouter sits between your SIP trunk providers and your endpoints β€” hardware phones, ATAs, browser softphones β€” and handles **everything** in between: - πŸ“ž **SIP B2BUA** β€” Terminates and re-originates calls with full RFC 3261 dialog state management - 🌐 **WebRTC Bridge** β€” Browser-based softphone with bidirectional audio to the SIP network - πŸŽ›οΈ **Multi-Provider Trunking** β€” Register with multiple SIP providers simultaneously (sipgate, easybell, o2, etc.) - πŸ”Š **Rust Codec Engine** β€” Real-time Opus ↔ G.722 ↔ PCMU ↔ PCMA transcoding in native Rust - πŸ€– **ML Noise Suppression** β€” RNNoise denoiser with per-direction state (to SIP / to browser) - πŸ—£οΈ **Neural TTS** β€” Kokoro-powered "connecting your call" announcements, pre-encoded for instant playback - πŸ”€ **Hub Model Calls** β€” N-leg calls with dynamic add/remove, transfer, and RTP fan-out - πŸ–₯️ **Web Dashboard** β€” Real-time SPA with live call monitoring, browser phone, contact management, provider config --- ## πŸ—οΈ Architecture ``` β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ Browser Softphone β”‚ β”‚ (WebRTC via WebSocket signaling) β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ Opus/WebRTC β–Ό β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ siprouter β”‚ β”‚ β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚ β”‚ Call Hub β”‚ β”‚ Rust Transcoder β”‚ β”‚ β”‚ β”‚ N legs │──│ Opus/G.722/PCM β”‚ β”‚ β”‚ β”‚ fan-out β”‚ β”‚ + RNNoise β”‚ β”‚ β”‚ β””β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚ β”‚ β”‚ β”‚ β”Œβ”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚ β”‚ SIP Stackβ”‚ β”‚ Kokoro TTS β”‚ β”‚ β”‚ β”‚ Dialog SMβ”‚ β”‚ (ONNX Runtime) β”‚ β”‚ β”‚ β””β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚ β”‚ β”‚ β”‚ β”Œβ”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚ β”‚ Local Registrar + Provider β”‚ β”‚ β”‚ β”‚ Registration Engine β”‚ β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β” β”‚ SIP Devices β”‚ β”‚ SIP Trunk β”‚ β”‚ (HT801, etc)β”‚ β”‚ Providers β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ``` ### The Hub Model Every call is a **hub** with N legs. Each leg is either a `SipLeg` (hardware device or provider) or a `WebRtcLeg` (browser). RTP flows through the hub β€” each leg's received audio is forwarded to all other legs, with codec transcoding handled transparently by the Rust engine. --- ## πŸš€ Getting Started ### Prerequisites - **Node.js** β‰₯ 20 with `tsx` globally available - **pnpm** for package management - **Rust** toolchain (for building the codec engine and TTS) ### Install & Build ```bash # Clone and install pnpm install # Build the Rust binaries (opus-codec + tts-engine) pnpm run buildRust # Bundle the web frontend pnpm run bundle ``` ### Configuration Create `.nogit/config.json` with your setup: ```jsonc { "proxy": { "lanIp": "192.168.1.100", // Your server's LAN IP "lanPort": 5070, // SIP signaling port "rtpPortRange": [20000, 20200],// RTP relay port pool (even ports) "webUiPort": 3060 // Dashboard port }, "providers": [ { "id": "my-trunk", "name": "My SIP Provider", "host": "sip.provider.com", "port": 5060, "username": "user", "password": "pass", "codecs": ["G.722", "PCMA", "PCMU"], "registerExpiry": 3600 } ], "devices": [ { "id": "desk-phone", "name": "Desk Phone", "type": "sip" } ], "routing": { "inbound": { "default": { "target": "all-devices", "ringBrowser": true } } } } ``` ### TTS Setup (Optional) For neural "connecting your call" announcements, download the Kokoro TTS model: ```bash mkdir -p .nogit/tts # Download the full-quality model (310MB) + voices (27MB) curl -L -o .nogit/tts/kokoro-v1.0.onnx \ https://github.com/mzdk100/kokoro/releases/download/V1.0/kokoro-v1.0.onnx curl -L -o .nogit/tts/voices.bin \ https://github.com/mzdk100/kokoro/releases/download/V1.0/voices.bin ``` If the model files aren't present, the announcement feature is simply disabled β€” everything else works fine. ### Run ```bash pnpm start ``` The SIP proxy starts on the configured port and the web dashboard is available at `http://:3060`. ### HTTPS (Optional) Place `cert.pem` and `key.pem` in `.nogit/` for TLS on the dashboard. --- ## πŸ“‚ Project Structure ``` siprouter/ β”œβ”€β”€ ts/ # TypeScript source β”‚ β”œβ”€β”€ sipproxy.ts # Main entry β€” bootstraps everything β”‚ β”œβ”€β”€ config.ts # Config loader & validation β”‚ β”œβ”€β”€ registrar.ts # Local SIP registrar for devices β”‚ β”œβ”€β”€ providerstate.ts # Per-provider upstream registration engine β”‚ β”œβ”€β”€ frontend.ts # Web dashboard HTTP/WS server + REST API β”‚ β”œβ”€β”€ webrtcbridge.ts # WebRTC signaling layer β”‚ β”œβ”€β”€ opusbridge.ts # Rust IPC bridge (smartrust) β”‚ β”œβ”€β”€ codec.ts # High-level RTP transcoding interface β”‚ β”œβ”€β”€ announcement.ts # Neural TTS announcement generator β”‚ β”œβ”€β”€ sip/ # Zero-dependency SIP protocol library β”‚ β”‚ β”œβ”€β”€ message.ts # SIP message parser/builder/mutator β”‚ β”‚ β”œβ”€β”€ dialog.ts # RFC 3261 dialog state machine β”‚ β”‚ β”œβ”€β”€ helpers.ts # SDP builder, digest auth, codec registry β”‚ β”‚ └── rewrite.ts # SIP URI + SDP body rewriting β”‚ └── call/ # Hub-model call management β”‚ β”œβ”€β”€ call-manager.ts # Central registry, factory, routing β”‚ β”œβ”€β”€ call.ts # Call hub β€” owns N legs, media fan-out β”‚ β”œβ”€β”€ sip-leg.ts # SIP device/provider connection β”‚ β”œβ”€β”€ webrtc-leg.ts # Browser WebRTC connection β”‚ └── rtp-port-pool.ts # UDP port allocation β”œβ”€β”€ ts_web/ # Web frontend (Lit-based SPA) β”‚ β”œβ”€β”€ elements/ # Web components (dashboard, phone, etc.) β”‚ └── state/ # App state, WebRTC client, notifications β”œβ”€β”€ rust/ # Rust workspace β”‚ └── crates/ β”‚ β”œβ”€β”€ opus-codec/ # Real-time audio transcoder (Opus/G.722/PCM) β”‚ └── tts-engine/ # Kokoro neural TTS CLI β”œβ”€β”€ html/ # Static HTML shell β”œβ”€β”€ .nogit/ # Secrets, config, models (gitignored) └── dist_rust/ # Compiled Rust binaries (gitignored) ``` --- ## 🎧 Codec Engine (Rust) The `opus-codec` binary handles all real-time audio processing via a JSON-over-stdio IPC protocol: | Codec | Payload Type | Sample Rate | Use Case | |-------|-------------|-------------|----------| | **Opus** | 111 | 48 kHz | WebRTC browsers | | **G.722** | 9 | 16 kHz | HD SIP devices | | **PCMU** (G.711 Β΅-law) | 0 | 8 kHz | Legacy SIP | | **PCMA** (G.711 A-law) | 8 | 8 kHz | Legacy SIP | **Features:** - Per-call isolated codec sessions (no cross-call state corruption) - FFT-based sample rate conversion via `rubato` - **RNNoise ML noise suppression** with per-direction state β€” denoises audio flowing to SIP separately from audio flowing to the browser - Raw PCM encoding for TTS frame processing --- ## πŸ—£οΈ Neural TTS (Rust) The `tts-engine` binary uses [Kokoro TTS](https://github.com/mzdk100/kokoro) (82M parameter neural model) to synthesize announcements at startup: - **24 kHz, 16-bit mono** output - **25+ voice presets** β€” American/British, male/female (e.g., `af_bella`, `am_adam`, `bf_emma`, `bm_george`) - **~800ms** synthesis time for a 3-second announcement - Pre-encoded to G.722 + Opus for zero-latency RTP playback during call setup --- ## 🌐 Web Dashboard & REST API ### Dashboard Views | View | Description | |------|-------------| | **Overview** | Stats tiles β€” uptime, providers, devices, active calls | | **Calls** | Active calls with leg details, codec info, packet counters. Add/remove legs, transfer, hangup | | **Phone** | Browser softphone β€” mic/speaker selection, audio meters, dial pad, incoming call popup | | **Contacts** | Contact management with click-to-call | | **Providers** | SIP trunk config with registration status | | **Log** | Live streaming log viewer | ### REST API | Endpoint | Method | Description | |----------|--------|-------------| | `/api/status` | GET | Full system status (providers, devices, calls) | | `/api/call` | POST | Originate a call | | `/api/hangup` | POST | Hang up a call | | `/api/call/:id/addleg` | POST | Add a leg to an active call | | `/api/call/:id/addexternal` | POST | Add an external participant | | `/api/call/:id/removeleg` | POST | Remove a leg from a call | | `/api/transfer` | POST | Transfer a call | | `/api/config` | GET/POST | Read or update configuration (hot-reload) | ### WebSocket Events Connect to `/ws` for real-time push: ```jsonc { "type": "status", "data": { ... } } // Full status snapshot (1s interval) { "type": "log", "data": { "message": "..." } } // Log lines in real-time ``` --- ## πŸ”Œ Ports | Port | Protocol | Purpose | |------|----------|---------| | 5070 (configurable) | UDP | SIP signaling | | 20000–20200 (configurable) | UDP | RTP relay (even ports, per-call allocation) | | 3060 (configurable) | TCP | Web dashboard + WebSocket + REST API | --- ## πŸ› οΈ Development ```bash # Start in dev mode pnpm start # Build Rust crates pnpm run buildRust # Bundle web frontend pnpm run bundle # Restart background server (build + bundle + restart) pnpm run restartBackground ``` ### Key Design Decisions - **Hub Model** β€” Calls are N-leg hubs, not point-to-point. This enables multi-party, dynamic leg manipulation, and transfer without tearing down the call. - **Zero-dependency SIP library** β€” `ts/sip/` is a pure data-level SIP stack (parse/build/mutate/serialize). No transport or timer logic β€” those live in the application layer. - **Rust for the hot path** β€” Codec transcoding and noise suppression run in native Rust for real-time performance. TypeScript handles signaling and orchestration. - **Per-session codec isolation** β€” Each call gets its own Opus/G.722 encoder/decoder state in the Rust process, preventing stateful codec prediction from leaking between concurrent calls. --- ## License and Legal Information This repository contains open-source code licensed under the MIT License. A copy of the license can be found in the [license](./license) file. **Please note:** The MIT License does not grant permission to use the trade names, trademarks, service marks, or product names of the project, except as required for reasonable and customary use in describing the origin of the work and reproducing the content of the NOTICE file. ### Trademarks This project is owned and maintained by Task Venture Capital GmbH. The names and logos associated with Task Venture Capital GmbH and any related products or services are trademarks of Task Venture Capital GmbH or third parties, and are not included within the scope of the MIT license granted herein. Use of these trademarks must comply with Task Venture Capital GmbH's Trademark Guidelines or the guidelines of the respective third-party owners, and any usage must be approved in writing. Third-party trademarks used herein are the property of their respective owners and used only in a descriptive manner, e.g. for an implementation of an API or similar. ### Company Information Task Venture Capital GmbH Registered at District Court Bremen HRB 35230 HB, Germany For any legal inquiries or further information, please contact us via email at hello@task.vc. By using this repository, you acknowledge that you have read this section, agree to comply with its terms, and understand that the licensing of the code does not imply endorsement by Task Venture Capital GmbH of any derivative works.