做摄像头接入这件事,折腾过的人都知道有多头疼。家里装了三五个不同品牌的摄像头,海康的走 RTSP,大华的走私有协议,杂牌的又是 ONVIF,想在同一个页面上看完所有画面,往往要装好几个 App,来回切换。后来我接触到 go2rtc,配合 Docker 部署,一个容器就把 RTSP、RTMP、HLS、MJPEG、WebRTC、ONVIF 这些协议全部打通了,浏览器里直接打开就能看实时画面,延迟能压到几百毫秒以内。这篇文章就是记录我完整搭建这套摄像头多协议流媒体平台的过程,从选型思路到 Docker 部署,再到摄像头接入和问题排查,希望能帮你少踩几个坑,尤其是那些正在折腾 Home Assistant 或者多品牌摄像头统一接入的朋友,这套方案值得仔细看一遍。

1. 先搞清楚 go2rtc 到底解决什么问题

1.1 摄像头接入的三大痛点

摄像头接入这件事,本质上就是三个问题:协议不统一、延迟降不下来、接入成本太高。

协议不统一是最直观的。海康威视摄像头默认走 RTSP,地址格式是 rtsp://账号:密码@IP:554/Streaming/Channels/101 ;大华的 RTSP 地址又长又怪,类似 /cam/realmonitor?channel=1&subtype=0 ;还有一批老摄像头只支持 RTMP 推送或者 MJPEG,甚至有些家用摄像头压根就不给你 RTSP 地址,只能通过它们的云平台看。你想把这些设备统一到一个平台里,就得让平台同时兼容这么多协议,这就不是一个小项目了。

延迟高是第二个痛点。很多人第一反应是用 FFmpeg 做转码,把 RTSP 转成 HLS 流,然后用网页播放。HLS 的切片机制决定了它天生有延迟,从摄像头到浏览器,1 到 3 秒的延迟是常态,严重的时候能到 5 秒以上。这样的延迟看个静态场景还行,要是在门口装个摄像头做实时监控,人走过去 3 秒画面才动,那就基本失去了监控的意义。

接入成本高则是被很多人低估的坑。我说的不只是买设备那点钱,而是维护成本。自己写程序要处理各种协议库、缓冲、丢包、重连;用现成方案也要面对编译依赖、配置复杂、文档缺失这些破事。如果你只是为了在 Home Assistant 里看几个摄像头,要去搭一套 ZLMediaKit,那学习成本和维护成本都太高了。go2rtc 这种轻量级方案,一个二进制文件或者一个 Docker 容器就能跑起来,正好解决这个问题。

1.2 go2rtc 的核心能力拆解

go2rtc 的核心定位是“流媒体网关”,它做的事情就是协议的转换和分发。你给它一个 RTSP 源,它可以把这条流同时以 WebRTC、HLS、MJPEG、LL-HLS 等多种协议分发出去,这样前端无论用什么播放器都能拉到画面,而后端你不需要维护多条独立的转码链路。

它的几个关键能力我分别说一下。

WebRTC 低延迟播放是 go2rtc 最出彩的地方。WebRTC 最初是为音视频通话设计的,走 UDP 传输,天然就是低延迟路线。go2rtc 自己实现了 WebRTC 服务端逻辑,从 RTSP 源拉流之后直接以 WebRTC 方式分发给浏览器,中间不需要经过转码环节。我这里实测下来,从摄像头到浏览器画面出现,延迟基本稳定在 300 到 500 毫秒,这个水平用在门铃、看护、安防场景里足够了。

多协议接入是第二个核心能力。它不只是能接 RTSP,RTMP、MJPEG、HTTP-FLV、HLS 这些主流形式都能作为输入源。你用 OBS 推一路 RTMP 流给 go2rtc,它也能把它转成 WebRTC 给网页播放,这个灵活性在做直播场景时非常好用。

ONVIF 自动发现是第三个亮点。ONVIF 是安防行业的标准协议,大部分品牌摄像头都支持。go2rtc 可以直接通过 ONVIF 协议探测摄像头的 RTSP 地址,不用你手动去翻说明书找路径,你只需要给它摄像头 IP 和账号密码,它能自动把可用的流地址找出来。这一点后面接入实战部分我会详细演示。

