Go 用 RTSPtoWeb 实现摄像头 RTSP2Web 显示
之前用原生库搭 RTSP 转 Web 的方案时,光是调 FFmpeg 转码参数、处理切片缓存就踩了不少坑。
后来发现 deepch 开源的 RTSPtoWeb 库——专门为 RTSP 转 Web 场景设计,Go 开发的轻量框架,不用写复杂转码逻辑,配个配置文件就能跑。
今天把这个“方案”记录分享给大家,希望对大家的开发有所帮助。
一、为什么推荐 RTSPtoWeb ?
核心优势:
- 零复杂编码 :不用自己调 FFmpeg API,库内部封装了 RTSP 拉流、转码、协议转换逻辑,配置文件驱动开发;
- 多协议支持 :同时支持转 HLS、WebRTC、WS-FLV 等 Web 友好协议,HLS 兼容所有浏览器,WebRTC 能做到毫秒级延迟;
- 轻量高效 :Go 原生开发,启动快、内存占用低,单服务支持多摄像头并发流转;
- 自带前端 :库内置简易播放页面,调试时不用自己写前端,正式部署可自定义页面。
整体流程比原生方案简洁太多:
配置摄像头 RTSP 地址 → 启动 RTSPtoWeb 服务 → Web 端通过协议链接播放 ,中间的转码、切片全由库搞定。
二、安装使用
本文是基于 go 1.18+ 版本开发,建议大家 go 的版本不要太低
安装 RTSPtoWeb 库
# 1. 克隆源码到本地
git clone https://github.com/deepch/RTSPtoWeb.git
cd RTSPtoWeb
# 2. 编译生成可执行文件
go build -o rtsp2web main.go
# 验证编译(生成 rtsp2web 可执行文件即成功)
ls | grep rtsp2web # 输出 rtsp2web如果不想克隆源码,也可以用
go install直接安装
三、核心配置
RTSPtoWeb 靠配置文件驱动,源码目录里有个默认配置 config.json,我们只需要修改“摄像头流配置”和“服务端口”即可,其他默认参数足够覆盖基础场景。
打开源码目录的 config.json,重点修改以下 3 部分(其他参数保持默认):
{
"server": {
"http": {
"port": ":8080" // Web 服务端口,默认 8080,避免占用可改 8081
}
},
"streams": { // 摄像头流配置,支持多个摄像头(新增键值对即可)
"camera1": { // 流名称,自定义(如 camera_lobby、camera_door)
"url": "rtsp://admin:123456@192.168.1.100:554/stream1", // 摄像头 RTSP 地址
"protocols": [ // 支持转换的 Web 协议,选 1-2 个即可
"hls", // 兼容性最好,所有浏览器支持(延迟 2-5 秒)
"webrtc" // 低延迟,毫秒级(部分旧浏览器不支持)
],
"hls": {
"segment_duration": 2 // HLS 切片时长(秒),越小延迟越低
}
}
}
}为了避免大家被默认配置的冗余参数干扰,我整理了一个简化版配置,直接替换原 config.json 即可用:
{
"server": {
"http": {
"port": ":8080",
"allow_origin": "*" // 允许跨域,前端部署在不同域名时需要
},
"webrtc": {
"port": ":8081" // WebRTC 端口,和 HTTP 端口区分开
}
},
"streams": {
"camera_lobby": { // 大厅摄像头
"url": "rtsp://admin:123456@192.168.1.100:554/stream1",
"protocols": ["hls", "webrtc"],
"hls": {
"segment_duration": 1, // 切片缩为 1 秒,降低延迟
"max_segment_count": 3 // 最多保留 3 个切片,避免磁盘占满
},
"webrtc": {
"ice_servers": [{"urls": ["stun:stun.l.google.com:19302"]}] // WebRTC 穿透配置
}
},
"camera_door": { // 门口摄像头(多摄像头配置示例)
"url": "rtsp://admin:654321@192.168.1.101:554/stream1",
"protocols": ["hls"]
}
}
}
RTSP 地址格式:一般摄像头说明书会写,格式为
rtsp://用户名:密码@摄像头IP:端口/流路径;多摄像头:在
streams里新增键值对(如camera_door)即可;协议选择:只需要兼容所有浏览器选
hls,需要低延迟选webrtc。
四、启动服务 & Web 播放
配置好之后,启动服务和播放都很简单,甚至不用自己写前端(库内置调试页面)。
在源码目录执行以下命令,启动服务(确保配置文件 config.json 在当前目录):
# 启动服务(默认读取当前目录的 config.json)
./rtsp2web -config config.json
# 启动成功会输出类似日志
# 2025/12/20 10:00:00 HTTP server started on :8080
# 2025/12/20 10:00:00 WebRTC server started on :8081
# 2025/12/20 10:00:00 Stream camera_lobby started服务启动后,直接打开浏览器访问 http://服务器IP:8080,就能看到库内置的调试页面,不用写一行前端代码:
-
页面下拉找到“Streams”区域,选择要播放的摄像头(如
camera_lobby); -
选择播放协议(HLS 或 WebRTC),点击“Play”按钮,就能看到实时画面;
-
调试页面还能查看流状态、切换协议,非常方便。
参考图示:
五、自定义播放器
内置页面只适合调试,正式部署需要自定义前端。
这里提供 HLS 和 WebRTC 两种协议的播放代码,直接嵌入自己的页面即可。
HLS 协议播放(兼容性最好)
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>大厅摄像头监控</title>
<style>video { width: 80%; max-width: 1280px; margin: 50px auto; display: block; }</style>
</head>
<body>
<video id="hlsPlayer" controls autoplay muted playsinline>
<source src="http://192.168.1.10:8080/hls/camera_lobby.m3u8" type="application/x-mpegURL">
您的浏览器不支持 HLS 播放,请升级浏览器。
</video>
</body>
</html>WebRTC 协议播放(低延迟)
WebRTC 需要简单的 JS 逻辑建立连接,依赖库内置的信号服务:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>门口摄像头监控(低延迟)</title>
<style>video { width: 80%; max-width: 1280px; margin: 50px auto; display: block; }</style>
</head>
<body>
<video id="webrtcPlayer" autoplay muted playsinline></video>
<script>
// 1. 建立 WebSocket 连接(信号服务)
const ws = new WebSocket('ws://192.168.1.10:8080/webrtc/camera_door');
const video = document.getElementById('webrtcPlayer');
// 2. 接收 WebRTC 配置并播放
ws.onmessage = async (event) => {
const data = JSON.parse(event.data);
if (data.type === 'offer') {
// 创建 RTCPeerConnection
const pc = new RTCPeerConnection({
iceServers: [{ urls: 'stun:stun.l.google.com:19302' }]
});
// 接收视频流
pc.ontrack = (e) => { video.srcObject = e.streams[0]; };
// 响应 offer
await pc.setRemoteDescription(new RTCSessionDescription(data));
const answer = await pc.createAnswer();
await pc.setLocalDescription(answer);
// 发送 answer 给服务端
ws.send(JSON.stringify({ type: 'answer', sdp: pc.localDescription.sdp }));
// 处理 ICE 候选
pc.onicecandidate = (e) => {
if (e.candidate) {
ws.send(JSON.stringify({ type: 'candidate', candidate: e.candidate }));
}
};
} else if (data.type === 'candidate') {
// 添加 ICE 候选
await pc.addIceCandidate(new RTCIceCandidate(data.candidate));
}
};
</script>
</body>
</html>常见问题
Q1. 启动服务报错“invalid RTSP URL”?
问题原因:RTSP 地址格式错误、用户名密码错误,或摄像头未联网。
解决方案:
-
用 FFmpeg 命令验证 RTSP 地址有效性:
ffmpeg -i rtsp://admin:123456@192.168.1.100:554/stream1 -vcodec copy -f mp4 test.mp4,能生成视频文件说明地址正常; -
检查摄像头 IP 是否能 ping 通:
ping 192.168.1.100,不通则检查摄像头网络配置; -
登录摄像头管理后台,确认 RTSP 端口(默认 554)已开放,且“匿名访问”或“用户名密码”正确。
Q2. 浏览器访问 http://IP:8080 打不开?
问题原因:端口被占用,或防火墙拦截。
解决方案:
-
更换端口:修改 config.json 里
server.http.port为:8081,重新启动服务; -
检查端口占用(Linux):
netstat -tulpn | grep 8080,杀死占用进程:kill -9 进程ID; -
开放防火墙端口(Linux):
sudo ufw allow 8080/tcp,Windows 在“防火墙高级设置”里添加端口规则。
Q3. HLS 播放延迟很高(超过 5 秒)?
问题原因:默认切片时长和缓存过多,HLS 天生延迟比 WebRTC 高。
解决方案:
-
缩小切片时长:修改 config.json 里
hls.segment_duration为 1(最小 1 秒); -
减少缓存切片数:添加
"max_segment_count": 2到 hls 配置里,只保留 2 个切片; -
前端添加低延迟属性:
<video id="hlsPlayer" controls autoplay muted playsinline lowlatency>; -
极致低延迟需求:改用 WebRTC 协议,延迟可降到 100-500 毫秒。
Q4. 多摄像头配置后,部分流无法播放?
问题原因:摄像头 RTSP 端口冲突,或服务资源不足。
解决方案:
-
确认每个摄像头的 RTSP 端口不同(部分摄像头默认都是 554,可在管理后台修改);
-
降低单个流的比特率:如果摄像头支持,在管理后台将分辨率从 1080P 降到 720P,减少服务压力;
-
检查服务日志:启动服务时添加日志参数
./rtsp2web -config config.json -log debug,查看具体流的报错信息。
Q5. WebRTC 播放时画面卡顿、频繁断连?
问题原因:网络穿透失败(内网可以播放,外网不行),或带宽不足。
解决方案:
-
优化穿透配置:在 config.json 的 webrtc 里添加多个 STUN/TURN 服务器(推荐用阿里云 TURN 服务,需申请);
-
检查带宽:确保服务器上行带宽 ≥ 每个流比特率 × 摄像头数量(720P 流约 1Mbps,4 个摄像头需 4Mbps 以上);
-
内网测试:先在同一网段的电脑上播放,排除外网穿透问题,再处理公网访问。
总结
RTSPtoWeb 库把复杂的 RTSP 转 Web 逻辑封装得非常好,基础场景下配个 config.json 就能用,比原生开发效率高太多。
实际部署时,可以再做这些优化:
-
权限控制:内置页面只用于调试,正式环境要给 Web 服务加登录验证(如用 Go 的 gin 框架加 JWT 认证)。
-
后台运行:Linux 下用
nohup ./rtsp2web -config config.json &让服务后台运行,日志输出到 nohup.out。 -
容器化部署:源码目录有 Dockerfile,直接打包成 Docker 镜像,避免环境依赖问题。
-
监控告警:用 Prometheus + Grafana 监控服务状态,流断连时通过邮件/短信告警。
如果你的需求是快速实现摄像头 Web 显示,且不想折腾转码逻辑,RTSPtoWeb 绝对是首选。
亲测可用。如果有其他特殊场景,欢迎在评论区交流~
版权声明
未经授权,禁止转载本文章。
如需转载请保留原文链接并注明出处。即视为默认获得授权。
未保留原文链接未注明出处或删除链接将视为侵权,必追究法律责任!