【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 服务器完成信令交互。2TypeScript 原生支持整个库使用 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:1001your-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:customeryour-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. 技术特点1RFC 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:aliceexample.com, password: superpassword }; var ua new JsSIP.UA(configuration); ua.start(); var session ua.call(sip:bobexample.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 做中间层这一问题可以被规避。我们会在后文详细分析。三、VertoFreeSWITCH 原生的 WebRTC 通信协议1. 背景与定位Verto全称 Verto RTC是由FreeSWITCH 核心团队专门为 WebRTC 场景设计的原生通信协议。它不是基于 SIP 的而是 FreeSWITCH 内置的一个 endpoint 模块mod_verto使用JSON-RPC over WebSocket进行信令交互。名字“Verto”源自拉丁语“通信”或“信息传播”寓意简化现代设备间的通信。2. 技术特点1FreeSWITCH 原生协议与 FreeSWITCH 同根生由核心团队开发维护兼容性无可比拟。2JSON-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 nameverto.conf profiles profile namemine param namebind-local value0.0.0.0:8082 securetrue/ param namesecure-combined value/path/to/wss.pem/ param nameuserauth valuetrue/ /profile /profiles /configuration !-- 用户配置中启用 Verto -- user id1001 params param nameverto-context valuepublic/ param namejsonrpc-allowed-methods valueverto/ /params /user5. 优缺点总结优点缺点✅与 FreeSWITCH 完美兼容由核心团队开发维护⚠️ 生态相对较小社区资源不如 SIP.js 丰富✅ 协议简洁JSON over WebSocket开发门槛低⚠️仅适用于 FreeSWITCH 平台无法与其他 SIP 服务器互通✅ 原生支持会议、实时状态更新等高级功能⚠️ 社区维护的 TypeScript 版本vertojs版本号较低0.0.5功能尚在完善中✅ 避免 SIP 协议的复杂性和 NAT 穿透问题✅ FreeSWITCH 官方强烈推荐第二部分三方对比总览对比维度SIP.jsJsSIPVerto本质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. 推荐Verto1官方原生支持由 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. 推荐JsSIP1官方明确支持 KamailioJsSIP 的官方文档在“生态项目”章节中明确列出 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.jsSIP.js 同样完全兼容 Kamailio如果你或团队1对 TypeScript 有强需求2需要 SIP.js 的 SimpleUser API 来快速开发3未来可能脱离 FreeSWITCH对接其他 SIP 服务器那么 SIP.js 可以作为备选方案它与 JsSIP 在这个架构下的差距很小更多是个人偏好问题。结语架构首选方案备选方案单机 FreeSWITCH或简单集群无 KamailioVertoSIP.jsKamailio FreeSWITCH 集群运营商级负载均衡JsSIPSIP.js选择软电话库时建议先确定你的系统最终架构是简单部署一个 FreeSWITCH 就上线还是需要支持高并发、多地容灾的集群方案。架构决定技术路线技术路线决定最终选型。如果你正在构建呼叫中心系统并且上述方案仍无法覆盖你的特定需求例如需要与特定的 PBX 对接、需要使用特定协议特性等欢迎在评论区留言交流。本文基于 FreeSWITCH 官方社区讨论、各项目 GitHub 仓库及作者实际项目经验整理力求客观准确。如有疑问或指正请不吝赐教。