1.3 和 FFmpeg、ZLMediaKit、Mediamtx 比,为什么选它

我最早用的方案其实是 FFmpeg 加 Nginx,后来也试过 Mediamtx(前身是 RTSP-Simple-Server),分别在两个场景里跑过一阵子,简单说说对比。

FFmpeg 方案灵活但也原始。它可以做真正的转码,从 H.265 转到 H.264,从 RTSP 推到 Nginx-RTMP,再切成 HLS。可问题是整个链路太长,中间任何一个环节挂了都要手动拉起,重连逻辑也得自己写。大量摄像头同时接入时,多个 FFmpeg 进程管理的复杂度会直线上升,CPU 也会被拖垮。

Mediamtx 作为轻量级 RTSP/RTMP 服务器很优秀,但它更多解决的是“接收和转发”这一个环节。它的定位是流媒体服务器,专注于协议转发,缺少 go2rtc 这种面向摄像头接入场景的 ONVIF 发现、WebRTC 低延迟分发、以及与 Home Assistant 深度集成这些能力。如果你只需要一个录流服务,Mediamtx 是合格的,但要做摄像头统一接入和低延迟查看,go2rtc 更对口。

ZLMediaKit 是另一个业界常用的服务器端方案,性能强、功能全,但配置和部署复杂度明显更高,更适合作为正式的流媒体服务来维护。对我这种要快速搭好、长期稳定跑的场景来说,用 ZLMediaKit 有点杀鸡用牛刀了。

所以我的结论很直接:go2rtc 的定位是“摄像头接入的轻量级网关”,它不需要你懂复杂的流媒体协议栈,也不需要维护一堆转码进程,一个容器跑起来,剩下的交给它。

2. Docker 部署前的准备:网络模式、端口与摄像头地址

2.1 Linux 下 Docker 环境与最小目录规划

go2rtc 官方提供了 Docker 镜像,名字是 alexxit/go2rtc ,Docker Hub 和 GitHub 都有发布。部署前你需要一台能跑 Docker 的机器,我这边用的是局域网里的一台 Debian 小主机,2 核 2G 内存,配置不算高,同时跑五六路摄像头画面毫无压力。如果只是接入两三路,树莓派或者软路由里的 Docker 环境也足够。

如果你还没装 Docker,在 Ubuntu/Debian 上就直接用官方脚本装一遍,装完确认 daemon 在运行, docker version 能输出客户端和服务端版本就行。安装步骤很常规,我就不展开讲了,网上成熟教程一大把,重点是一定要把 Docker 源换成国内可用的镜像源,不然拉 alexxit/go2rtc 这个镜像会等到怀疑人生。

目录规划这块,我的习惯是单独建一个目录给 go2rtc,不和其他容器混在一起:

mkdir -p /opt/go2rtc
cd /opt/go2rtc

然后在这个目录里放 docker-compose.yml 和 go2rtc.yaml 两个文件。配置文件挂在容器外,一是方便直接编辑,二是升级容器时配置不会丢。go2rtc 容器内有自己的配置目录,官方要求把配置挂载到 /config/go2rtc.yaml ,这属于部署时的固定动作。

2.2 host 网络模式和 bridge 网络模式怎么选

go2rtc 部署中有一个非常关键的选择:网络模式。官方文档推荐的是 network_mode: host ,也就是让容器直接用宿主机网络,不经过 Docker 的 NAT 转发。这样做的原因和 WebRTC 的传输机制有关。

WebRTC 播放时需要客户端和 go2rtc 之间通过 UDP 进行数据传输,默认端口是 8555。如果用 Docker 的 bridge 网络,端口映射需要同时映射 TCP 和 UDP,并且 WebRTC 还要支持 ICE 协商,也就是客户端和服务器之间要来回探测可用的网络路径。端口映射一多,中间任何一层 NAT 或者防火墙没放通,WebRTC 就建不起来,表现为页面一直转圈就是不出画面。用 host 模式,容器直接占宿主机的 8555 端口,少了一层 NAT,成功率会高很多。所以如果你的宿主机是 Linux,就跑在 Linux 上,优先用 host 模式。

