用 go2rtc 流媒体网关接入 UniFi Protect:把私有摄像头流转成标准 RTSP 流,5 分钟走通
【免费下载链接】go2rtcUltimate camera streaming application项目地址: https://gitcode.com/GitHub_Trending/go/go2rtc
读完这篇,你能在自己的 Synology NAS 上跑起一个 go2rtc 流媒体网关,把 UniFi Protect 摄像头的私有 RTSPS 流变成任何播放器、任何智能家系统都能直接消费的标准 RTSP / WebRTC / HLS 流。go2rtc 是一个用 Go 写的轻量流媒体转换应用,核心能力就一句话:从几十种私有协议"进货",转成所有主流格式"出货",且很多协议下是零转码、接近零延迟的转发。
这个场景适合谁
- 适合:装了 UniFi Protect(或其他只给私有流地址的摄像头品牌),想把录像接到 Frigate、Home Assistant、VLC 或 NAS 回放里的人。
- 适合:NAS 常开、想给全家/多系统共享同一路视频,又不想在每台设备上单独折腾私有 SDK 的人。
- 不适合:只需要浏览器里看看画面、且摄像头已提供标准 RTSP 地址的人——VLC 直连摄像头即可,不用中间加一层网关。
动手前自检清单
- Synology NAS 已装好 Container Manager(DSM 7.2 起的新名字,就是群晖的 Docker)。SSH 能登录,方便跑一条
docker命令。 - UniFi Protect 摄像头已接入 NVR,并能拿到它的 RTSPS 地址和 token。30 秒确认:在 Protect 控制台对摄像头点 Details → Stream,复制出
rtsps://...地址。 - 端口空闲:1984(WebUI/HTTP API)、8554(RTSP 服务端口)、8555(WebRTC 端口,TCP+UDP)。30 秒确认:
docker ps里没看到已占这些端口的容器即可。 - 接受用 host 网络模式:WebRTC 和 UDP 摄像头流量在容器网桥下经常通不了,官方 Docker 文档也是直接推荐
network_mode: host,NAS 上跑一个专用容器影响不大。
部署实操
1. 拉取镜像。群晖 Container Manager 里搜alexxit/go2rtc拉最新版,或者 SSH 里执行docker pull alexxit/go2rtc。这个镜像已内置 FFmpeg 和 Python,后续想加转码源不用再装任何东西。
2. 创建容器。GUI 建容器对 host 网络模式支持得比较别扭,直接 SSH 跑这一条最稳:
# 宿主机 ~/go2rtc 映射进容器 /config,配置文件 go2rtc.yaml 就住这里 docker run -d --name go2rtc \ --network host \ --restart unless-stopped \ -v ~/go2rtc:/config \ alexxit/go2rtc--network host让容器直接用 NAS 的 IP 和端口,后面所有访问地址都按 NAS 的 IP 来写。
3. 打开 WebUI。浏览器访问http://NAS_IP:1984,能看到 add / config / log / net 四个标签页就算活了。以后改配置全部在这个页面上做,点 Save & Restart 会自动重启容器并加载新配置(所以第 2 步加了--restart unless-stopped)。
核心配置:streams 到底怎么写
所有配置都在 WebUI 的 config 页编辑,本质是编辑容器里/config/go2rtc.yaml这一个文件。对你这个场景,真正要动的只有一个配置项:
streams→ 它管什么:整个应用"认识"哪些流。流的名字(camera1这种)是唯一的调用句柄,后面所有播放链接、API 都靠它寻址。建议怎么填:
streams: camera1: # 摄像头原始 RTSPS 地址,token 换成 Protect 给的那串 - rtsps://NAS_IP:7441/xxxxxxxxxxxx?enableSrtp几个容易踩的底层逻辑,别跳过:
- 名字不能和摄像头品牌绑死。
camera1可以叫front-door,但一旦在别的系统里引用了,改名等于断链。 rtsps://加?enableSrtp是在告诉客户端"握手时启用 SRTP 加密",Protect 的流地址通常长这样;如果直连报证书错误,优先先试试不带rtsps的明文rtsp://地址(很多 Protect 部署两者都开)。- 一个流名可以写多个源(list 形式),系统怎么选?这是最常被问的底层逻辑:go2rtc 不是"挑一个能用的源",而是把每个源都当一路生产者同时维护,播放端(浏览器/客户端)连上来时,按客户端支持的能力跨源协商出一套最合适的编码组合——比如 RTSP 源出 H.264+AAC,你再加一个
ffmpeg:转码源出 Opus 音频,浏览器要的音轨自动从转码源拿,视频仍走零延迟的 RTSP 源。某个源掉线时它会按退避策略自动重连,恢复后无感切回,视频不断。所以"写多个"不是备胎机制,是多源编码协商,是 go2rtc 的核心特性,详见 README 的 Codecs negotiation 一节。 - 输出侧给什么由源决定。RTSP 端口能提供的编码=源里已有的编码,查询参数(如
?mp4、?video=h264&audio=aac)只是从已有编码里挑,挑不出就得加 FFmpeg 源来造编码,见 FFmpeg 模块文档。
一键验证流是否通
三种方式,由快到慢:
- 浏览器打开
http://NAS_IP:1984/,add 标签页会列出camera1,点进去用 WebRTC 播放器看画面——延迟最低,能听到声音说明音频也通了。 - 播放器直接开
rtsp://NAS_IP:8554/camera1。VLC 记得把偏好里的缓存级别调到最低,否则默认缓冲会让你误以为延迟高。 - 想给 Frigate/Home Assistant 用的话,拿
http://NAS_IP:1984/api/stream.m3u8?src=camera1(HLS)或http://NAS_IP:1984/api/stream.mp4?src=camera1&mp4(MP4 渐进流)测试。
另外 net 标签页是排障神器:所有连接、走的协议、传的编码、字节数都画在一张图上,一眼看出卡在哪一段。
高频坑速查表
| 现象 | 大概率原因 | 一行解法 |
|---|---|---|
播放器报stream not found | 访问用的流名和 config 里的 key 不一致,或改完没点 Save & Restart | 对照 config 页的 key 原样复制;保存后看容器日志确认重启 |
| RTSPS 握手报证书错误 | 自签证书/SRTP 协商失败 | 换明文rtsp://地址,或确认地址带?enableSrtp |
| 画面有但延迟大(秒级) | 走了 HLS/RTSP 且播放器缓冲高 | 播放端换 WebRTC 模式;ffplay 加-fflags nobuffer -flags low_delay |
| 401/403 拒绝 | Protect 的 token 过期(token 是有有效期的) | 回 Protect 重新生成流地址,替换 config 里的源 |
再往深走一步
- 硬件转码:NAS 有 Intel 核显或想上 GPU 转码,换
alexxit/go2rtc:latest-hardware镜像,版本说明在 Docker 文档。 - 接入 Home Assistant / 写自定义页面:看 HTTP API 文档 和 OpenAPI 描述。
- 多源编码协商的完整规则:README 的 Codecs 章节 和 流处理模块源码。
到这里,你已经有了一个标准 RTSP 端点rtsp://NAS_IP:8554/camera1——任何系统、任何播放器,对着这一个地址拿画面即可。
【免费下载链接】go2rtcUltimate camera streaming application项目地址: https://gitcode.com/GitHub_Trending/go/go2rtc
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考