ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Docker部署go2rtc:统一多品牌摄像头视频流的流媒体网关实战

Docker部署go2rtc:统一多品牌摄像头视频流的流媒体网关实战 先说说我为什么折腾这个。家里和工作室加起来七八个摄像头海康、大华、萤石还有几个杂牌每个牌子一个APP想看的时候得挨个打开。有一回半夜手机弹窗说门口有动静我打开对应APP等了快半分钟画面还没出来等人影消失了才看到个尾巴。那之后我就琢磨着搞一个统一平台把多路摄像头都收进去在一个页面里看。试过几套方案最后留在go2rtc上。它是一个用Go写的轻量级流媒体网关核心思路是把不同来源的视频流RTSP、RTMP、本地文件都行统一收进来再按需转成你想要的协议吐出去。配合Docker部署几分钟就能把一套多协议流媒体平台跑起来。这篇文章写给同样被多品牌摄像头折磨的朋友也记录一下我自己踩过的坑。1. go2rtc是什么为什么选它来统一摄像头视频流1.1 从多个APP来回切到一个页面看全部先说痛点。普通人家里装两三个摄像头用原厂APP也还行但一旦数量上来、品牌还不一样问题就来了海康的录像在A APP里大华的报警在B APP里萤石的回放在C APP里想看全貌就得来回切。更麻烦的是想把摄像头接进Home Assistant、Frigate、群晖Surveillance Station这类第三方系统很多平台对单一协议比如RTSP支持得很好但对各家私有协议就束手无策了。go2rtc解决的就是这个中间层问题。它是一个独立运行的流媒体网关服务你不必去改任何摄像头的配置只需要让go2rtc拿到摄像头的RTSP地址它就能统一管理这些视频流并对外提供统一的接入能力。相当于所有摄像头先汇聚到go2rtc这一个节点再由go2rtc按客户端的需求分发出去。这个设计思路和生活里“换一个中控遥控器”差不多摄像机还是各干各的但查看入口只留一个。我实际用下来还有个额外收获排查问题方便了。以前摄像头连不上我得分品牌去找原因现在所有视频流入口都在go2rtc哪一路断了、为什么断一个页面加一行日志就能看到。对于设备多、品牌杂的环境这种“统一入口”本身就是最大的价值。1.2 go2rtc的核心能力与协议生态go2rtc支持的能力比我预期宽不少。它的名字里有WebRTC所以最拿手的就是WebRTC低延迟播放浏览器打开页面直接看延迟能做到几百毫秒级别这在摄像头实时预览场景下非常实用。同时它也兼容RTSP、RTMP、HLS、MJPEG、MP4等多种协议既可以拉流也可以推流还能把一路视频流同时以多种协议输出给不同端。举个例子我在go2rtc里加了一路海康摄像头之后可以同时做三件事电脑浏览器用WebRTC看实时画面延迟基本无感手机用HLS地址在不稳定网络下慢慢缓冲播放兼容性好家里一个小程序直接抓MJPEG截图做门铃提示。这些都基于同一路源流完成不需要为每个场景单独部署一套服务。如果你对延迟不敏感、对兼容性要求高HLS最稳如果要实时看门口来人WebRTC的优势就非常明显。另外要赞一下go2rtc对编码的容忍度。它默认走不转码直接转发的路子只要源端编码在目标播放端能解出来就尽量不额外消耗CPU。H.264、H.265都能通过不同播放链路适配。当然这也带来一个限制某些情况下需要播放端或者摄像头端配合编码格式这点我在第4章会展开聊。1.3 为什么用Docker而不是直接装在主机上直接运行go2rtc也不难官方有编译好的二进制下载下来一条命令就能跑。但我最终选择Docker部署原因有三点。第一安装干净。Go写的程序虽然依赖少但总归要在系统里放二进制、配置、日志时间长了容易弄乱。用Docker容器把程序和数据隔离在固定目录卸载时直接删容器和挂载目录就行不留垃圾。第二升级方便。go2rtc迭代不算慢隔几个月就有新版本。如果用二进制部署每次都要下载、停服务、替换文件出问题还得回滚。用Docker只需要改一下镜像tag重启容器就完事旧版本通过镜像tag保留着随时能切回去。第三迁移友好。我在一台小主机上部署好了配置想迁到另一台机器上直接把 docker-compose.yml 和配置目录复制过去docker compose up -d就完成了。家里也好、工作室也好只要Docker能跑这套部署方式就是一致的。后续如果你想接Home Assistant、Frigate这些同样容器化的服务网络打通也顺理成章。2. Docker部署go2rtc的完整过程2.1 部署前需要想清楚的几件事动手之前先花两分钟确认环境省得后面来回折腾。第一Docker版本。理论上Docker 20.10以上都行我自己是在Ubuntu 22.04上用Docker 24系列部署的跑得很稳。如果还在用老版本Docker建议先升级避免个别镜像特性和compose语法不支持。第二端口规划。go2rtc默认用1984端口提供Web界面和API同时需要UDP 8555端口做WebRTC媒体传输。如果你的服务器、软路由、NAS已经占用了这两个端口要么换端口要么用host网络模式。我建议尽量保持1984和8555不变因为go2rtc很多内置调用、第三方集成比如Home Assistant的go2rtc集成都默认这两个端口改动后还得去各处适配划不来。第三摄像头网段和RTSP账号。go2rtc要能拉到摄像头视频流前提是它和摄像头之间网络互通。如果Docker跑在软路由上而摄像头在另一个VLAN需要在网关上放行相关流量。摄像头端的RTSP用户名密码也要提前准备好后面配置都会用到。我把经常需要确认的信息整理成一张表部署前对照打勾就行项目建议值说明Docker版本20.10太老版本可能不支持部分compose字段Web端口1984/tcpgo2rtc Web界面和API默认端口WebRTC端口8555/udp低延迟播放必须用的UDP端口配置路径/config/go2rtc.yaml容器内默认路径宿主机用挂载覆盖摄像头RTSP提前准备账号密码后面接入摄像头时必填网络模式端口映射优先NAT严格时host兜底不同环境灵活切换2.2 Docker命令行部署演示最简单的跑法一条命令mkdir -p /opt/go2rtc cd /opt/go2rtc touch go2rtc.yaml docker run -d --name go2rtc --restartunless-stopped \ -p 1984:1984 \ -p 8555:8555/udp \ -v /opt/go2rtc/go2rtc.yaml:/config/go2rtc.yaml \ alexxit/go2rtc:latest拆解一下这条命令里每个参数的含义。-p 1984:1984是把容器的1984端口映射到宿主机Web界面和API都走这个端口。-p 8555:8555/udp映射WebRTC需要的UDP端口少了这个你能打开页面但大概率连不上WebRTC实时流。-v /opt/go2rtc/go2rtc.yaml:/config/go2rtc.yaml是挂载配置文件go2rtc在容器里的默认配置路径就是/config/go2rtc.yaml这样配置在宿主机上一份备份、修改都方便。执行完成后用下面的命令确认容器状态docker ps | grep go2rtc docker logs go2rtc日志里如果出现类似server listening on :1984的输出说明服务已经起来了。这时候在浏览器打开http://服务器IP:1984能看到go2rtc的Web界面页面虽然简陋但功能都在左侧是源列表右侧是播放预览。如果你是在群晖、威联通、飞牛这类NAS上部署方法也一样只是挂载路径按NAS的目录结构来填就好。第一次跑起来的时候我在屏幕前愣了几秒因为真没想到会这么顺。浏览器打开就能看到一个可以点击播放的控制台这对一个部署过程来说已经是相当友好的体验了。2.3 用docker-compose管理更省心虽然一条docker run能跑起来但我个人更推荐docker-compose尤其当你后面还要加Frigate、Home Assistant容器时compose可以统一管理。我的compose文件长这样services: go2rtc: image: alexxit/go2rtc:latest container_name: go2rtc restart: unless-stopped ports: - 1984:1984 - 8555:8555/udp volumes: - ./go2rtc.yaml:/config/go2rtc.yaml在/opt/go2rtc目录下保存为docker-compose.yml然后执行docker compose up -d即可。这里有个小细节restart: unless-stopped保证宿主机重启后容器自动拉起。摄像头监控这种事最怕断电后还要手动启动服务我吃过一次亏所以这个参数一定会加。如果你的Docker宿主在NAT后面或者WebRTC一直连不通可以把网络模式改成host再试services: go2rtc: image: alexxit/go2rtc:latest container_name: go2rtc restart: unless-stopped network_mode: host volumes: - ./go2rtc.yaml:/config/go2rtc.yamlhost模式下容器直接共享宿主机网络栈没有端口映射这一层优点是能降低NAT问题的影响缺点是1984和8555必须确认没被占用。普通家庭环境建议先用端口映射方式不行再换host这样最省心。2.4 配置文件怎么写go2rtc的配置是一个典型的YAML文件核心就是streams字段。最简单的配置streams: door: rtsp://admin:password192.168.1.64:554/Streaming/Channels/101 backyard: rtsp://admin:password192.168.1.65:554/cam/realmonitor?channel1subtype0冒号左边是流的名字右边是源地址。名字最好用有意义的英文比如door、backyard、driveway因为后面播放URL、接入Home Assistant时都靠这个名字来引用对应摄像头。你可以直接在Web界面的设置里改配置并保存也可以改了宿主机上挂载的yaml文件后重启容器。我习惯直接编辑宿主机文件因为可以纳入版本管理出问题回滚也快。配置文件里还可以设置日志级别等全局参数默认值基本够用。这里要特别注意一点go2rtc本身没有强制密码保护如果它跑在公网可达的环境强烈建议在前面挂一层反向代理加basic auth别把裸的1984端口直接暴露出去。我见过有人图方便把1984映射到公网结果摄像头画面被陌生地址访问这种教训真的不希望你们再踩一次。3. 摄像头接入与多协议播放实操3.1 摄像头端准备开启RTSP并确认地址go2rtc要拉摄像头视频流最通用的方式就是RTSP协议。绝大多数IPC摄像头海康、大华、萤石、TP-Link、小米部分型号都在后台提供RTSP开关不同品牌位置不太一样但思路相同在摄像头管理页面开启RTSP服务设置一个专门用于取流的账号权限只给视频流然后记下RTSP地址。这里我把几个常见品牌的RTSP地址格式整理成表方便你直接对照配置品牌主码流RTSP地址海康威视rtsp://用户名:密码IP:554/Streaming/Channels/101大华rtsp://用户名:密码IP:554/cam/realmonitor?channel1subtype0萤石rtsp://用户名:密码IP:554/h264/ch1/main/av_streamTP-Linkrtsp://用户名:密码IP:554/stream1需要注意这个地址里的端口如果不写默认是554一般不用加但如果你改过摄像头端口就必须显式写上。海康的101结尾表示通道1主码流102是通道1子码流大华则是subtype0表示主码流subtype1表示子码流。子码流分辨率低、码率小适合预览和多路同看主码流清晰但更吃带宽这个选择在后面的播放流畅度里会直接影响体验。我自己的习惯是预览墙和报警推送用子码流回放和AI识别需要细节时用主码流两个码流都分别在go2rtc里配置好需要时随时切换。3.2 把摄像头接进go2rtc拿到RTSP地址后把它填到go2rtc配置里。比如我在配置里写了streams: front_door: - rtsp://admin:pass192.168.1.64:554/Streaming/Channels/101 - rtsp://admin:pass192.168.1.64:554/Streaming/Channels/102 backyard: - rtsp://admin:pass192.168.1.65:554/cam/realmonitor?channel1subtype1注意我用了列表形式也就是一个流名下可以写多个地址。go2rtc会优先选择链路质量高的那个源如果第一个断了会自动切换第二个。我把海康的主码流和子码流都挂到front_door下面这样默认用主码流预览遇到带宽波动时可以自动切到子码流实际使用中这个机制帮了不少忙。配置保存后重启容器或者直接在go2rtc页面点刷新就能看到对应流开始工作。页面会显示源状态和进程信息。如果配置错误页面上会直接抛异常提示也可以在容器日志里定位问题。我第一次配置时手滑把RTSP地址里的密码多打了一个字符页面提示拉流失败我还怀疑是端口映射有毛病后来看日志才知道是认证失败。所以看到问题先看日志别瞎猜。3.3 多协议输出WebRTC、HLS、MJPEG、MP4go2rtc的核心魅力在于接入一路源流后不仅能在它自己的页面看还能按需输出多种协议给不同客户端。以我的经验最常用的四个输出形态如下WebRTC是首选在go2rtc页面点击播放默认就是用WebRTC传输延迟极低局域网内基本感觉不到延迟适合实时看门口、看孩子房间。HLS是兜底方案把流切成一小段一小段通过HTTP提供兼容性最好任何浏览器、播放器都能播代价是延迟会高几秒。MJPEG适合需要“静态图”的场景比如做门铃预览、嵌套到网页仪表盘。MP4适合临时录制点个链接就能下载当前时间段片段应急取证很好用。这些输出对应的URL我整理如下WebRTC直接在 go2rtc 页面打开或者用支持WebRTC的播放器 HLS http://IP:1984/api/stream.m3u8?srcfront_door MJPEGhttp://IP:1984/api/frame.jpg?srcfront_door MP4 http://IP:1984/api/stream.mp4?srcfront_door其中src参数指的就是你配置的流名。这几个URL可以直接填到支持相应协议的播放器、Home Assistant卡片、网页代码里。比如我给家里的智能家居仪表盘嵌入了一张MJPEG的门口画面加载速度和稳定性都远超原厂APP的小窗口。实际测试下来局域网内一路MJPEG请求占用带宽不高动态画面下也能稳定刷新嵌入网页最合适。3.4 在手机、电视和第三方系统里播放手机上最省事的办法是直接用浏览器打开http://IP:1984go2rtc页面做了移动端适配点开就能看。如果嫌Web界面不够用也可以用支持WebRTC的App配合URL拉流。电视端的思路类似通过支持HLS的播放器或者浏览器访问HLS地址就行。更进阶的玩法是把go2rtc接入第三方系统。Home Assistant和go2rtc关系非常紧密官方集成直接支持go2rtc填一下go2rtc地址就能把配置的所有流暴露为摄像头实体。Frigate这个NVR方案也支持把go2rtc作为源再接进来我后面会再展开讲。这里先给个结论只要go2rtc里能流畅看到流基本就等于所有主流系统都能用上这路视频流了。用VLC这类本地播放器也能直接拉流。在VLC里打开网络串流输入http://IP:1984/api/stream.m3u8?srcfront_door就能在电脑上把go2rtc管的所有摄像头当成普通电视直播一样看。这个调试技巧很实用排查播放问题时比浏览器环境少很多干扰。4. 常见问题与排查技巧实录4.1 流一直转圈拉不出来这是新手碰到最多的问题。现象是go2rtc页面能看到流但点开播放一直转圈。排查路径按优先级排下来第一步看日志。执行docker logs go2rtc重点看有没有rtsp、auth、timeout这几个关键词。如果是401或认证失败说明RTSP地址里的用户名或密码不对去摄像头后台确认一下。如果是连接超时说明网络不通先ping摄像头IP再确认Docker宿主和摄像头是不是同一网段。第二步看摄像头并发限制。有些家用摄像头支持的路数有限如果你同时让原厂APP、go2rtc、另外一个NVR都在拉同一路流可能触发摄像头侧的资源限制。我遇到过一台摄像头最多允许两路RTSP并发第三路就会拒绝连接表现在go2rtc这里就是反复重连。解决方法是关掉原厂APP的实时预览或者减少接入的端数。第三步看摄像头编码类型。新版摄像头常默认H.265如果播放端不支持画面就是黑的或者一直不出流。这个通常不是拉流失败而是解码失败这类问题我在4.3节专门讲。4.2 画面卡顿与延迟优化画面卡、延迟高要先分清是“源端拉不动”还是“分发端扛不住”。如果只是单路就卡基本可以认为是摄像头到go2rtc这段带宽或摄像头性能不够。这时我建议把源地址换成子码流海康把101改成102大华把subtype0改成subtype1。子码流分辨率低码率小局域网内非常流畅代价是细节少一些。如果多路同时卡就要考虑Docker宿主性能了。go2rtc的设计是尽量不转码、直接转发所以CPU占用一般不高但宿主内存太低或磁盘IO很慢时多路并发还是有压力。再一个是网络我的经验是摄像头尽量走有线的POE交换机不要靠Wi-Fi承载多路主码流2.4G频段干扰大丢包率上去了画面就花。延迟方面WebRTC延迟低但前提是UDP 8555端口通。如果网络环境NAT很严、UDP打洞失败go2rtc会退化成TCP中继延迟会飙升。局域网内一般没事跨网络访问时才明显。想降低延迟可以检查宿主机的8555/udp端口是否映射正常或直接改用host网络模式。4.3 浏览器黑屏与编码问题接入后发现go2rtc页面能出界面但画面黑屏、只有声音或者干脆没画面多数情况和H.265编码有关。Chrome、Firefox这类浏览器对H.265的支持时好时坏尤其是不支持的平台黑屏是很正常的。Safari稍微好一点但也不能保证所有H.265都能播。我的建议很朴实在摄像头后台把视频编码从H.265改成H.264。很多家用摄像头可以选择H.264/H.265或者主码流H.265、子码流H.264。go2rtc的优势是不转码直接转发所以尽量在源端把格式统一成H.264后端所有播放端就省心了。如果你确实需要H.265又要在非Safari浏览器播放那得引入转码方案这就不是go2rtc的强项了建议用带硬件转码的服务配合。还有一类黑屏是分辨率或帧率导致浏览器解码压力大比如500万像素主码流在低配电脑上WebRTC解码吃力。这种情况回退到子码流基本能解决别指望浏览器在监控场景里做超高画质解码。4.4 WebRTC打洞失败与访问不了WebRTC连接失败的症状是页面能加载、画面白屏、日志里出现ICE、STUN相关报错。这通常是因为UDP端口没有放通。如果你用的是端口映射方式检查是不是漏了8555:8555/udp这一条只映射TCP 1984是不够的。如果已经映射还不行建议换成host网络模式省去NAT映射这一层很多跨网段访问问题会迎刃而解。如果你需要从外网访问go2rtc做远程监控我建议不要直接暴露1984端口而是用Caddy、Nginx之类的反向代理加HTTPS和基础认证。反向代理把WebRTC涉及的UDP转发处理好相对麻烦所以远程实时流我一般直接改用HLS或者干脆配合Home Assistant/Frigate来访问避免被WebRTC的NAT问题反复折磨。记住一个原则局域网追求低延迟用WebRTC跨网络求稳用HLS。4.5 Docker容器资源占用与异常恢复go2rtc本身很轻量部署后空闲时内存占用通常只有几十MBCPU几乎为0。但如果你发现容器CPU持续飙高先检查是不是有人在持续拉HLS流或者转码任务被触发。还有容器日志太大也会慢慢吃磁盘我习惯在docker-compose里加上日志轮转限制logging: driver: json-file options: max-size: 10m max-file: 3这样日志最多30MB左右不会被海量重连日志撑爆磁盘。镜像升级也很重要建议定期执行docker compose pull docker compose up -d保持go2rtc版本较新因为摄像头和浏览器生态都在变新版本对WebRTC兼容性和流切换稳定性都有改进。真正遇到容器挂了怎么办因为设置了restart: unless-stopped绝大多数崩溃会自动拉起。如果起不来先看docker logs最后几行报错常见的是挂载路径权限问题或yaml格式错误。yaml格式错误最常见的是缩进不对go2rtc对缩进敏感我踩过一次坑在流名下面忘记缩进结果服务直接拒绝启动。改好配置后重新docker compose up -d即可容器级的隔离让回滚非常快。现象最常见原因优先处理方式播放一直转圈RTSP地址认证失败或网络不通看日志ping摄像头IP画面卡顿主码流带宽压力大切换子码流检查Wi-Fi信号黑屏H.265编码不兼容摄像头端改为H.264WebRTC白屏UDP 8555端口不通检查端口映射或host模式容器异常重启配置格式错误或权限问题看日志修正yaml缩进5. 更多玩法与个人使用体会5.1 把go2rtc接入Frigate做AI识别go2rtc是Frigate官方推荐的好搭档。Frigate是一个开源的NVR/AI摄像头识别方案可以对视频流做人形、车辆、宠物检测。直接在Frigate的配置里把go2rtc的流地址指过去Frigate就能拿到实时流做推理而预览界面还能借助go2rtc的WebRTC低延迟播放比传统的MJPEG预览流畅太多。我的使用方式是这样的go2rtc统一管理家里所有摄像头Frigate通过go2rtc拉取主码流做检测和录像Home Assistant负责报警推送。整个链路里go2rtc只做流量调度不负责录像也不负责AI职责单一出了问题也容易定位。如果你对NVR录像有兴趣还可以让Frigate把录像写到NAS上那是另一套部署方案但基础就是先把go2rtc这层打通。5.2 多路画面同时看的进阶实践go2rtc页面默认可以单独点开每一路流但如果你想一屏看四路、九路原生界面比较朴素。我的做法是在浏览器里同时开多个iframe每个iframe指向go2rtc的不同HLS或WebRTC播放地址拼成一个简单的监控墙。你也可以用Home Assistant的Picture Glance卡片或者自己写一个带Grid布局的小网页原理都是引用go2rtc的输出URL。如果某一刻对低延迟要求特别高比如正在等快递、要看门口的人走到哪了我会单独用WebRTC全屏看这一路延迟低到几乎和摄像头本身的画面同步这在原厂APP里很难做到。反正gog2rtc把协议转换这层抽象掉了你只需要关心“用哪个协议去消费这个流”剩下的它来操心。5.3 最后分享几个我的使用心得这套系统我实际用了大半年从最初的一台Docker加三路摄像头到现在家里工作室统共九个摄像头都挂在上面整体稳定性让我比较满意。最明显的感受是统一入口带来的便利远大于部署时的一点折腾成本。现在我想看任何一路摄像头打开同一个页面就能解决不用再记哪个牌子用哪个APP。踩过的坑也值回票价我总结三条送给你。第一摄像头端尽量统一编码为H.264能省掉后续一大半播放兼容性问题。第二Docker容器要舍得给稳定网络我用的是有线POE和一台小主机专门跑比最初放在Wi-Fi路由器上稳多了。第三go2rtc配置文件的备份要纳入日常习惯我把它放到NAS同步目录里一次配置多台设备迁移都不用愁。如果你也想改善家里或者公司的摄像头查看体验这套Docker加go2rtc的方案值得一试。
返回列表