但是有一个例外情况要专门提醒:如果你用的是 Windows 或 macOS 上的 Docker Desktop,host 网络模式的兼容性不一样,实际使用中经常是配了 host 但容器起不来,或者端口监听不到。这种情况下就要退回到 bridge 模式,显式映射端口。后面常见问题章节我会再细说。

2.3 从摄像头侧拿到可用的 RTSP 地址

在配置 go2rtc 之前,你的摄像头得先具备能被局域网访问的条件。IP 摄像头一般要做两件事:一是把摄像头接到和 go2rtc 相同的局域网,二是通过厂商工具或者网页后台开启 RTSP 功能,并确认账号密码。

不同品牌的 RTSP 地址格式差别不小,我把几个常见品牌的格式整理成了表,方便你对照查找。如果你的摄像头品牌不在表里,也有一个通用思路:在厂商提供的网页后台里找“集成协议”“ONVIF”“RTSP”这类选项,大部分正规设备都会在说明文档里标注流地址格式。

品牌 RTSP 地址格式(主码流/子码流)
海康威视 rtsp://user:pass@IP:554/Streaming/Channels/101 / /102
大华 rtsp://user:pass@IP:554/cam/realmonitor?channel=1&subtype=0 或 subtype=1
TP-LINK rtsp://user:pass@IP:554/stream1 / /stream2
宇视 rtsp://user:pass@IP:554/unicast/c4/s0/live
杂牌/通用 ONVIF 通过 ONVIF 自动发现,不需要手动拼路径

拿到地址后,我习惯先用 VLC 验证一下这个地址能不能播。在 VLC 里打开网络串流,粘贴 RTSP 地址,能出画面就说明地址和账号密码没问题。这一步非常关键,因为如果你在 go2rtc 里配置了半天发现不生效,结果其实是摄像头地址本身写错了,排查起来会很费劲。

另外要注意主码流和子码流的选择。主码流分辨率高、码率大,画面清晰但占用带宽高;子码流分辨率低,适合多画面预览或移动端观看。如果你用 go2rtc 做本地多路集中查看,建议在列表里同时配置主码流和子码流,预览时先看子码流,点开单路大画面再切主码流,这样最省网络带宽。

3. 一条命令跑起来:Docker Compose 部署与配置文件拆解

3.1 编写 docker-compose.yml

我用了 Docker Compose 来管理 go2rtc,因为 Compose 可以把容器启动参数固化在文件里,以后换机器或者重装系统,一条命令就能恢复环境,不需要记住那一长串 docker run 参数。下面是我在 Linux 上实际使用的 compose 文件:

services:
  go2rtc:
    image: alexxit/go2rtc:latest
    container_name: go2rtc
    restart: unless-stopped
    network_mode: host
    volumes:
      - ./go2rtc.yaml:/config/go2rtc.yaml
    environment:
      - TZ=Asia/Shanghai

拆开来说一下每个配置项的作用。 image 用的是 latest 标签,go2rtc 更新比较频繁,latest 能及时拿到新功能和修复,但如果你追求极致稳定,也可以固定在某个具体版本号上。 restart: unless-stopped 表示 Docker 服务启动或者容器异常退出时自动拉起,摄像头这种 7x24 小时跑的服务一定要加这个。 network_mode: host 前面说过了,是 WebRTC 低延迟播放的关键。 volumes 把宿主机上的 go2rtc.yaml 挂载到容器内配置路径,这样改配置不用进容器。

如果你是在 Docker Desktop 上跑,需要把 compose 改成 bridge 模式,显式映射端口:

services:
  go2rtc:
    image: alexxit/go2rtc:latest
    container_name: go2rtc
    restart: unless-stopped
    ports:
      - "1984:1984/tcp"
      - "8555:8555/tcp"
      - "8555:8555/udp"
    volumes:
      - ./go2rtc.yaml:/config/go2rtc.yaml
    environment:
      - TZ=Asia/Shanghai

