关于视频对讲项目的研究对比:LiveKit / Jitsi / SRS
在本机(Windows + Docker)下载并部署了三个主流开源 WebRTC 视频对讲项目,用同一台电脑的两个浏览器标签页实测双向视频通话,目的是对比哪个更适合「开箱即用」。
-
LiveKit :现代 SFU,部署最轻、SDK 最全,实测可用 ✅
-
Jitsi :功能最全(完整会议 UI),部署最重,已修复并可测试 ✅
-
SRS :偏流媒体 / 直播方向,不适合开箱即用做双向对讲(详见下文)⚠️
目录结构
video-call-comparison/
├── README.md ← 本文档
├── 对比可视化.html ← 三项目对比可视化页面
├── livekit/
│ ├── livekit-server/ ← 官方源码(浅克隆)
│ ├── run/
│ │ ├── livekit.yaml ← 服务端配置(已生效)
│ │ └── livekit-server.exe ← 本机二进制(备用)
│ └── test-client/
│ ├── server.js ← 本地测试客户端(签发 token + 托管页面)
│ ├── index.html ← 测试页面(房间连接 / 发布 / 订阅展示)
│ └── node_modules/ ← livekit-client SDK(本地安装)
├── jitsi/
│ ├── docker-jitsi-meet/ ← Jitsi 官方 docker-compose 仓库
│ │ └── .env ← 部署配置(已按本机调试优化)
│ ├── jitsi-meet/ ← 官方前端源码(浅克隆)
│ └── .jitsi-meet-cfg/ ← 各服务持久化配置目录
└── srs/
├── srs/ ← 官方源码(浅克隆)
├── demos/ ← 从容器拷出的 demo 页面
├── run/
│ └── srs.conf ← 服务端配置(已生效)
└── docker.conf.actual ← 配置取证副本
环境要求
| 依赖 | 版本 |
|---|---|
| Windows | 10/11 |
| Docker Desktop | 29.x(WSL2 后端) |
| Node.js | ≥ 18(LiveKit 测试客户端用) |
| Git | ≥ 2.x |
本机内存共 15.7GB,但系统空闲内存常年紧张(浏览器、WSL、其他应用占用高)。
Jitsi 前端吃内存,测试前建议关闭占用高的程序。
快速开始(当前运行状态)
三个服务均已部署并运行(截至本 README 编写时):
| 服务 | 容器 | 状态 | 端口 |
|---|---|---|---|
| LiveKit | livekit |
Up | 7880/7881 TCP,50000--50100 UDP |
| Jitsi | docker-jitsi-meet-{web,jvb,jicofo,prosody}-1 |
Up | 8000/8443 TCP,10000 UDP |
| SRS | srs |
Up | 1935/1985/8080 TCP,8000 UDP |
| LiveKit 测试页 | node 进程 | 监听 3000 | 3000 |
测试入口:
-
LiveKit:
http://localhost:3000 -
Jitsi:
https://localhost:8443 -
SRS:
http://localhost:8080/players/whip.html(推)/.../whep.html(拉)
一、LiveKit(实测可用 ✅)
部署
用官方镜像启动,关键点:
-
必须传
--node-ip 127.0.0.1,让 SFU 广播回环地址(否则广播容器私网 IP,本机浏览器连不上,媒体流建立失败); -
UDP 端口范围要与发布端口一致。
docker run -d --name livekit
-p 7880:7880 -p 7881:7881
-p 50000-50100:50000-50100/udp-v D:\myDoubao\video-call-comparison\livekit\run\livekit.yaml:/etc/livekit.yaml
docker.1ms.run/livekit/livekit-server:latest `
--config /etc/livekit.yaml --node-ip 127.0.0.1
livekit/run/livekit.yaml 核心内容:
port: 7880
rtc:
tcp_port: 7881
port_range_start: 50000
port_range_end: 50100
use_external_ip: false # 关闭外部 IP 探测,强制用 --node-ip
keys:
devkey: secret # 开发用 API key/secret,生产务必更换
logging:
level: info
镜像因网络原因使用加速器
docker.1ms.run(LiveKit 官方镜像)。版本 v1.13.10。
调试与测试
启动测试客户端(签发 JWT token + 托管页面):
node D:\myDoubao\video-call-comparison\livekit\test-client\server.js
# 输出:LiveKit test client running at http://localhost:3000
浏览器开两个标签页 访问 http://localhost:3000,输入同一房间名 (如 room1),分别点击加入。两个页面都能看到对方的摄像头画面即成功。
验证服务端配置已生效:
docker logs livekit 2>&1 | Select-String "nodeIP|portICERange"
# 应看到 nodeIP=127.0.0.1, rtc.portICERange=[50000,50100]
踩坑记录
| 问题 | 现象 | 根因 | 解决 |
|---|---|---|---|
| 连不上 | could not establish pc connection |
开发模式默认监听 UDP 7882,与发布的 50000--50100 不匹配;且广播容器 IP | 用配置文件固定 UDP 范围 + --node-ip 127.0.0.1 |
| Node 无法自动验证 | LiveKit 报 "doesn't seem to be supported on this browser" | livekit-client 需浏览器环境建 RTCPeerConnection | 放弃 Node 端自动验证,改用浏览器双标签实测 |
二、Jitsi(已修复,可测试 ✅)
部署
Jitsi 用官方 docker-compose 全栈(web /prosody/jicofo /jvb 四个服务):
cd D:\myDoubao\video-call-comparison\jitsi\docker-jitsi-meet
# 首次需复制 env.example 为 .env,本文已配置好
docker compose up -d
.env 关键配置(已按本机调试优化):
CONFIG=D:/myDoubao/video-call-comparison/jitsi/.jitsi-meet-cfg
HTTP_PORT=8000
HTTPS_PORT=8443
PUBLIC_URL=https://localhost:8443
ENABLE_XMPP_WEBSOCKET=1
JVB_ADVERTISE_IPS=127.0.0.1 # 关键:让 JVB 广播回环地址,同机双标签可直达
JVB_COLIBRI_PORT=16080 # 关键:避开 SRS 的 8080 与 Windows 排除段
Jitsi 四个服务镜像均为
ghcr.io/jitsi/*:unstable。
调试与测试
浏览器开两个标签页 访问 https://localhost:8443(自签名证书,浏览器点「高级 → 继续访问」):
-
标签页 A:新建会议;
-
标签页 B:输入同一房间名加入;
-
两个标签都允许摄像头 / 麦克风。
验证 JVB 已正确注册为视频桥:
docker logs --tail 12 docker-jitsi-meet-jvb-1 2>&1
# 应看到 Joined MUC: jvbbrewery@internal-muc.meet.jitsi(无 DNS 报错)
踩坑记录(重点,曾导致 "开第二个标签全崩")
| 问题 | 现象 | 根因 | 解决 |
|---|---|---|---|
| 标签页全崩 | 开第二个标签后所有标签崩溃 | JVB 容器没挂进 meet.jitsi内部网络 → 无法解析 xmpp.meet.jitsi → 注册不上视频桥,第二人加入时会议拿不到视频桥 |
干净重建:docker compose down && docker compose up -d,确保 JVB 联网 |
| 端口冲突 | JVB 无法启动 / 联网 | SRS 占用宿主 8080,JVB colibri 也要 8080 | 改 JVB_COLIBRI_PORT=16080 |
| Windows 端口排除 | bind: forbidden by its access permissions |
18080 落在 WSL2 排除段(17553--18152) | 改到 16080(不在排除段) |
排查要点
:JVB 必须能解析
xmpp.meet.jitsi。检查
docker inspect --format '{``{json .NetworkSettings.Networks}}' docker-jitsi-meet-jvb-1,若输出
{}说明没联网,需重建。
三、SRS(偏流媒体,双向对讲需自行组装 ⚠️)
部署
SRS 用核心镜像(ossrs/srs:5,阿里云源可拉取),必须显式传入自定义配置(否则镜像按默认 conf/docker.conf 启动):
docker run -d --name srs `
-p 1935:1935 -p 1985:1985 -p 8080:8080 -p 8000:8000/udp `
-v D:\myDoubao\video-call-comparison\srs\run\srs.conf:/usr/local/srs/conf/srs.conf `
registry.cn-hangzhou.aliyuncs.com/ossrs/srs:5 `
/usr/local/srs/objs/srs -c /usr/local/srs/conf/srs.conf
run/srs.conf 关键点:http_api 绑定 0.0.0.0:1985、rtc_server 端口 8000/UDP 且 candidate 127.0.0.1。
SRS 官方仓库镜像(1ms /ghcr 源)拉不动,改用阿里云
registry.cn-hangzhou.aliyuncs.com/ossrs/...。版本 v5.0.225。
调试与测试(v5 走 WHIP/WHEP)
SRS v5 的 WebRTC 信令是 WHIP/WHEP(HTTP 协议),正确的单路视频测试:
-
推流(标签页 A) :
http://localhost:8080/players/whip.html?autostart=true -
拉流(标签页 B) :
http://localhost:8080/players/whep.html?autostart=true -
默认推 / 拉同一条流:
webrtc://localhost/live/livestream
这只实现
单向
(A 推、B 看)。
SRS 开箱不提供双向互讲
,群组会议需走 SRS Stack 或自建 WHIP/WHEP 客户端。
踩坑记录
| 问题 | 现象 | 根因 | 解决 |
|---|---|---|---|
| 开会 "没反应" | 自带 room.html 多人会议打不开 | SRS v5 废弃了旧 WebSocket 信令 /sig/v1/rtc(返回 non-101),自带 room.html 用的正是旧协议 |
改走 WHIP/WHEP;或换 SRS Stack |
| 镜像拉不动 | 1ms /ghcr 源超时 | 网络问题 | 换阿里云源 registry.cn-hangzhou.aliyuncs.com/ossrs/srs:5 |
| Stack 裸跑不可用 | 会议场景 | SRS Stack 内部 http_api 绑 127.0.0.1、需 verify 钩子 | 改用 SRS 核心镜像 + 自定义配置 |
四、为什么 localhost 不用 HTTPS
浏览器能否调用摄像头 / 麦克风(getUserMedia)的判断标准是安全上下文(secure context),而非单纯 "必须 https"。
安全上下文包括:
-
https://的页面; -
http://localhost/http://127.0.0.1------ 被浏览器永久豁免,即使协议是 http 也允许调摄像头。
所以:
-
LiveKit 用
http://localhost:3000直接可用(靠 localhost 豁免省掉 https 麻烦); -
Jitsi 默认就配成 https + 自签名证书(所以要点「继续访问」),它也可以配成 http 走 localhost。
注意:一旦部署到别人能访问的域名(非本机),必须上 https,否则远程用户调不了摄像头。
五、三项目对比与结论
| 维度 | LiveKit | Jitsi | SRS |
|---|---|---|---|
| 定位 | 现代 SFU + SDK | 完整开源会议系统 | 流媒体服务器(RTMP/WebRTC) |
| 部署难度 | ★ 低(单容器) | ★★★ 高(4 容器 compose) | ★★ 中(单容器,配置灵活) |
| 开箱即用做双向对讲 | ✅ 是 | ✅ 是(配置正确后) | ⚠️ 否(需自行组装) |
| 前端体验 | 需自己写测试页 | 完整会议 UI | 偏推拉流 demo |
| SDK / 集成 | 极全(多语言) | 提供 iframe 嵌入 | 需自写 WHIP/WHEP 客户端 |
| 本机访问 | http://localhost | https://localhost(自签名) | http://localhost |
| 内存占用 | 低(~15MB) | 较高(~500MB 服务端 + 重前端) | 低(~14MB) |
结论:
-
只想快速跑通、做二次开发 → 选 LiveKit(最省事、SDK 全);
-
想要开箱即用的完整会议功能 (录屏、字幕、白板等)→ 选 Jitsi,但部署最重、吃内存;
-
侧重直播 / 流媒体推送 → 选 SRS ,但不适合开箱即用做视频对讲。
详细对比可视化见 对比可视化.html。
六、停止与清理
# 停止单个服务
docker stop livekit
docker compose -f D:\myDoubao\video-call-comparison\jitsi\docker-jitsi-meet\docker-compose.yml down
docker stop srs
# 停止全部
docker stop livekit srs docker-jitsi-meet-web-1 docker-jitsi-meet-jvb-1 docker-jitsi-meet-jicofo-1 docker-jitsi-meet-prosody-1
# 彻底删除(会删容器,配置文件保留在项目目录)
docker rm -f livekit srs
docker compose -f D:\myDoubao\video-call-comparison\jitsi\docker-jitsi-meet\docker-compose.yml down
想重新完整启动 Jitsi:
cd .../docker-jitsi-meet && docker compose down && docker compose up -d(干净重建,确保各容器正确联网)。
七、常见问题(FAQ)
Q1:开第二个 Jitsi 标签全崩?
A:先确认 JVB 是否注册成功(日志有 Joined MUC: jvbbrewery、无 xmpp.meet.jitsi 解析报错);其次检查系统空闲内存是否过低,测试前关闭占用高的程序。
Q2:LiveKit 报 "could not establish pc connection"?
A:检查启动命令是否带 --node-ip 127.0.0.1,且 UDP 发布端口与配置的 50000--50100 一致。
Q3:SRS 的 room.html/one2one.html 打不开?
A:v5 已废弃旧 WebSocket 信令,请改用 WHIP/WHEP 页面(whip.html / whep.html)。
Q4:能只用两个不同浏览器窗口测吗?
A:可以,同一浏览器两个标签页、或不同浏览器各开一个、或再加一台设备,用同一房间名即可互相看到。