ARTICLE DETAIL

资讯详情

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

基于Docker部署go2rtc:统一接入RTSP/WebRTC,解决多品牌摄像头监控难题

基于Docker部署go2rtc:统一接入RTSP/WebRTC,解决多品牌摄像头监控难题 如果你家里同时有三四个品牌的摄像头你会发现最麻烦的不是安装而是把它们统一到同一个平台里看。我前阵子折腾了一套基于 Docker 的 go2rtc 流媒体服务专门解决摄像头多协议接入的问题——RTSP、RTMP、HLS、WebRTC 全部打通摄像头这边只管推流浏览器那边想用什么协议看都行。go2rtc 不是传统意义上的 NVR它更像一个流媒体中枢上游接各种来源下游按需输出不同协议。这套方案对家里零散布局的海康、大华、小米类网络摄像头或者对 OBS、手机推流这类临时流源特别友好。适合谁用如果你手头有摄像头想接入 Home Assistant或者想省掉多套平台分别拉流带来的带宽浪费又不太想为一个功能单独买台 NVR那这篇文章能帮你少走不少弯路。1. 为什么最终选了go2rtc从摄像头品牌乱局说起很多人的家庭监控系统是一台摄像头送一个App这么攒出来的。客厅一个海康门口一个大华阳台又挂了一个带云台的杂牌每个都有自己的客户端、自己的账号体系。到了想统一看、想统一录像的时候问题就全冒出来了。1.1 摄像头接入的三大痛点第一个痛点就是协议不统一。海康、大华这类专业安防摄像头好歹还提供标准的 RTSP 地址但地址格式各家还不一样小米、萤石这类面向家庭的摄像头很多干脆不给你 RTSP只给你一个私有云接口树莓派摄像头模组、ESP32-CAM 这类自制设备又是另一种玩法要么走 V4L2要么走 MJPEG over HTTP。想把它们塞进同一个平台等于同时跟五六种协议打架。第二个痛点是带宽的重复浪费。如果没有统一网关而你又想同时让手机、电视、Home Assistant 三处看同一路画面最笨的办法就是三个客户端各自去连摄像头。对家用 WiFi 摄像头来说这种多路直连很容易把无线带宽吃满画面卡顿是小事严重时摄像头会直接掉线。注意很多家用摄像头本身只允许一个或两个并发 RTSP 会话第三个客户端会被踢掉或者被拒绝。第三个痛点是低延迟方案不好选。HLS 协议兼容性确实好但延迟通常在 3 到 10 秒WebRTC 延迟能做到几百毫秒可是搭建 WebRTC 服务又太复杂。普通用户想要打开网页就看到门外的实时画面在 go2rtc 出现之前往往得靠 FFmpeg 转码插件硬撑CPU 占用高不说配置起来也一套一套的。1.2 它和FFmpeg、mediamtx、NVR方案有什么不一样先说结论go2rtc 的核心价值是统一接入 按需输出它不转码只做协议和封装格式之间的搬运。下面这张对比表应该能让你一眼看清楚它和常见替代方案的位置。方案是否转码多协议输出配置难度与 Home Assistant 整合适合场景FFmpeg 脚本是需要自己搭输出链路高弱临时转码任务mediamtx原 rtsp-simple-server否支持 RTSP/RTMP/HLS/WebRTC中一般通用流媒体服务器成品 NVR群晖 Surveillance Station 等通常可以协议依赖厂商中高看品牌追求录像管理的用户go2rtc否RTSP/RTMP/HLS/WebRTC/MJPEG/MP4低强多品牌摄像头统一接入、实时低延迟查看为什么最终选 go2rtc 而不是 mediamtx两个我都在 Docker 里跑过一轮。mediamtx 更偏向传统流媒体服务器它的逻辑是先定义好输入输出端口等客户端来拉go2rtc 则更像一个会话管理器同一个上游摄像头只保持一路拉流下游不管有多少个客户端、用什么协议都从这一路分发。这个一次拉流、多处复用的机制在摄像头接入场景里太关键了。另外go2rtc 对 ONVIF 摄像头有主动发现能力能给不支持 RTSP 协议的摄像头自动拼接出可用的流地址这正好打中家用安防品牌杂、配置乱的痛点。后面我会专门演示。2. go2rtc的多协议机制不是转码而是拆包重封很多人第一次用 go2rtc 会下意识把它当成 FFmpeg 的替代品其实完全不是一回事。它不做视频转码H.264 进来还是 H.264 出去CPU 占用极低。它的核心工作是协议转换和会话复用。2.1 一次拉流多方使用的会话模型打个比方摄像头是冰箱里的食材go2rtc 是配菜师傅但师傅不做菜只是把食材按客人要求切成不同形状端出去。RTSP 的客人要整块原材料HLS 的客人要切成片WebRTC 的客人要切成丁——食材还是那块食材只是摆盘方式不同。实际运行中go2rtc 对每个定义的 stream 只维护一条上游连接。你家大门口的海康摄像头无论同时有手机 App、浏览器网页、Home Assistant 三个客户端在看go2rtc 都只从摄像头拉一路 RTSP 流然后在内存里分发。摄像头侧永远只看到一个会话不会因为被过多客户端轮流请求而拥塞。这一点对稳定性影响非常大。我实测过不带 go2rtc 的时候用群晖的 Survalance Station 和手机 App 同时看同一路海康摄像机偶尔会报会话数超限接上 go2rtc 之后这个报错再没出现过。2.2 各协议适配什么场景go2rtc 对外输出的协议很多但每个协议都有它自己的脾气选错了体验差很多。下面是我实际使用中的经验值。输出协议延迟表现浏览器兼容最佳使用场景WebRTC200ms 左右现代浏览器直接支持低延迟实时看护MSEMedia Source Extensions0.5 到 1 秒Chrome、Edge、Safari 大部分支持网页实时播放HLS3 到 10 秒几乎所有浏览器兼容性兜底、跨网络分享MJPEG0.5 到 2 秒几乎所有浏览器简单预览、嵌入式看板MP4 文件流实时但延迟偏高播放器友好回放、录制文件在你自己的环境里建议默认用 WebRTC 或 MSE 看实时画面HLS 留给局域网外分享或对延迟不敏感的场景。2.3 配置文件的整体形态streams 段与 server 段go2rtc 的配置逻辑很直白一个 YAML 文件就搞定。它主要分两部分前半段定义我对外提供哪些服务端口RTSP Server、RTMP Server、WebRTC 等后半段定义我有哪些流streams。rtsp: listen: :8554 rtmp: listen: :1935 webrtc: listen: :8555 streams: cam_living: - rtsp://admin:password192.168.1.64:554/Streaming/Channels/101这里streams下的每个键就是一个流名。cam_living指客厅摄像头它对应的值是一个列表你甚至可以给同一个流配置多个来源做故障切换——第一个源不可用时自动切到第二个。这个机制在监控重要点位时很实用。注意如果不需要对外提供 RTSP Server 或 RTMP Server这两个段可以不写go2rtc 默认只启动 Web 界面和拉流功能。但后面我们要用 FFmpeg 录像、其他地方拉流所以建议一开始就把这三个监听段都配上。3. Docker部署全流程从拉取镜像到浏览器里看见第一路画面部署 go2rtc 的方法不止一种可以直接跑二进制也可以在 Docker 里跑。我推荐 Docker不是因为二进制不好而是因为容器化之后配置目录、日志、升级都干净尤其是后面折腾坏了可以直接重建不污染宿主机。3.1 部署前检查什么先确认两件事宿主机装了 Docker且版本不算太老。直接在终端跑docker --version看一眼即可旧版本对network_mode、volumes这类语法支持不完整容易出怪问题。然后是端口规划。go2rtc 本身至少占用 1984 端口作为 Web 管理界面如果你按上面的配置开启了 RTSP、RTMP、WebRTC 额外功能还会占用 8554、1935、8555。记住8555 这类的 WebRTC 端口既有 TCP 也有 UDP防火墙和 Docker 端口映射要同时放开。如果你用的是 Linux 服务器最省事的做法是network_mode: host容器直接共享宿主机网络既没有 NAT 性能损耗也不用手动映射一堆端口。但在 Windows 和 macOS 的 Docker Desktop 上host 网络模式支持有限就得退回 bridge 模式并逐个映射端口。3.2 docker-compose 配置逐段解读我用 docker-compose 管理配置文件如下services: go2rtc: image: alexxit/go2rtc:latest container_name: go2rtc restart: unless-stopped network_mode: host environment: - TZAsia/Shanghai volumes: - ./config:/config这段配置有几个关键点。alexxit/go2rtc:latest是官方镜像架构上支持 amd64、arm64 和 armv7树莓派之类的小主机也能直接跑。network_mode: host让 go2rtc 直接使用宿主机网络这样从容器访问局域网摄像头的 RTSP 地址时路由和防火墙规则最简单WebRTC 的 UDP 报文也能顺利回传。./config:/config把当前目录下的 config 目录挂载成容器内的/configgo2rtc 默认会在这个位置读取 go2rtc.yaml。记得先建好目录并放置配置文件mkdir config vi config/go2rtc.yaml如果你是 Docker Desktop 的 bridge 模式不推荐使用 host 网络的需要把上一段改成ports: - 1984:1984/tcp - 8554:8554/tcp - 1935:1935/tcp - 8555:8555/tcp - 8555:8555/udp注意最后一行 UDP 很容易漏少了它 WebRTC 会在建立连接时卡住。3.3 首次访问 Web UI 与验证启动完成后docker compose up -d docker logs -f go2rtc看到日志里出现监听 1984 的提示基本就成功了。浏览器访问http://你的主机IP:1984会看到一个简洁的 Web 控制台。界面左侧是流列表右侧是实时预览。这里可以先不急着接摄像头我们看到的是 go2rtc 的整体状态。验证部署是否正常最直接的方式是添加一条本地测试流。比如配置里加一个名为test的流单独用公开的 RTSP 测试源来验证链路但这类公共源地址时效性太强我实际更推荐用下一节的方法用 OBS 推一路 RTMP 进来验证完全自给自足。4. 三种摄像头接入场景RTSP、RTMP推流、ONVIF自动发现go2rtc 真正让我觉得值得写篇文章记录的是它接入不同源时几乎不用改架构YAML 里加一行就行。下面三种场景覆盖了我能想到的绝大多数家庭和工作室用法。4.1 海康大华RTSP直接抄配置海康威视和大华是家用、小型门店里最常见的两个品牌。它们的 RTSP 地址格式有固定套路不用去摄像头发掘流地址页面也能写。海康威视主码流通用格式streams: cam_living: - rtsp://admin:你的密码192.168.1.64:554/Streaming/Channels/101末尾的101表示 1 通道主码流102是同一通道的子码流子码流分辨率低适合网络差或预览场景。大华主码流格式稍有不同streams: cam_front: - rtsp://admin:你的密码192.168.1.66:554/cam/realmonitor?channel1subtype0这里subtype0是主码流subtype1是子码流。注意地址里带了符号YAML 里最好用引号包起来否则解析会有歧义。填进配置后重启 go2rtc在 Web UI 里点击cam_living选择 WebRTC 或 MSE 模式能看到画面就说明接入成功。如果画面一直转圈优先确认摄像头侧是否允许 RTSP 协议访问海康和大华默认都是开启的但有些固件更新后会默认关闭需要在摄像头后台手动打开。4.2 OBS/手机RTMP推流RTMP 在直播行业里还有大量存量设备OBS 推流、部分手机直播 App 都原生支持。go2rtc 的 RTMP Server 可以接收这些推送统一转成其他协议这相当于把 go2rtc 变成了一个小型直播平台。配置同样很简单rtmp: listen: :1935 streams: live_obs: - rtmp://localhost/live/obs这里rtmp://localhost/live/obs是一个虚拟的拉流地址它告诉 go2rtc当有人推流到本机 1935 端口的/live/obs路径时就把内容命名为live_obs这个流。推流端设置OBS 里选择自定义服务服务器填rtmp://你的主机IP:1935/live推流码填obs。点击开始推流回到 go2rtc Web UI点开live_obs就能看到 OBS 画面了。这个玩法在工作室场景里特别香。比如用一台笔记本做摄像头推流 OBS 画面go2rtc 负责把 RTMP 分成 HLS 和 WebRTC 两种输出一个给剪辑同事做监看一个给客户做低延迟预览互不干扰。4.3 ONVIF发现与本地文件/测试流ONVIF 是安防设备的通用协议标准go2rtc 支持直接用 ONVIF 方式接入摄像头省去手动查 RTSP 地址的麻烦。以某些不支持标准 RTSP 的云摄像头为例streams: cam_unknown: - onvif://admin:你的密码192.168.1.88go2rtc 会通过 ONVIF 探测设备支持的媒体流并自动构造出可用的拉流地址。如果你的摄像头后台能看到 ONVIF 选项但找不到 RTSP 播放地址试试这种写法成功率很高。本地文件同样可以作为流源。比如放一个演示视频在挂载目录里streams: demo: - file:///media/demo.mp4这种情况下 go2rtc 会把这个文件伪装成一个实时流输出方便在没有摄像头的时候测试整条链路。5. 进阶玩法WebRTC低延迟、Home Assistant联动与FFmpeg录像跑通基础接入后go2rtc 的价值才刚开始体现。低延迟、联动、录像这三件事是我觉得最值得投入时间折腾的。5.1 WebRTC把延迟压到毫秒级局域网内WebRTC 的延迟能做到 200ms 上下这个表现已经很接近本地监控了。要实现它只需要确保配置里有 WebRTC 监听段webrtc: listen: :8555如果你的 go2rtc 通过 Docker 跑在内网且使用 host 网络那 WebRTC 的 UDP 回传一般能自动打通。浏览器打开 Web UI 后在播放模式里选择 WebRTC 即可。延迟体感上是画面和现实几乎同步。注意如果想把 WebRTC 暴露到公网事情就没这么简单了。WebRTC 需要候选地址candidates能被对端访问家用路由器要配置端口映射、还可能涉及公网 IP 或较复杂的 NAT 穿透。我的建议是公网场景尽量用 HLS 或 MP4别跟 WebRTC 死磕。5.2 Home Assistant联动go2rtc 在智能家居圈子里这么火很大程度上是因为 Home Assistant简称 HA的摄像头卡片可以基于它实现超低延迟。HA 里通过 HACS 安装的 go2rtc 集成可以把摄像头流统一交给 go2rtc 管理然后在 Lovelace 界面用卡片播放 WebRTC 画面。如果你不想走 HACS 插件用 HA 自带的通用摄像头平台也能接入camera: - platform: generic name: 客厅摄像头 still_image_url: http://192.168.1.2:1984/api/frame.jpeg?srccam_living stream_source: rtsp://192.168.1.2:8554/cam_living第一行still_image_url是从 go2rtc 拉取一帧 JPEG 作为缩略图而stream_source指向 go2rtc 的输出 RTSP 地址这样 HA 里点开能看到实时画面平时网格卡片上又不至于一直开着视频流浪费资源。5.3 用FFmpeg按需录像go2rtc 本身专注转发录像我习惯交给 FFmpeg 按需拉流完成。例如要对cam_living做 60 秒一分段的全天录像可以直接起一个独立容器docker run -d --name recorder \ --network host \ -v /absolute/path/to/recordings:/recordings \ mwader/static-ffmpeg:latest \ -rtsp_transport tcp \ -i rtsp://127.0.0.1:8554/cam_living \ -c copy -f segment -segment_time 60 -strftime 1 \ /recordings/%Y-%m-%d_%H-%M-%S.mp4这里的核心逻辑是从 go2rtc 的 RTSP Server 拉流-c copy不做转码直接复制编码数据CPU 开销几乎为零。分段录制的好处是即使某段文件因为网络波动损坏前面已完成的时段文件仍然可播不至于一整天的录像全丢。6. 踩坑实录与性能建议跑了三周后的经验能用和好用之间隔着一堆坑。我连续跑了三周多过程中遇到过几个非常典型的问题排查思路值得记录。6.1 四个常见问题及排查链路第一个问题是 WebRTC 点击后一直正在连接。排查思路是按协议走先看 TCP 控制连接是否通再看 UDP 媒体通道是否被防火墙拦截。在 Docker bridge 模式下最常出问题的就是 8555 的 UDP 没映射。用nc -u 你的IP 8555可以快速验证 UDP 端口通不通如果不通回到 compose 文件补上 UDP 映射。第二个问题是画面卡顿、音频不同步。一般是摄像头主码流码率偏高而 WiFi 传输不稳导致。优先把 Web UI 里的播放模式切到 MSE 或 HLS 做对比如果切到 HLS 就好了那不是 go2rtc 的问题是链路带宽不够。解决方法是给这个流单独定义一个低分辨率子码流源用子码流做预览主码流保留给录像。第三个问题是摄像头不推流但日志没有明显错误。先换一个测试流验证 go2rtc 本身是否正常再确认摄像头的 RTSP 地址是否真的可以从 docker 宿主机访问。我碰到过一次是摄像头绑定了 MAC 地址准入换到宿主机网段后地址虽然 ping 通但 RTSP 请求被拒绝了。第四个问题是容器重启后配置丢失。十有八九是 volume 挂载参数写错导致 go2rtc 读的是镜像内默认配置而不是宿主机挂载的文件。排查时进容器看一眼实际加载的配置文件即可docker exec go2rtc cat /config/go2rtc.yaml如果内容和你本地的对不上说明挂载路径映射有问题。6.2 稳定性与资源占用建议go2rtc 本身内存占用非常低我同时管理 8 路 1080p 摄像头容器内存稳定在 200MB 上下CPU 基本可以忽略因为它不转码。真正吃资源的是下游的录像容器和 WebRTC 连接数所以建议把 FFmpeg 录像容器单独拆出去别和 go2rtc 塞在一个容器里互相挤压。关于镜像更新我习惯每月拉一次latest并重启go2rtc 迭代很快新版本经常修复 WebRTC 兼容性问题。但注意升级前备份 config 目录虽然配置格式基本向后兼容但万一你用了比较冷门的旧版语法新版本可能不认。日志方面容器默认日志量不算大不过如果同时接入几十路流建议在 compose 里限制日志大小logging: driver: json-file options: max-size: 10m max-file: 3最后再说一个容易被忽略的习惯给每个流命名时尽量用简短、不带空格的英文名。因为 go2rtc 的流名会直接出现在 RTSP、HLS、WebRTC 的 URL 路径里带中文或特殊符号的流名会让某些播放器解析出问题。我一开始用过cam_客厅这种名字手机上某些 App 打开就是黑屏改成cam_living后一切正常。这个细节在官方文档里没怎么强调但实际影响不小。
返回列表