这样映射之后,WebRTC 的 UDP 路径也能从宿主机转发进容器,实际可用性会好很多。但注意,在 Docker Desktop 的 macOS 版本上,某些网络模式仍有兼容性问题,如果你发现 UDP 端口不好使,优先检查你的 Docker 版本和网络配置文档。

3.2 go2rtc.yaml 配置文件拆解

go2rtc 的配置全部集中在 go2rtc.yaml 里,初次上手不需要理解太多,一个最小可用配置长这样:

log:
  level: info

api:
  listen: ":1984"

webrtc:
  listen: ":8555"

streams:
  front_door: rtsp://admin:123456@192.168.1.64:554/Streaming/Channels/101

逐行解释一下。 log 是日志级别配置, info 级别会输出连接建立、断流、错误等关键信息,排查问题时有用,日常跑着也不吵。 api.listen 是 go2rtc 的管理接口和 Web UI 监听地址,1984 是它的默认端口,浏览器访问 http://宿主机IP:1984 就能打开控制台。 webrtc.listen 是 WebRTC 的监听端口,默认 8555。

streams 是核心,它是一个映射表,键是流的名字,值是流地址。上面配置的意思是创建一条名为 front_door 的流,来源是海康摄像头的 RTSP 主码流。流名字是自定义的,建议用有意义的英文标识,比如 front_door (前门)、 back_yard (后院)、 living_room (客厅),方便在 Web UI 里一眼认出是哪路摄像头。

go2rtc.yaml 支持 YAML 注释,我建议把自己的摄像头 IP、账号、流地址写清楚后在配置里加上注释,时间久了你自己回来看也能快速知道哪行对应哪个摄像头。另外注意,如果 RTSP 地址里有 @ 、 # 、 ? 、 & 这种特殊字符,YAML 里最好用单引号把整个地址包起来,避免解析出错。

提示:go2rtc 的配置文件是启动时读取的,你改了配置之后需要重启容器才能生效。命令是 docker compose restart go2rtc ,如果看到日志没有报错,说明新配置已经被正常加载了。

3.3 启动容器并验证服务

配置写好后,在 /opt/go2rtc 目录下执行:

docker compose up -d

它会自动拉取镜像并启动容器。稍等几秒,先确认容器状态:

docker ps | grep go2rtc

看到状态是 Up 就没问题。再看一眼日志,确认没有配置错误:

docker logs go2rtc

正常日志里会看到 api listening on :1984 、 webrtc listening on :8555 之类的输出。接下来验证服务是否真的通了,几个步骤按顺序来。

第一步,访问 Web UI。在浏览器里打开 http://宿主机IP:1984 ,能看到一个简洁的页面。这时候你配置的 front_door 流应该已经显示出来了。第二步,直接在 Web UI 里点击流名称旁边的播放按钮,查看画面是否能打开。go2rtc 的 Web UI 自带播放测试器,会让你选择用 WebRTC、HLS 还是 MJPEG 来播放,我推荐先用 WebRTC,因为这是它的强项,验证延迟效果最直观。第三步,用 API 验证流列表:

curl http://localhost:1984/api/streams

返回的 JSON 里可以看到流名、当前状态、源地址等完整信息。如果这一步返回里能看到 front_door 并且没有明显错误信息,说明 go2rtc 已经成功拉取到了摄像头流。看到画面、API 通、状态正常,部署这层就算彻底完成了,下一步才是真正考验配置能力的时候——接入各种不同协议和品牌的摄像头。

4. 摄像头接入实战:RTSP、ONVIF 与低延迟播放

4.1 手动配置 RTSP 码流:主码流和子码流分开配

最常用的接入方式就是在 streams 里手动写 RTSP 地址。我先展示一个接了两路摄像头的配置,这里面包含了不少容易踩坑的细节:

streams:
  front_door:
    - rtsp://admin:pass@192.168.1.64:554/Streaming/Channels/101
  front_door_sub:
    - rtsp://admin:pass@192.168.1.64:554/Streaming/Channels/102
  living_room:
    - rtsp://admin:pass2@192.168.1.65:554/cam/realmonitor?channel=1&subtype=0

