【WebRTC】呼叫中心前端技术选型:SIP.js vs JsSIP vs Verto
前端开发者独立构建呼叫中心系统时,软电话库的选择往往是第一个需要迈过的坎。本文一次性讲清 SIP.js、JsSIP、Verto 三种主流方案,并给出两种常见架构下的最终选型建议。
引言
如果你是一名前端开发人员,正在规划一套基于 FreeSWITCH 的呼叫中心系统,那么“如何在浏览器里实现软电话”这个问题一定会摆在面前。目前业界主流的解决方案有三条路线:SIP.js、JsSIP 以及 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. 核心代码示例
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. 核心代码示例
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. 核心代码示例
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 服务端配置示例
<!-- 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. 架构示意图
┌──────────┐ 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 仓库及作者实际项目经验整理,力求客观准确。如有疑问或指正,请不吝赐教。
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐


所有评论(0)