【WebRTC】呼叫中心前端技术选型:SIP.js vs JsSIP vs Verto

前端开发者独立构建呼叫中心系统时,软电话库的选择往往是第一个需要迈过的坎。本文一次性讲清 SIP.js、JsSIP、Verto 三种主流方案,并给出两种常见架构下的最终选型建议。

引言

如果你是一名前端开发人员,正在规划一套基于 FreeSWITCH 的呼叫中心系统,那么"如何在浏览器里实现软电话"这个问题一定会摆在面前。目前业界主流的解决方案有三条路线:SIP.jsJsSIP 以及 FreeSWITCH 自带的 Verto

这三种方案各有特点,而且随着系统架构的不同(单机 FreeSWITCH 还是引入 Kamailio 负载均衡),最佳的选型结论也会发生逆转。本文将从零开始,详细拆解三者的技术背景、核心能力与优缺点,并通过对比表格和实际架构场景,帮你一次性搞清楚到底该选哪个。


第一部分:三种技术详细介绍

一、SIP.js:现代化浏览器 SIP 客户端

1. 背景与定位

SIP.js 由 OnSIP 团队于 2014 年从 JsSIP fork 而来。OnSIP 是一家商业 VoIP 服务商,他们在使用 JsSIP 开发 WebRTC 产品时发现其无法满足复杂业务场景的需求,因此决定独立维护并持续投入开发。如今 SIP.js 已成为社区最活跃的浏览器 SIP 库之一。

2. 技术特点

1)完整的 SIP over WebSocket 实现:在浏览器中通过 WebSocket 传输 SIP 协议,与 SIP 服务器完成信令交互。

2)TypeScript 原生支持:整个库使用 TypeScript 编写,类型定义完善,对现代化前端开发极为友好。

3)分层 API 设计

① SimpleUser:高层简化 API,仅需几行代码即可实现软电话。

② 完整底层 API:支持呼叫保持、转移(Transfer)、早期媒体(Early Media)、会话恢复等高级 SIP 特性。

4)活跃维护:持续更新,GitHub 活跃度高,文档详尽。

3. 核心代码示例
javascript 复制代码
import { Web } from 'sip.js';

const simpleUser = new Web.SimpleUser('wss://your-server:8083/ws', {
    aor: 'sip:1001@your-domain.com',
    media: {
        constraints: { audio: true, video: false },
        remote: { audio: document.getElementById('remoteAudio') }
    }
});

// 呼叫流程
await simpleUser.connect();    // WebSocket 连接
await simpleUser.register();   // SIP 注册
await simpleUser.call('sip:customer@your-domain.com');  // 发起呼叫
await simpleUser.hangup();     // 挂断
4. 优缺点总结
优点 缺点
✅ TypeScript 原生支持,开发体验优秀 ⚠️ SIP 协议较重,复杂网络下需配合 TURN/STUN 服务器
✅ API 设计现代化,SimpleUser 降低开发门槛 ⚠️ 对 SIP 协议有一定理解要求
✅ 完整支持高级 SIP 特性(转移、保持等)
✅ 与 FreeSWITCH 兼容性良好
✅ 社区活跃,文档完善

二、JsSIP:最早的浏览器 SIP 客户端

1. 背景与定位

JsSIP 由 José Luis Millán 和 Iñaki Baz Castillo (同时也是 RFC 7118 的作者)开发,是第一个完整的浏览器端 SIP 协议栈。它开创了在浏览器中通过 WebSocket 实现 SIP 通信的先河,是整个领域的奠基者。

2. 技术特点

1)RFC 7118 标准实现:由标准文档的作者亲自编写,协议规范性极高。

2)跨平台支持:既可在浏览器中运行,也支持 Node.js 环境。

3)轻量级设计:核心库体积较小,专注于基础 SIP 功能。

4)广泛的 SIP 服务器兼容性:与 OverSIP、Kamailio、Asterisk 等主流 SIP 服务器均可配合。