注意 front_door 和 front_door_sub 是两条独立的流,分别指向同一个摄像头的主码流和子码流。为什么要这样分开配?因为在多路预览或者网络带宽不足的时候,用子码流可以大幅降低带宽消耗,需要仔细看某一画面时再切到主码流。这个逻辑和你在海康、大华官方客户端里看到的流畅/高清切换是同一回事。

另外注意值的位置,一个流名下面用了一个列表,这是因为 go2rtc 允许一个流名对应多个源地址,如果第一个源断了它可以自动切换到备用源。这个特性在做多路冗余时会很实用,比如同一个摄像头存在两个打包方式,标清流作为备源。我个人在普通家庭场景里一般就写一个源,但如果你在办公室或者园区里跑,建议把主备源都配上。

RTSP 地址里的账号密码一定要和摄像头后台设置的一致。很多人在这一步卡住,是因为摄像头后台改过密码,但 go2rtc 里还写着初始密码,拉流失败日志会报 401 Unauthorized 。排查时先在 VLC 里用同样的地址试一遍,这一步能过滤掉 80% 的账号问题。

4.2 ONVIF 自动发现:不用拼地址也能接入

手动写 RTSP 地址对海康、大华这种格式固定的设备没问题,但遇到一些没有公开文档的杂牌摄像头就很头疼了。这种时候 ONVIF 就是救命稻草。ONVIF 是一个安防设备互操作标准,支持这个协议的摄像头会公开一组接口,go2rtc 可以调用这些接口自动发现设备支持的媒体流地址。

go2rtc 的 streams 配置里可以直接写 ONVIF 地址,格式是:

streams:
  garage_cam:
    - onvif://admin:password@192.168.1.66:8000

启动后 go2rtc 会通过 ONVIF 协议向摄像头发起探测,拿到可用的 RTSP 流地址,然后自动建立连接。你完全不需要知道这个摄像头的 RTSP 路径长什么样。我在一台不知名厂商的摄像头上试过这个方式,它的 ONVIF 端口是 8000,配置后 go2rtc 成功识别出了主副两个流地址,整个过程中我确实没有手动去查任何路径信息,省去了很多麻烦。

ONVIF 方式还有一个隐藏福利:知名品牌设备通常也会在 ONVIF 接口里返回设备型号、序列号、固件版本等信息,go2rtc 会在日志或 API 响应里带上这些元数据,对资产盘点有辅助作用。但也要说一句,有些杂牌摄像头虽然标注支持 ONVIF,实际上实现并不完整,探测可能失败,这种就只能退回手动写 RTSP 地址,或者用厂商私有 SDK 配合。

如果你家里摄像头数量多,还有一个更省事的思路:go2rtc 支持通过 API 批量添加流。你可以在 Web UI 里手动添加,也可以通过 POST /api/streams 的方式在脚本里成批写入配置。我自己用脚本读取一份 CSV 表格(里面有摄像头名称、IP、账号、密码),然后循环调用 API 把二三十路流一次性加进去,比手写 YAML 快得多,也方便后续在脚本里统一改名、调整参数。

4.3 WebRTC 低延迟播放与 Home Assistant 联动

go2rtc 接入摄像头之后,最爽的一件事就是浏览器直接打开,毫秒级延迟看画面。你在 Web UI 里点击某个流,选择 WebRTC 播放,浏览器会和 go2rtc 建立 UDP 通道,实现接近实时的画面。我实际测试时,用自己的手机连着局域网 Wi-Fi,画面上我做出动作到屏幕上出现,体感上几乎就是同步的,这种体验和传统 HLS 那种转圈等画面完全不同。

WebRTC 能这么低延迟,核心在于它不走“切片-下载-播放”的流程,而是通过 UDP 持续推流。浏览器原生支持 WebRTC,go2rtc 自己做了协议转换,所以整个链路就是“摄像头 RTSP -> go2rtc -> 浏览器 WebRTC”,中间没有转码延迟,没有切片等待,自然就快。虽然受限于浏览器实现和网络状况不能做到绝对的实时,但 500 毫秒以内的水平对绝大多数监控、门铃、看护场景已经完全够用。

