ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

用go2rtc配合Docker实现多摄像头统一接入,告别多套APP

用go2rtc配合Docker实现多摄像头统一接入,告别多套APP 很多玩智能家居、搞监控工程或者自己折腾NAS的朋友应该都遇到过这种尴尬手里好几个摄像头牌子还不一样海康的、大华的、杂牌的接入协议五花八门有的走RTSP有的走RTMP还有的只给你个私有SDK。看个实时画面要么装各自家的APP要么在电脑上装一堆厂商客户端烦得要死。我自己就为这事折腾过好几个晚上直到用上了go2rtc配合Docker一把梭才算是把“摄像头自由”这事儿给彻底办了。这篇文章我就把自己的部署过程、踩过的坑、还有怎么把它跟Home Assistant、VLC这些生态串起来的经验一次性写给兄弟们。1. 为什么选 go2rtc不只是“又一个流媒体网关”先说个前提市面上面向摄像头的流媒体中间件不少像ZoneMinder、Frigate、Scrypted甚至有些NVR方案也能干这活。但在“多协议接入”这块go2rtc确实有它独到的设计思路。1.1 go2rtc 到底解决什么问题简单理解go2rtc是一个用Go语言写的轻量级流媒体网关它不负责录制和AI识别那是NVR和Frigate的活它只专注干一件事把各路来源的流统一成你能方便消费的格式再分发给多方去用。你可以把它当成一个“流媒体翻译官”。摄像头说RTSP浏览器要WebRTC你的手机APP要HLSHome Assistant要MJPEG正常情况你得各写各的拉流代码。有了go2rtc你只需要告诉它“RTSP源在哪”它自己就能搞定协议转换把H.264/H.265视频流和AAC/G.711音频流按需转成WebRTC、HLS、MJPEG、RTMP等格式输出。这玩意儿最吸引我的点有三个极致轻量Go编译的单一二进制文件内存占用几十MB级别哪怕放在树莓派或者软路由这种弱鸡设备上也毫无压力。协议兼容之王它不只是RTSP中转还内置了针对海康、大华等厂商SDK的适配通过ffmpeg调用以及ONVIF协议的自动发现。很多冷门摄像头型号只要支持ONVIFgo2rtc基本能直接识别取流。WebRTC低延迟输出对于本地局域网内的监控预览通过WebRTC协议延迟能压到几百毫秒以内这在操作云台或者人脸识别联动时体验是质的飞跃。1.2 Docker 部署的核心优势go2rtc官方提供了二进制文件直接运行但我还是强烈推荐用Docker方式部署。最直接的原因是**“零依赖”**。go2rtc虽然是个静态编译的二进制但如果你需要用到它内置的FFmpeg转码功能比如把无法直接解析的私有格式转成RTSP或者做H.265转H.264官方镜像里会封装好一个可用的FFmpeg如果你裸装还得自己解决FFmpeg的版本兼容和PATH环境变量问题麻烦。另外Docker的版本管理也舒服。go2rtc更新迭代很快有时候修一个厂商SDK的兼容bug可能一两天就发一个新版本。用Docker镜像我在Portainer或者命令行里换个latest标签docker-compose pull docker-compose up -d一下就升级完了不想用了回滚也方便不会在宿主机上留下一堆乱七八糟的库文件。2. 部署前的准备工作动手敲命令之前先得把账算清楚。虽然Docker部署基本是傻瓜式,但有几个前置条件不准备好后面排查起来会极其痛苦。2.1 硬件选型不是所有设备都能硬解go2rtc本身不挑硬件跑在树莓派3B上也能稳如老狗。但这里有个隐形的大坑WebRTC低延迟播放的“硬件加速”。如果只是局域网内两三个人看画面纯CPU软解也没有任何问题。但你要是接了4路以上1080P的摄像头还想在手机或者平板上通过WebRTC或者HLS看流畅画面建议还是找一台带Intel Quick Sync核显或者NVIDIA GPU的设备。go2rtc的FFmpeg转码模块是支持硬件加速的能大幅降低CPU占用。我自己用的是N100的小主机平时CPU占用率被go2rtc吃掉的可以忽略不计。如果你打算在群晖NAS上跑也得确认下你的NAS是否支持容器化大部分主流都支持了以及硬解相关驱动是否已经加载。2.2 网络规划固定IP是底线摄像头和NVR主机这一层一定要用固定的局域网IP。DHCP分配的IP一旦变了go2rtc配置里的RTSP地址就全失效了画面一断排查会让你崩溃。同时要确保跑go2rtc的这台主机能直接访问摄像头。这听起来像废话但很多人会把摄像头挂在POE交换机上NVR也接同一个POE交换机而go2rtc跑在主路由或另一台服务器上这时候就要看下VLAN隔离的设置了没有路由自然拉不到流。2.3 端口规划go2rtc默认监听1984端口。这个端口用于Web界面和API请求。如果要在公网或者跨VLAN访问记得防火墙放行1984端口。WebRTC牵扯到的UDP端口较广通常默认50000到50100需要同时放行不然会导致能扫码出画面但实际播放黑屏或者要等很久。3. Docker Compose 部署全过程这块我直接给你能“抄作业”的配置省得照着官方文档绕。3.1 编写 docker-compose.yml我用的是docker-compose方式管理比单条docker run更清晰。目录结构大概是~/docker/go2rtc/ ├── docker-compose.yml ├── go2rtc.yaml └── data/docker-compose.yml内容如下亲测可用version: 3.8 services: go2rtc: image: alexxit/go2rtc:latest container_name: go2rtc network_mode: host restart: unless-stopped environment: - TZAsia/Shanghai volumes: - ./go2rtc.yaml:/config/go2rtc.yaml - ./data:/tmp注意几个关键点是**network_mode: host**。这个非常关键go2rtc支持的RTSP、RTSP over TCP、WebRTC等协议需要创建很多动态的UDP和TCP连接端口用桥接模式映射端口会非常痛苦。host模式直接就共享宿主机网络栈了一台设备不需要做NAT映射视频流吞吐性能损耗也最小。data目录挂在容器的/tmp是给snapshot等功能用保存临时截图不是必须的但建议加上。3.2 配置 go2rtc.yaml核心重点这个配置文件是整个平台的心脏格式是YAML。先放我的一份通用配置log: level: info # 调试期间可以改成 debug api: listen: :1984 webrtc: listen: :8555 ice_servers: - urls: [ stun:stun.l.google.com:19302 ] ffmpeg: bin: ffmpeg hardware: vaapi # 如果你的CPU不支持VAAPI可以注释掉或者改成 cuda streams: living_room: - ffmpeg:rtsp://admin:password192.168.1.108:554/h265/ch1/main/av_stream#videocopy#audiocopy bedroom: - rtsp://admin:password192.168.1.109:554/Streaming/Channels/101 doorbell: - onvif://admin:password192.168.1.110配置内容不复杂但每一项都值得细细说下面拆解下。streams 域详解streams就是你要映射的通道。键是你给这个流起的名字值是一个列表表示该流可以通过哪些方式获取。直接RTSP取流bedroom: - rtsp://admin:password192.168.1.109:554/Streaming/Channels/101这是最朴素的方式直接把摄像头的RTSP地址交给go2rtcgo2rtc内部做代理转发。注意这里URL里的特殊字符最好做一下URL编码比如密码中如果有或:可能会解析错位。通过ffmpeg转换取流living_room: - ffmpeg:rtsp://admin:password192.168.1.108:554/h265/ch1/main/av_stream#videocopy#audiocopy很多海康新固件的子码流格式是H.265编码如果你网页端无法直接解H.265可以迁就一下用ffmpeg:前缀让go2rtc去调内置FFmpeg拉流。后面的#videocopy指的是视频编码流不变ch1是主码流这里对着主码流直接copy就行#audiocopy表示音频编码流也不变。这套思路和播放器的硬件解码原理一致降低了延迟也不损失清晰度。如果遇到各种无法直接打开的厂商私有格式也可以直接落这一招。ONVIF自动发现doorbell: - onvif://admin:password192.168.1.110go2rtc对ONVIF支持得不错。只要你摄像头开启了ONVIF协议它就能自动探测出视频流地址不用你去翻厂商文档找RTSP路径。3.3 启动并验证服务配置写好后在docker-compose文件目录下执行docker-compose up -d docker logs -f go2rtc打开浏览器访问http://你的IP:1984如果能看到go2rtc自带的Web界面并且在界面左侧能看到你配置的living_room、bedroom这些通道点击右侧的画面能正常预览恭喜第一步走通了。4. 核心玩法进阶不止是“看个画面”仅仅是能在网页上看摄像头还不至于让我花这么大力气。go2rtc最诱人的地方在于和周边生态的联动。4.1 API 接口与代码对接go2rtc暴露了一套RESTful API操作起来极顺滑。比如获取当前所有流的信息一条curl命令就行curl http://127.0.0.1:1984/api/streams返回结果是JSON格式状态一目了然。真正玩出花的是api/webrtc接口。当你想在自己的前端页面里快速播放摄像头画面时不需要引入一大堆JS SDK直接用WebRTC原生能力去拉go2rtc的流就行。go2rtc官方文档里把这套信的策源地讲得很细。简单说你的网页代码只要从/api/webrtc?srcstream_name获取SDP然后走传统WebRTC握手就能实现亚秒级延迟的播放这体验比HLS的5秒延迟强太多了。4.2 从 VLC 到网页播放VLC拉go2rtc的流也非常方便。在VLC里选择“打开网络串流”填Go2RTC的HTTP接口地址即可http://你的IP:1984/api/webrtc?srcbedroom甚至你还可以使用RTSP模式rtsp://你的IP:8554/bedroom这里的8554端口是go2rtc内置的RTSP服务端口通过rtsp配置项可以修改默认我在配置里没开如果需要备注可以加一行rtsp: 8554。4.3 接入 Home Assistant如果你是Home Assistant玩家go2rtc的集成体验几乎是官方级的。在HA的配置里添加一个camera实体指向go2rtc的流地址即可不需要额外安装怪异的插件。更骚的操作是利用go2rtc的WebRTC组件直接给HA的卡片用。这样你在手机上打开HA面板监控画面几乎是零延迟的。配合人脸识别或者人体传感器响应速度会舒服不少。5. 视频流原理与问题排查做流媒体这行光会配还不算完还是要懂点底层原理否则出了问题就是两眼一抹黑。5.1 推流和拉流模式go2rtc里一条流有几种状态tracks表示已经拿到了的音视频轨。producers当前活动的流生产者。consumers当前正在消费这条流的客户端。它这个设计很巧妙。比如一个RTSP源2个浏览器看通过go2rtc对外只维持一个到摄像头的连接。内部做分发对摄像头友好不会把摄像头连接数打满。5.2 常见问题速查表我踩过的坑还挺典型的顺便整理个表格给大家避雷症状可能原因处理方法网页画面一直转圈黑屏摄像头H.265编码浏览器不支持硬解在WebRTC播放器中勾选“通过FFmpeg转码”或者在流路径中加#videocopy并启动软/硬解转码在go2rtc里可以将视频转成H.264延迟爆炸十几秒以上默认拉的是子码流或RTSP over TCP的缓存问题检查摄像头主码流是否用的H.265/HEVC且清晰度高如果只是看预览配置一条子码流或者切换RTSP transport为UDPWebRTC连接不稳定频繁断开UDP端口未放行或者STUN配置错误确保容器/防火墙放行UDP 50000-50100确保ICE server可以连通公网局域网内建议直接用IP通过FFmpeg转码后CPU占用100%没开硬件加速在ffmpeg模块中配置hardware: vaapi或cuda并确保Docker启动时映射了设备devices:/dev/dri:/dev/dri摄像头的音频和视频画面不同步RTSP协议抓流时的缓存策略导致在go2rtc配置中为流加#audiocopy让音频轨道直接复用源数据不同步情况会改善。如果还不行尝试降低前端的缓冲设置5.3 抓包排查三板斧排查的时候先看go2rtc的日志然后把日志级别调成debug直接看它打印的SDP信息和RTSP状态码很多问题就清楚了。如果涉及摄像头本身的问题可以在宿主机上用ffprobe或者curl直接测试一下摄像头的RTSP地址是否可通。注意不要用ffmpeg去探测过于频繁部分摄像头有连接数限制试探太多会给锁IP。6. 与 Docker 生态的“梦幻联动”go2rtc用处太多了经常和别的服务串起来用比单一功能价值翻倍。6.1 联动 Frigate 做检测Frigate会从go2rtc这里拉流供检测模块使用。你可以直接在Frigate配置里指向go2rtc的流地址这样既可以平时在Web UI看低延迟实时流又能让Frigate随时抓帧做目标识别。好处是Frigate不用自己维护一堆摄像头连接都交给go2rtc去管理。6.2 联动 OBS 推流如果你想在家里搭建一个简单的“家庭直播间”或者做一个“慢直播”页面调用go2rtc的WebRTC接口OBS通过浏览器源拉过来再走自有RTMP推到平台链路非常顺滑。6.3 结合 Node-RED 做自动化Node-RED接onvif或RTSP很酸爽但监控流本身不好在流程里直接处理。用go2rtc做中间层Node-RED只负责API调用(get snapshot)和决策画面表现交给go2rtc分工清晰效率高。7. 最后聊点实在的几点心得折腾了这么久有几点感受特别深。别迷信最新版本稳定版更重要。go2rtc的Dev分支新功能多但偶尔也会冒出来一些breaking change。我生产环境一直固定在某个稳定版本等确认没问题再升级。配置文件写注释是个好习惯。go2rtc的yaml格式比较宽泛但对缩进和特殊符号还是敏感的如果你的密码或者路径里带#或建议用引号包裹起来。其实这玩意儿的Web界面自带一个功能叫snapshot可以实时抓帧这对做监控联动或者生成缩略图非常有用。直接浏览器访问/api/frame?srcstream_name就能返回一张JPEG图毫秒级响应比你自己用ffmpeg去抓要省事太多。希望这篇经验贴能帮兄弟们少走点弯路。流媒体这东西入门容易折腾精难但我们图的不就是那种“一屏看尽所有摄像头”的舒坦劲儿吗。去搞个Docker跑起来试试看吧你会有惊喜的。
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进