3. 核心代码示例
javascript 复制代码
var socket = new JsSIP.WebSocketInterface('wss://sip.myhost.com');
var configuration = {
    sockets: [socket],
    uri: 'sip:alice@example.com',
    password: 'superpassword'
};

var ua = new JsSIP.UA(configuration);
ua.start();

var session = ua.call('sip:bob@example.com', {
    eventHandlers: {
        'confirmed': function(e) { console.log('call answered'); },
        'ended': function(e) { console.log('call ended'); }
    }
});
4. 优缺点总结
优点 缺点
✅ 历史最悠久,协议规范性高 与 FreeSWITCH 直连存在已知兼容性问题(后文详述)
✅ 轻量级,核心库体积小 ❌ FreeSWITCH 核心开发者曾明确表示"JSSIP IS KNOWN TO BE BROKEN AND DOES NOT RELIABLY WORK"
✅ 由 RFC 作者开发,SIP 标准理解深刻 ❌ 项目活跃度已被 SIP.js 超越
✅ 官方文档明确列出与 Kamailio 兼容 ⚠️ TypeScript 支持较弱
⚠️ 高级 SIP 特性支持不如 SIP.js 完整

⚠️ 关于 JsSIP 与 FreeSWITCH 兼容性的重要说明

FreeSWITCH 核心开发者 Mike Jerris 在官方邮件列表中多次指出:"JSSIP IS KNOWN TO BE BROKEN AND DOES NOT RELIABLY WORK FOR ANYONE I HAVE SEEN POST ABOUT IT"。这个警告针对的是 JsSIP 直接连接 FreeSWITCH 的 mod_sofia 的场景。如果架构中引入 Kamailio 做中间层,这一问题可以被规避。我们会在后文详细分析。


三、Verto:FreeSWITCH 原生的 WebRTC 通信协议

1. 背景与定位

Verto(全称 Verto RTC)是由 FreeSWITCH 核心团队 专门为 WebRTC 场景设计的原生通信协议。它不是基于 SIP 的,而是 FreeSWITCH 内置的一个 endpoint 模块(mod_verto),使用 JSON-RPC over WebSocket 进行信令交互。名字"Verto"源自拉丁语"通信"或"信息传播",寓意简化现代设备间的通信。

2. 技术特点

1)FreeSWITCH 原生协议:与 FreeSWITCH 同根生,由核心团队开发维护,兼容性无可比拟。

2)JSON-RPC over WebSocket:使用简洁的 JSON 格式进行信令交互,而非复杂的 SIP 协议。

3)原生支持高级功能:会议(Conference)、实时状态更新(LiveArray)、消息推送等开箱即用。

4)简化 Web 开发:设计目标就是让 Web 开发者能用最简单的代码实现复杂的实时通信功能。

5)社区 TypeScript 支持 :社区项目 vertojs 提供了 TypeScript 类型定义。

3. 核心代码示例
javascript 复制代码
import { Verto } from 'vertojs';

const verto = new Verto({
    transportConfig: {
        socketUrl: 'wss://your-freeswitch:8082',
        login: '1001',
        passwd: 'password'
    },
    rtcConfig: { iceServers: [{ urls: 'stun:stun.l.google.com:19302' }] }
});

await verto.login();

// 获取本地媒体流
const localStream = await navigator.mediaDevices.getUserMedia({ audio: true });

// 发起呼叫
const call = verto.call(localStream.getTracks(), '9664');

// 监听远端音频
call.subscribeEvent('track', (track) => {
    if (track.kind === 'audio') {
        const stream = new MediaStream();
        stream.addTrack(track);
        document.getElementById('remoteAudio').srcObject = stream;
    }
});

// 接听来电
verto.subscribeEvent('invite', (call) => {
    call.answer(localStream.getTracks());
});
4. FreeSWITCH 服务端配置示例
XML 复制代码
<!-- conf/autoload_configs/verto.conf.xml -->
<configuration name="verto.conf">
  <profiles>
    <profile name="mine">
      <param name="bind-local" value="0.0.0.0:8082" secure="true"/>
      <param name="secure-combined" value="/path/to/wss.pem"/>
      <param name="userauth" value="true"/>
    </profile>
  </profiles>