如果你在用 Home Assistant,go2rtc 还有更优雅的玩法。HASS 社区有对应的 go2rtc 集成,你在 HASS 里配置好 go2rtc 集成后,摄像头卡片可以直接引用 go2rtc 里的流名称,不需要为每个摄像头单独写 rtsp: 实体配置。我目前就是把 go2rtc 作为 HASS 的流媒体后端,摄像头画面在 HASS 的仪表盘里直接展示,延迟低,卡片加载也快,比 HASS 自带的 stream 组件体验好很多。这里提醒一句:HASS 集成和 go2rtc 的主程序是两套组件,HASS 侧要先安装 go2rtc 集成(通过 HACS 或手动安装),再在 HASS 配置里指定 go2rtc 服务地址,这样才能把摄像头资源同步过来。

4.4 用 ffmpeg 扩展:兼容老设备和编码格式

go2rtc 的很大一个优点是它内部集成了对常见格式的解析能力,但它也有对付不了的情况。比如某些设备只输出 H.265、MPEG4 等格式,而浏览器又不原生支持这些编码格式的 WebRTC 播放,这时候就需要转码了。go2rtc 支持在配置里调用外部 FFmpeg 来处理这类源,把不支持格式的输入转成浏览器能直接播放的格式。

在 go2rtc.yaml 里先声明 FFmpeg 的可用性:

ffmpeg:
  bin: "ffmpeg"

然后在流地址前加上 ffmpeg: 前缀,比如:

streams:
  legacy_cam:
    - ffmpeg:rtsp://admin:pass@192.168.1.67:554/live

go2rtc 检测到带 ffmpeg: 前缀的源时,会拉起一个 FFmpeg 进程来处理这个流,之后再把处理好的流注册到 go2rtc 的分发链路中。这种模式下 CPU 占用会上升,因为转码本质上是实时运算,所以如果不是格式实在不兼容,我一般不建议普遍开启,只在个别的老旧设备上开。

另外,如果你的摄像头同时被多个客户端访问,比如 HASS、Web UI、手机 App 三端同时看,go2rtc 会做分发层的优化,同一路源只需要从摄像头拉一次,后续所有播放都从这个缓存分发出流。多个客户端同时播放同一路流时,不会给摄像头带来成倍压力,这对摄像头这种性能并不强的设备来说非常友好。我刚部署完时同时开着三个页面看同一路画面,摄像头侧的 CPU 占用几乎没变化,而如果三端各自独立拉流,摄像头早就卡死了。

5. 常见问题速查与避坑实录

5.1 典型问题速查表

我把这段时间实际使用中遇到的问题整理成了表格,遇到相似情况的可以先对照排查,很多问题一看表就有思路了。

问题现象 可能原因 排查与解决办法
Web UI 能打开,但 WebRTC 播放一直转圈 8555 UDP 端口没放通 / 网络模式不对 确认宿主机的 8555 UDP 端口可访问;Linux 优先 host 模式;检查防火墙放行 UDP 8555
播放时有画面但是延迟很高 播放器选了 HLS 而不是 WebRTC 在 Web UI 播放测试器里切换为 WebRTC;HLS 本身有 1-3 秒延迟属正常
摄像头源连不上,日志报 401 Unauthorized RTSP 账号密码错误 在 VLC 里用同一地址验证,确认账号和密码;检查摄像头后台密码是否被修改
摄像头源连不上,日志报 Connection refused IP 或端口写错 / 摄像头不在同一网段 用 ping IP 和 telnet IP 554 验证基本连通性;确认摄像头和服务器在同一局域网或路由可达
容器反复重启 配置文件语法错误 / 端口被占用 用 docker logs go2rtc 看启动日志;修正 YAML 缩进;释放被占用的 1984 或 8555 端口
在 Windows/Mac Docker Desktop 上容器起不来 host 网络模式在此环境不生效 改用 bridge 模式,显式映射 1984 和 8555 的 TCP/UDP 端口
接入多个摄像头之后 CPU 占用升高 开启了 FFmpeg 转码或者同时在拉主码流 检查日志中是否有 ffmpeg 进程;把不需要大屏显示的流切换到子码流;关闭不必要的转码

