尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

go2rtc+Docker部署指南:轻松实现网页低延迟摄像头监控

go2rtc+Docker部署指南:轻松实现网页低延迟摄像头监控 1. 为什么我放弃了“RTSP 直连播放”改用 go2rtc先说个我踩过的坑。以前给人做监控大屏或者车间看板最省事的方案是什么VLC 拉 RTSP。客户电脑装个 VLC然后把“rtsp://admin:password192.168.1.64:554/Streaming/Channels/101”这种地址扔进去就能看画面。但这个方案有个致命伤——Web 页面里没法直接看。浏览器是不认 RTSP 协议的你不可能让客户打开 Chrome 就直接输入 rtsp 地址看监控。有人用 VLC 的 Web 插件但那个插件现在基本被浏览器封死了。也有人用 FFmpeg 转 HLS延迟能给你干到 5 秒以上看人脸都嫌费劲。后来我经手了一个小项目客户要求是在网页端同时预览厂区里 20 多个摄像头混合了海康、大华、还有几个杂牌 IPC。这要是每个摄像头单独转流服务器得炸。于是我开始认真玩 go2rtc。go2rtc 不是什么新玩意儿但在“多协议接入 网页实时预览”这个场景里它是我用下来最顺手的工具。它的核心思路是不管你摄像头是什么协议统一出流成浏览器能直接看的 WebRTC以及 MJPEG、LL-HLS 等。而且它资历浅、体量小一个 Docker 镜像拉下来就完事不需要像 SRS 或者 ZLMediaKit 那样折腾一堆依赖。这篇文章我就把怎么用 Docker 部署 go2rtc、怎么把各种摄像头接进来、以及我实际操作中遇到的那些坑一次性说清楚。这篇文章适合谁看正在折腾 Home Assistant 接摄像头的人、想用树莓派做监控中转的人、还有给公司搭轻量级监控看板但不想买商业平台的运维。如果你是那种看到 FFmpeg 命令行就头疼的小白这篇文章也能帮你少走不少弯路。2. Docker 部署 go2rtc 的完整流程2.1 为什么选 Docker而不是直接装二进制go2rtc 官方其实提供了 Linux、Windows、macOS 的预编译二进制我自己也试过直接在 Ubuntu 服务器上跑——确实能跑但有一个很头疼的地方版本更新太频繁。go2rtc 算是活跃项目几乎一两周就有新版本手动换二进制还得停服务、备份配置、再启动麻烦。用 Docker 就简单了一条docker pull加一条docker run就完事回滚也就两条命令。另外Docker 方式跑 go2rtc 还天然带了资源隔离。我这台机器同时还跑着其他服务如果 go2rtc 因为某个摄像头的码流异常导致 CPU 飙高至少不会把整个系统拖死。重启策略也方便设置好--restart unless-stopped它就能一直活着。2.2 用 host 模式还是端口映射先直接给结论在 Linux 上部署 go2rtc我强烈建议用 host 网络模式。为什么关键在于 go2rtc 的招牌功能 WebRTC 传输。WebRTC 不是单一 TCP 连接它默认会在你的服务器上开一段 UDP 端口范围默认我配置成 50000~50050用来做媒体数据传输。如果你用默认的 bridge 网络模式就得单独把这段 UDP 端口也映射出来而且在 NAT 后面链路WebRTC 的协商会非常容易翻车。我曾经在 Docker bridge 模式下折腾 ICE 视频流折腾了半天画面就是出不来日志里一堆candidate报错。切到 host 模式以后这些问题全部消失。如果你的环境实在不能用 host 模式比如用的是 Docker Desktop 跑 Windows 容器那至少要把下面这些端口都映射出去8554/tcpRTSP 入口、8555/tcpWebRTC 的 HTTP 信令、1984/tcpWeb UI 管理界面以及你自定义的 UDP 段默认是 50000~50050。下面是我常用的部署命令直接复制就能用docker run -d \ --name go2rtc \ --restart unless-stopped \ --network host \ -v /opt/docker/go2rtc:/config \ -e TZAsia/Shanghai \ -e GIN_MODErelease \ carlonluca/go2rtc:latest注意我特意挂了-v /opt/docker/go2rtc:/config这个目录所有摄像头配置、录制的回放文件都会存在这里。第一次启动时go2rtc 会自动在/config下生成一个默认的go2rtc.yaml后面所有配置都改这个文件就行。2.3 第一次登录 Web 界面先调整哪些参数启动之后浏览器访问http://服务器IP:1984。这里有个简单的 UI 面板左侧是“Streams”展示所有已配置的视频源右侧是“Playback”放录制文件。第一次进界面看到的是空的 Streams不用慌。建议先点右上角的“Settings”看一下 System 和 WebRTC 两个标签页。在 WebRTC 的配置里最关键的一项叫ICE 服务器。如果你是局域网内使用留空就行WebRTC 会自动发现内网地址如果你打算让公网的浏览器也能看比如通过端口映射出去这里需要填上stun:stun.l.google.com:19302这样的公开 STUN 地址。注意只填 STUN 解决的是“发现你的公网 IP”问题不解决 NAT 穿透失败的问题——后者要么靠 TURN 服务器要么就别折腾 WebRTC 了直接用 MJPEG 或 LL-HLS 更省心。这一步搞清楚了接下来就开始接摄像头。3. 配置文件详解从最简到复杂3.1 先搞清楚 go2rtc.yaml 的逻辑go2rtc 的配置文件的语法很简单核心就一个streams节点。它的设计思路是“给每个视频源起个名字名字对应一个 URL 或者一个处理指令”。UI 面板里显示的视频流列表就是从这个文件读出来的。举个例子最简单的配置长这样streams: living_room_cam: - rtsp://admin:password192.168.1.100:554/Streaming/Channels/101这里living_room_cam是流的别名你可以随意命名比如cam1、yard、parking之后在 Web 端调用或者在其他系统里拉流时用的就是这个名字。后面那一长串是 RTSP 地址。有些海康摄像头的地址中/Streaming/Channels/101的“1”代表主码流“01”代表通道 1如果要子码流就是102或201。子码流分辨率低、帧率低适合大屏九宫格预览主码流画面清晰适合单画面放大看细节。一般来说我会在配置里给同一台摄像头加两路流streams: cam1_main: - rtsp://admin:password192.168.1.100:554/Streaming/Channels/101 cam1_sub: - rtsp://admin:password192.168.1.100:554/Streaming/Channels/102这么做的原因很简单WebRTC 传输高分辨率主码流时如果客户端网速不够或者设备解码能力不行画面会卡顿到怀疑人生。有一个低码率的子码流做备用或者直接在 UI 面板切换体验完全不一样。3.2 多协议支持不只是 RTSPgo2rtc 真正值钱的地方在于它的streams节点不只接受 RTSP。我自己实际用过的就有RTSP最通用海康、大华、宇视、各种杂牌 IPC 基本都支持。RTMP很多网络摄像头和编码器支持推 RTMP 到指定地址go2rtc 可以作为 RTMP 服务器接收。HLS可以直接拉取其他平台已生成的 HLS 流。MJPEG适合那种很老式的 USB 摄像头或者某种 HTTP MJPEG 输出设备。USB 摄像头 / 本地文件直接把/dev/video0设备文件指进去。屏幕捕获display协议可以抓取本机桌面这个我在测试机上玩过能跑通。FFmpeg 后端理论上任何 FFmpeg 能读的源它都能接。这点我后面单独展开。多协议接入带来的好处是你不必为每一种摄像头都配一套平台。我现场就遇到过一台仓库用的老摄像头只支持 MJPEG over HTTP以前我都是写一段 Python 脚本去抓帧再转给前端现在直接丢给 go2rtc 一个 URL 就完事。3.3 通过 FFmpeg 接入“不听话”的私有协议如果说上面讲的都是“正规军”那现实世界里总有“杂牌军”。比如我接过一种特种设备上的摄像头只有厂商私有协议既不是 RTSP 也不是 RTMP但厂商提供了 FFmpeg 的拉流命令。这种场景下go2rtc 的配置方式不是给 URL而是给一个ffmpeg指令模板streams: special_cam: - ffmpeg:rtsp://admin:password192.168.1.50:554/stream0#videocopy#audiocopy这里的核心思路是go2rtc 内部会调用它自带的 FFmpeg 进程去做协议转换#videocopy和#audiocopy是告诉它直接复制视频和音频流不做重编码节省 CPU。但这里有个非常大的坑如果源格式本身不是浏览器能直接解析的编码格式光 copy 是没用的。比如某些老摄像头的视频编码是 MJPEG浏览器虽然能显示但 WebRTC 协议要求视频编码最好是 H.264MJPEG 走 WebRTC 会非常别扭。这种时候就得强转编码streams: old_cam: - ffmpeg:rtsp://admin:password192.168.1.60:554/stream0#videoh264#audioaac这段配置的意思是让 FFmpeg 做一次实时转码把输入视频转成 H.264音频转成 AAC再由 go2rtc 包装出流。代价是 CPU 占用会上升我实测下来 720p 的老摄像头转码后 CPU 大约吃 15%~20% 的单核。如果你的服务器性能一般建议优先尝试copy不行再上转码。4. 实操接入不同摄像头的完整过程4.1 海康 / 大华 / 萤石 RTSP 接入实战这是最常见的场景。拿海康威视举例一般摄像头出厂地址是192.168.1.64默认用户名admin密码是你激活设备时设的。如果你忘记了密码那得先在局域网里用 SADP 工具重置这是海康的传统操作。接入流程分四步确认摄像头和服务器在同一局域网段用ping测通。拿 VLC 或者 ffprobe 验证 RTSP 地址真实有效。我习惯用 ffprobe 检查ffprobe rtsp://admin:password192.168.1.64:554/Streaming/Channels/101能打印出 Stream #0 的编码信息说明通了。把地址填进go2rtc.yaml的streams节点重启容器或者直接在 UI 面板点“加流”。实际上 go2rtc 支持热更新配置修改完 yaml 后不用重启容器只在 UI 界面刷新就能看到新流这点很舒服。在 UI 面板点开流选一种输出方式WebRTC、MJPEG、LL-HLS测试。关于大华摄像头地址格式跟海康不一样常见的是这样streams: dahua_cam: - rtsp://admin:password192.168.1.65:554/cam/realmonitor?channel1subtype0subtype0是主码流subtype1是子码流。萤石摄像头大部分也走 RTSP 标准协议端口 554地址一般是rtsp://admin:passwordip:554/h264/ch1/main/av_stream但需要你在萤石云的 App 里开启“本地访问”权限否则 RTSP 可能拉不通。这个权限不开你怎么配都没用这是最容易卡住新手的地方。4.2 树莓派 USB 摄像头 / CSI 摄像头的接入如果你手头是树莓派想在 go2rtc 里直接预览 USB 摄像头流程也简单。先把摄像头插上在树莓派终端确认设备节点ls /dev/video*如果是 CSI 接口的树莓派摄像头模块比如 OV5647一般会出现/dev/video0。然后修改配置streams: usb_cam: - rtsp://192.168.x.x:8554/usb_cam usb_cam_local: - ffmpeg:video4linux2:///dev/video0#videocopy#audioskip这里有个关键点在 Docker 容器里访问 USB 摄像头必须把设备文件映射进去。也就是说你启动 go2rtc 容器的docker run命令要加上--device /dev/video0:/dev/video0。我之前第一次跑容器忘记加这个参数日志里报了一堆open /dev/video0: no such file or directory当时还以为是配置问题排查了半天才发现是设备没映射进去。另外CSI 摄像头在 go2rtc 里最简单的接入方式是通过 FFmpeg 的v4l2输入。但树莓派官方 CSI 摄像头使用的是自己的驱动层直接走 V4L2 不一定能识别到。一个更稳的做法是先用树莓派自带的rpicam-vid工具把视频流转成 RTSP 或者标准 MJPEG再推给 go2rtc。我在树莓派 4B 上用 ov5647 摄像头实测最终还是靠这条命令解决的rpicam-vid -t 0 --inline -o udp://127.0.0.1:5000这样 go2rtc 通过拉取本地 UDP 流的方式接入虽然绕了一圈但胜在稳定不掉帧。4.3 通过 ONVIF 自动发现局域网里的摄像头说句实在话手动填地址的痛谁配谁知道。尤其是设备一多IP 地址靠脑子根本记不住得一张表一个本子地写。go2rtc 支持 ONVIF 协议它帮你自动发现局域网里的摄像头服务当你打开 Web UI左边栏下方会有一个Discover区域点击搜索同一网段内支持 ONVIF 的设备就会列出来。我实测下来海康、大华、宇视这些主流品牌基本都支持。点击发现出来的设备填上账号密码go2rtc 会自动给出它的 RTSP 地址并加入配置。省去手动记忆 URL 的痛苦。但要注意ONVIF 发现需要 go2rtc 的运行环境跟摄像头在同一个二层广播域内。如果你的 go2rtc 跑在 Docker 的 bridge 模式容器里的广播包可能出不去。所以这也是我推荐 host 模式的理由之一——ONVIF 发现依赖于主机网卡真实参与局域网广播host 模式下天然可用。5. WebRTC 与延迟优化为什么比传统 HLS 体验好5.1 WebRTC 的低延迟原理大家在浏览器里看视频监控最常见的是 HLS 方案。HLS 的流程是服务端把视频切成一个个小片段一般 2~5 秒一个客户端按顺序下载播放。所以 HLS 天然有延迟低则 5 秒高了能到 15 秒。你拿手机看楼下小区门口的画面人走过去 10 秒之后手机才显示看监控这种场景很难接受。WebRTC 的延迟通常在 200~500 毫秒接近“实时”。它为什么能做到一是因为传输层用的是 UDP不需要像 TCP 那样做重传确认丢几个包也能继续渲染而是因为它的协议栈做了很多针对实时媒体的优化比如 JitterBuffer 来抵消网络抖动。这就像是你跟人打电话用的是语音数据包实时传输而不是等对方把整段话录成文件发过来再听。5.2 实际优化参数不过 WebRTC 不是“开了就用”它要求你的网络环境比较特殊UDP 端口段要畅通。默认是 50000~50050如果你的 go2rtc 跑在防火墙后面记得放行 UDP。服务器的公网 IP 要能被客户端发现。如果你是通过公网访问部署在内网服务器的 go2rtcWebRTC 往往会因为 NAT 穿透失败而黑屏。这种情况我建议直接切换成 MJPEG 模式预览MJPEG 就是服务端不断发 JPEG 图片帧浏览器直接显示延迟大约在 1~2 秒兼容性最好任何浏览器都能看。代价是画质不可控和流量消耗巨大。如果公网看是刚需更稳妥的做法是套一层 VRay 服务或者直接用 go2rtc 对外的 LL-HLS 流。这就是 go2rtc 比较贴心的地方它给你的不是一个固定输出方式而是同一个输入源、多种输出格式。在 Web UI 里点开一个摄像头右侧会出现 WebRTC / MJPEG / LL-HLS 三个播放选项你可以根据当前网络环境随意切换。5.3 LL-HLS 是什么什么时候用它LL-HLSLow-Latency HLS是苹果推的低延迟 HLS 标准把原来的切片时间从 2~6 秒缩短到 0.5 秒左右还引入了“预加载提示”机制让播放器能更快拿到最新内容。go2rtc 内置了对 LL-HLS 的支持你只需要在 Web 端播放时选择 LL-HLS 模式它就能自动出流。我一般在什么场景用 LL-HLS跨公网访问的时候。因为 WebRTC 穿 NAT 太依赖网络环境公网延迟高一点就黑屏而 LL-HLS 走标准 HTTP 协议任何网络环境都能稳定播出延迟又能控制在 1~3 秒。对于企业客户要求在手机 App 或者微信里远程看一下厂区画面LL-HLS 完全够用且不需要装任何插件。6. 常见问题与排查技巧实录6.1 “流已添加但就是不出画面”怎么办这是我在各种群里被问烂的问题。最多的原因是摄像头 RTSP 地址里的账号密码不对go2rtc 日志会显示401 Unauthorized。在 Web UI 的日志页面上能看到具体报错如果显示 401就去摄像头的网页管理台确认账号密码。注意海康、大华很多摄像头有个“安全码”机制用于第三方平台接入的有时候你填了正确的登录密码也不行还得到摄像头配置页的“对接平台”那里生成一个安全码才能拉流成功。第二种常见原因是地址里的路径写错了。比如大华有些型号的路径是/cam/realmonitor?channel1subtype0有些是/useradminpasswordxxxchannel1stream0.sdp不同固件版本差异不小。最快的办法是用 ONVIF 设备管理器扫一下设备的通道路径直接把生成的 URL 粘进go2rtc.yaml。6.2 画面卡顿与 CPU 占用过高如果多路摄像头同时打开画面开始掉帧第一步检查是不是所有摄像头都用了主码流1080p 以上如果是全部换成子码流或降低分辨率。监控场景中“看到人”比“看到毛孔”重要得多子码流能同时显示 16 路主码流可能 4 路就卡。CPU 飙高还有个隐藏坑当你把某一路流从 WebRTC 切换到 MJPEG 播放go2rtc 内部可能需要额外转一次码。因为 MJPEG 往往是独立的编码流程如果你在 UI 里同时开着好几路 MJPEG 预览CPU 会被拉爆。我的建议是最多保留 2 路 MJPEG 预览其余用 WebRTC 或 LL-HLS另外在 go2rtc 的配置中可以用#hardware参数尝试启用硬件解码如果你的服务器 CPU 支持 Intel Quick Sync 或 NVIDIA NVENC能明显降低 CPU 占用。6.3 公网访问时画面黑屏但局域网正常这基本就是 WebRTC 的 NAT 穿透问题。我在 3.3 节已经预告过最稳的方案是改走 LL-HLS 或者 MJPEG。如果你想继续用 WebRTC那就需要一台 TURN 服务器。TURN 的作用是当两个设备无法直接建立点对点 UDP 通道时由一台公网服务器转发媒体流量。go2rtc 的配置文件中WebRTC 部分可以设置 TURNwebrtc: ice_servers: - urls: turn:你的公网IP:3478 username: xxx credential: xxx如果没有现成的 TURN 服务器又不想自己搭那就老老实实切 LL-HLS也是一种解决方案。公网监控实时性要求通常没那么高LL-HLS 比折腾 TURN 省心十倍。7. 进阶玩法不只是看监控go2rtc 的能力边界远不止“把摄像头接到网页里”。我实际用过几个比较有意思的场景可以作为后续扩展的参考场景一Home Assistant 智能家居联动。go2rtc 是 HA 的官方推荐的摄像头集成方案之一你只要在 HA 里配置 go2rtc 作为摄像头源就能把任意 RTSP 摄像头变成 HA 的camera实体再结合人脸识别或者自动化规则做到“有人经过时拍照推送手机通知”。场景二本地录制与回放。go2rtc 支持record模式在配置里打开录制它会按时间把视频流写入磁盘。相比 NVR 录像机go2rtc 的优势是轻量单机跑十几路摄像头完全没问题而且录制文件直接是 mp4 格式不需要专用播放器。场景三多人同时查看。go2rtc 内部做了多客户端复用。比如 5 个人同时打开同一个摄像头它不会为每个人都建立一条独立的拉流连接而是复用一条上行 RTSP 拉流然后分发给多个浏览器客户端。这个设计对摄像头本身压力极小不用怕摄像头被拉爆。场景四多源合流与切片导出。如果你是开发人员go2rtc 暴露了 HTTP API可以直接调用接口获取摄像头的快照或者当前流地址。比如我用它给客户做过一个小程序进入页面就自动拿到 16 路摄像头的 MJPEG 快照点大某一路再切 WebRTC 放大整个开发量比从零写流媒体服务少了 90%。8. 最后分享一点真实体会这套环境我大概用了半年多从最初的单摄像头测试到后面 20 多路摄像头的正式环境go2rtc 的稳定性确实让我意外。唯一一次出问题是因为容器所在磁盘满了——录像文件把磁盘写满了导致整个容器崩溃。后来我把录像目录单独挂载到了一块大容量数据盘并把recorder的保存策略改成了“按天保留 15 天”这才彻底放心。另一个体会是别追求把所有摄像头都接到 go2rtc 里。有些摄像头的私有协议或者老旧固件接入成本很高甚至不稳定。而 go2rtc 在配置层面支持在streams里写多个 URL 做备用比如第一个失败自动切换到第二个所以对于关键点位我会配两个不同网段的摄像头一个为主一个为备保障核心通道永远在线。如果你刚开始接触建议先拿一台海康或者大华摄像头跑通“RTSP - go2rtc - WebRTC”这个最简单的链路再慢慢加设备、加录制、加 HA。这条路看似长但走通之后你就有了一套完全自主可控、不依赖任何云平台的流媒体基础设施。
返回列表