</configuration>

<!-- 用户配置中启用 Verto -->
<user id="1001">
  <params>
    <param name="verto-context" value="public"/>
    <param name="jsonrpc-allowed-methods" value="verto"/>
  </params>
</user>
5. 优缺点总结
优点 缺点
与 FreeSWITCH 完美兼容,由核心团队开发维护 ⚠️ 生态相对较小,社区资源不如 SIP.js 丰富
✅ 协议简洁(JSON over WebSocket),开发门槛低 ⚠️ 仅适用于 FreeSWITCH 平台,无法与其他 SIP 服务器互通
✅ 原生支持会议、实时状态更新等高级功能 ⚠️ 社区维护的 TypeScript 版本(vertojs)版本号较低(0.0.5),功能尚在完善中
✅ 避免 SIP 协议的复杂性和 NAT 穿透问题
✅ FreeSWITCH 官方强烈推荐

第二部分:三方对比总览

对比维度 SIP.js JsSIP Verto
本质 SIP over WebSocket 客户端库 SIP over WebSocket 客户端库 FreeSWITCH 原生 JSON-RPC 协议
开发者 OnSIP 团队(商业 VoIP 服务商) RFC 7118 作者团队 FreeSWITCH 核心团队
与 FreeSWITCH 直连兼容性 ✅ 良好 ❌ 存在已知严重问题 ✅✅ 完美(官方原生)
官方推荐度(单机) 可接受,但更推荐 Verto ❌ 官方明确不推荐 ✅✅ 官方强烈推荐
协议复杂度 高(完整 SIP 协议栈) 高(完整 SIP 协议栈) 低(JSON-RPC 简洁协议)
TypeScript 支持 ✅ 一流(原生 TS 编写) ⚠️ 较弱 ✅ 有社区版本(vertojs)
高级功能 保持/转移/早期媒体等完整 SIP 特性 基础 SIP 功能 会议、LiveArray、消息推送等原生支持
生态与社区 ✅ 活跃,文档完善 ⚠️ 维护模式,活跃度降低 ⚠️ 生态较小,但官方文档完善
跨平台 浏览器 浏览器 + Node.js 浏览器(FreeSWITCH 服务端)
学习曲线 中等(需理解 SIP 概念) 中等(需理解 SIP 概念) 低(JSON API,无 SIP 负担)
NAT 穿透 需配合 TURN/STUN 需配合 TURN/STUN 同样需 TURN/STUN,但协议层面更简洁

第三部分:两种架构下的选型建议

场景一:WebRTC 与 FreeSWITCH 直接交互(单机或简单集群)

在这个场景下,浏览器直接通过 WebSocket 与 FreeSWITCH 通信,FreeSWITCH 的 mod_verto 或 mod_sofia 直接处理信令。

1. 推荐:Verto

1)官方原生支持:由 FreeSWITCH 核心团队设计,是官方为 WebRTC 场景量身定制的解决方案。

2)开发效率最高:JSON 比 SIP 信令简单得多,前端开发者无需深入理解 SIP 协议即可上手。

3)功能完备:呼叫中心所需的会议、状态同步等功能开箱即用。

4)规避兼容性问题:不存在 JsSIP 直连 FreeSWITCH 的稳定性风险。

5)如果因某些原因无法使用 Verto (例如需要对接非 FreeSWITCH 的 SIP 服务器,或团队对 SIP 协议有成熟经验),则 SIP.js 是稳妥的第二选择。

2. 不推荐:JsSIP(直连场景)

理由如上一节所述,官方明确指出其与 FreeSWITCH 直连存在根本性问题,不应在直连架构中使用。


场景二:WebRTC 与 FreeSWITCH 之间引入 Kamailio 做负载均衡