5.2 我踩过几次坑之后的经验

第一个最典型的坑是防火墙把 UDP 8555 给拦了。我第一次在一台 CentOS 机器上部署时,Web UI 能开,HLS 能播,就是 WebRTC 起不来,浏览器控制台里全是 ICE 相关的报错。查了半天,才发现防火墙规则只放行了 TCP,UDP 8555 一直被拦着。WebRTC 建连阶段需要 UDP 打洞,UDP 不通就什么都白搭。所以 Linux 防火墙里一定要显式放行 UDP 8555,命令类似 firewall-cmd --add-port=8555/udp ,具体命令依你的防火墙管理工具而定。

第二个坑是 RTSP 地址里的特殊字符。有个摄像头的密码里带了一个 @ 符号,我直接写进 YAML 里,go2rtc 老是解析成错误的地址。后来把整个地址用单引号括起来,再把密码里的特殊字符做了 URL 编码,才正常连上。如果你密码里有 @ 、 : 、 / 、 # 这些字符,建议先在工具里转义,或者干脆把密码改简单一点,摄像头内网访问用不到特别复杂的密码,但要注意避免用弱口令,至少要保证密码强度说得过去,毕竟摄像头暴露在局域网内也有被扫描的风险。

第三个坑和摄像头主码流有关。接入一开始图省事,把主码流同时配置给预览和大屏,结果三路摄像头就把交换机和小主机折腾得够呛。后来我把预览用的流全部切到了子码流,只在点击某路画面放大时才切换主码流,网络和 CPU 占用一下就降下来了。如果你发现画面卡顿、卡死频繁,先从码流选择开始排查,这个优化成本是最低的。

还有一个容易忽略的点:go2rtc 的 Web UI 接口本身没有认证。只要有人能访问到服务器 1984 端口,他就能直接看到你的所有摄像头画面,甚至通过 API 修改流配置。这个风险在局域网内可能还好,但如果有任何方式的公网暴露,隐患就大了。

5.3 安全加固建议

go2rtc 默认的 Web 管理接口不带登录认证,这个特性在方便排查、方便配置的同时也埋下了安全隐患。使用它的最低底线是:不要把 1984 端口直接暴露到公网,也不要在路由器上随意做端口转发。

我目前的做法是把 go2rtc 限制在专门的局域网网段,只允许受信任的内网设备访问。如果有远程查看的需求,我会在它前面放一层带认证的反向代理,由代理负责登录校验,然后把 /api 、 /stream 这些请求转发给 go2rtc。这样既保住了 WebRTC 的低延迟特性,又给管理接口加了一层访问控制。反向代理本身也有认证插件,就不在这里展开讲具体配置了,重点是“绝不让裸奔的 1984 端口暴露给公网”。

另外,给 go2rtc 单独创建操作系统账号或使用非 root 用户运行 Docker 容器,也是值得做的加固手段。即使容器被攻击,也能把影响范围控制在最小。如果你对摄像头隐私特别敏感,可以考虑在物理层面用独立 VLAN 隔离摄像头网段和办公网段,不过这个属于网络规划层面的优化了,不做也不会妨碍 go2rtc 的正常使用。

在写这篇文章的过程中,我又重新部署了一遍整个流程,每一步都做了验证。说实话,go2rtc + Docker 这套组合,是我目前用过的摄像头接入方案里“性价比”最高的:部署成本低、配置直观、协议支持广、延迟表现好。如果你家里或者办公室正好有一堆不同品牌的摄像头,想在一个页面里统一查看,或者正在给 Home Assistant 找低延迟的摄像头后端,强烈建议照这篇文章的步骤试一下。跑起来之后你就会发现,摄像头接入这件事,确实可以不用那么折腾。最后分享一个我自己的习惯:每次改完 go2rtc.yaml 只是重启容器还不够,我还会在 Web UI 里把每路流点一遍,确认画面正常后才算结束,避免某一路断流了但没及时发现。这个习惯看着费事,但在摄像头数量多的时候,能帮你省下后面很多排查的时间。

Logo

邀请您加入社区

更多推荐