1. 架构示意图
XML 复制代码
┌──────────┐  WSS (SIP over WS)  ┌──────────────┐   SIP (UDP/TCP)  ┌─────────────┐
│  Browser │ ──────────────────▶│   Kamailio   │ ───────────────▶│ FreeSWITCH 1 │
│  (SIP.js │                     │  (负载均衡)   │                  ├─────────────┤
│   或     │ ◀──────────────────│              │ ◀───────────────│ FreeSWITCH 2 │
│  JsSIP)  │                     └──────────────┘                  └─────────────┘
└──────────┘                                                                                
2. 为什么 Verto 不再适用?

Kamailio 是一个 SIP 服务器,其负载均衡、路由、Dispatcher 等核心模块都是为 SIP 协议设计的。Verto 使用 JSON-RPC over WebSocket,不是 SIP 协议,因此无法被 Kamailio 识别和处理。虽然 Kamailio 可以转发 WebSocket 连接,但它无法解析 Verto 的信令内容来做智能路由。在此架构下,Verto 被迫出局。

3. 推荐:JsSIP

1)官方明确支持 Kamailio:JsSIP 的官方文档在"生态项目"章节中明确列出 Kamailio 作为兼容的 SIP 服务器,这是非常强的背书。

2)与 Kamailio 生态高度契合:JsSIP 的作者 Iñaki Baz Castillo 同时也是 RFC 7118 和 OverSIP(专为 WebSocket 设计的 SIP 代理)的作者,他对 Kamailio 生态的理解非常深入。

3)规避直连问题:通过 Kamailio 中转,JsSIP 与 FreeSWITCH 直连的已知问题被彻底规避。Kamailio 负责 WebSocket 连接管理和 SIP 协议转换,与 FreeSWITCH 之间使用标准的 UDP/TCP SIP 通信,稳定性有保障。

4)轻量级设计:代码量较小,浏览器加载性能更优。

4. 备选:SIP.js

SIP.js 同样完全兼容 Kamailio,如果你或团队:

1)对 TypeScript 有强需求;

2)需要 SIP.js 的 SimpleUser API 来快速开发;

3)未来可能脱离 FreeSWITCH,对接其他 SIP 服务器;

那么 SIP.js 可以作为备选方案,它与 JsSIP 在这个架构下的差距很小,更多是个人偏好问题。


结语

架构 首选方案 备选方案
单机 FreeSWITCH(或简单集群,无 Kamailio) Verto SIP.js
Kamailio + FreeSWITCH 集群(运营商级负载均衡) JsSIP SIP.js

选择软电话库时,建议先确定你的系统最终架构:是简单部署一个 FreeSWITCH 就上线,还是需要支持高并发、多地容灾的集群方案。架构决定技术路线,技术路线决定最终选型。

如果你正在构建呼叫中心系统,并且上述方案仍无法覆盖你的特定需求(例如需要与特定的 PBX 对接、需要使用特定协议特性等),欢迎在评论区留言交流。


本文基于 FreeSWITCH 官方社区讨论、各项目 GitHub 仓库及作者实际项目经验整理,力求客观准确。如有疑问或指正,请不吝赐教。

相关推荐
Pedantic1 小时前
SwiftUI 手势层级(Gesture Hierarchy)详解
前端
飘尘1 小时前
前端转型全栈(Java后端)的快速上手指引
前端·后端·全栈
一颗烂土豆1 小时前
Meshopt 压缩深度解析,为什么它比 Draco 更快
前端·javascript·webgl
浏览器工程师2 小时前
AI Agent 接浏览器任务,先别让它一路点到底
前端·后端
雨季mo浅忆2 小时前
VSCode自动格式化三要素
前端
爱勇宝3 小时前
深扒 Anthropic 1680 位工程师简历:应届生几乎没机会,AI 公司最缺的不是博士
前端·后端·程序员
kyriewen4 小时前
同事每天催我 Code Review,我写了个脚本让 AI 替我 review PR——现在他反过来催 AI 了
前端·javascript·ai编程
user20585561518136 小时前
Windows 项目安装时报 `node-sass` 错误,如何快速处理
前端
LiaCode6 小时前
Redis 在生产项目的使用
前端·后端