尧图精选

Docker部署go2rtc:打造多协议摄像头统一流媒体平台

🕒 发布时间:2026/9/19 18:41:32 📁 来源:尧图网络
折腾了好几个月的摄像头接入问题后我最终选择用 Docker 部署 go2rtc把家里那几台协议完全不同的摄像头统一成了一个多协议流媒体平台。海康走 RTSP小米的局域网 RTSP 开关藏得深树莓派 CSI 摄像头根本不走网络协议过去每看一路都要开一个独立 App要么就是被厂商私有协议绑死。go2rtc 解决了这个痛点它是一个用 Go 写成的轻量级流媒体网关支持 RTSP、RTMP、HTTP-FLV、HLS、WebRTC 等多种协议互转而且通过 Docker 拉起后配置文件一个、容器一个、端口一个几分钟就能跑起来。这篇文章是我从零到一部署的完整记录包含配置文件、网络模式取舍、多摄像头接入方法和一堆实测踩坑适合正在折腾统一看摄像头、又不想被各路厂商协议捆住的朋友。1. 项目概述与整体设计思路1.1 摄像头协议分裂是第一个绕不开的坎我在最开始接触这个需求时单纯想解决“所有摄像头能在一个页面里看”的问题。但实际一接才发现摄像头协议分裂得比想象中严重。海康的老型号只开放 RTSP用户密码和端口一把梭小米摄像头在米家 App 里用得很顺手可它的局域网 RTSP 功能通常要在设备设置里手动打开不开就是一个黑盒子树莓派摄像头模组 OV5647 更是完全不走网络协议直接挂载在/dev/video0要交给流媒体服务器读取。市面上成品 NVR 虽然能接入不少品牌但小米和 DIY 摄像头往往不在兼容列表里而且家庭用户不一定愿意为封闭设备再花一笔钱。go2rtc 的设计思路正好对症下药。它不关心你的摄像头是什么品牌只关心你能不能给出一个取流地址或设备节点。只要把“这个流从哪来”写进配置文件go2rtc 就会自己处理后续的协议转换和分发。它的核心不是解码、转码、录制这种重活而是“路由”——把不同来源的流转换成浏览器、播放器、智能家居平台都能直接用的协议。所以在整个体系里它扮演的是流媒体中枢的角色而不是视频存储平台。1.2 为什么选 go2rtc 而不是自己写 FFmpeg 脚本可能有人会问既然摄像头有 RTSP 地址是不是直接用 FFmpeg 拉流就行我一开始也是这么想的甚至写过一个循环脚本用ffmpeg -rtsp_transport tcp -i ... -f hls ...往目录里落切片再接个 Nginx 对外服务。问题是每加一个摄像头就要改一次脚本摄像头 IP 变了要改编码格式不同要传一堆参数断流重连还要自己实现整个方案脆弱得不堪一击。go2rtc 把这些事都收进去了。它内部集成了流媒体协议栈RTSP 输入、HLS 输出、WebRTC 协商这些都不用自己管甚至可以直接调用 FFmpeg 做特例处理。配置方式也比脚本直观得多每个摄像头在 YAML 文件里占几行加摄像头就像加字典条目一样简单。再配合 Docker 部署不用关心宿主机有没有 Go 环境、有没有 FFmpeg拉个镜像就能跑。对个人用户来说这种“工具化”的体验比“脚本化”舒服太多了。1.3 整体架构摄像头进来统一协议出去我实际部署后的数据流向大概是这样的摄像头作为输入源通过 RTSP、RTMP、HTTP-FLV 或者本地设备节点进入 go2rtcgo2rtc 作为流媒体中枢把每一路输入抽象成一个带名字的 stream同时对外提供 WebRTC、HLS、HTTP-FLV、RTSP 等输出浏览器访问 Web UIHome Assistant 通过 API 抓流其他软件也可以用标准协议从 go2rtc 取流。这套架构的好处是“下游解耦”。以前如果 Home Assistant 要接入摄像头只能靠 HA 自带组件去猜摄像头的协议现在所有摄像头都统一由 go2rtc 暴露成标准地址下游软件只需要认一套规则。哪怕以后换了一台摄像头也只改 go2rtc 配置下游全部不用动。对于喜欢折腾智能家居的人这一点能省下大量重复劳动。2. 环境准备与容器创建2.1 硬件门槛低但网络规划要提前想go2rtc 本身很轻量CPU 占用主要来自转码单纯做协议路由时内存占用通常只有几十兆。我在四核的 NAS 上跑 go2rtc 加 Home Assistant几乎感受不到额外负载。如果你只有树莓派 3B 或者一台小主机也完全够用。唯一要注意的是摄像头和 go2rtc 之间的网络链路要稳定。我这里吃过一次亏摄像头通过 Wi-Fi 接入信号稍差就频繁断流换成有线之后稳定多了。家庭环境改动布线不方便的话至少给摄像头设置 DHCP 固定 IP避免地址漂移导致 go2rtc 配置失效。如果把树莓派摄像头或者 USB 摄像头交给 go2rtc 容器去读还要额外考虑设备映射的问题。Docker 容器默认看不到宿主机的/dev/video0需要在启动参数里手动把设备节点透传进去。这也是为什么我不建议在 Docker Desktop 上玩本地摄像头——macOS 和 Windows 的虚拟化层对宿主机设备透传支持很别扭真接了也会出各种权限问题。2.2 docker-compose 快速启动一份最小可跑配置我建议直接用 docker-compose 管 go2rtc后续更新镜像、重启服务都方便。这是我当时最先验证通过的一份配置services: go2rtc: image: alexxit/go2rtc:latest container_name: go2rtc restart: unless-stopped network_mode: host volumes: - ./go2rtc.yaml:/config/go2rtc.yaml - ./recordings:/recordings启动命令只有一句docker compose up -d镜像源如果不方便可以先去 go2rtc 官方仓库确认当前可用的镜像地址后缀:latest会跟随版本更新。network_mode: host是 Linux 宿主机上的推荐写法这样容器直接共享宿主机的网络栈端口监听、WebRTC 的 UDP 通道都不需要额外映射性能损耗也最小。2.3 host 网络模式与 bridge 模式怎么选很多第一次用 Docker 的人会习惯性写ports: - 1984:1984这在 bridge 模式下没问题但 go2rtc 的 WebRTC 功能会有点尴尬。WebRTC 不只是走一个固定的 TCP 端口它还要协商 UDP 通道容器模式下要映射一长串 UDP 端口才能正常工作。我实测下来直接在 Linux 上用 host 网络模式最省心一个端口都不用映射容器启动就能访问http://宿主机IP:1984。如果你坚持用 bridge 模式那么至少要把 1984 端口的 TCP 和 UDP 都映射出去同时还要准备一段 UDP 端口范围来配合 WebRTC。但这样一来配置复杂度就上去了排查问题也麻烦。所以我的建议是能在 Linux 物理机或虚拟机上跑就优先用 host只有 Docker Desktop 这类受限环境才退而求其次用 bridge。3. 多协议接入实操与配置3.1 在 go2rtc.yaml 里添加第一路摄像头go2rtc 的配置路径/config/go2rtc.yaml核心配置项就是streams。这个段落定义所有输入流每一个摄像头都是一个键值对键名是你起的流名称值是一个列表里面写取流地址。最简单的海康摄像头配置长这样streams: front_door: - rtsp://admin:your_password192.168.1.64:554/Streaming/Channels/101保存文件后重启容器docker restart go2rtc之后打开http://IP:1984就能在页面上看到front_door这一路画面。你可以在 Web UI 里点开它测试延迟和清晰度。如果你的摄像头不止一路码流海康默认路径里Channels/101是主码流Channels/102是子码流。监看场景我一般建议用子码流清晰度够看带宽和解码压力都小很多。3.2 不同品牌 RTSP 地址的常用格式可能你已经遇到“同样都是摄像头RTSP 地址完全不一样”的问题。我整理了我实际用过的几种常见地址格式供你参考品牌或场景RTSP 地址风格海康威视rtsp://user:passIP:554/Streaming/Channels/101大华rtsp://user:passIP:554/cam/realmonitor?channel1subtype0TP-Link 等rtsp://user:passIP:554/stream1小米支持 RTSP 的型号rtsp://user:passIP:554/stream1树莓派 CSI 摄像头不走 RTSP用ffmpeg:video/dev/video0这些地址并不是绝对标准有些摄像头固件版本不同路径也会有差异。最靠谱的确认方式是在电脑上用 VLC 拉一下这个 RTSP 地址VLC 能出画面再往 go2rtc 里填。如果 VLC 都打不开先排查摄像头端的 RTSP 开关、账号密码和网络连通性不要急着怀疑 go2rtc 配错了。3.3 非 RTSP 协议的流怎么接入很多摄像头和网络直播源不是 RTSP 协议有的直接给一个 RTMP 推流地址有的给一个 HTTP-FLV 地址。go2rtc 对这类地址也很友好直接写在 streams 里就行它会自动识别streams: living_room: - rtmp://192.168.1.88/live/cam1 back_yard: - http://192.168.1.99:8000/live/stream.flv如果遇到那种比较怪的非标协议go2rtc 还可以通过ffmpeg:前缀调用内部的 FFmpeg 能力。比如某些 USB 摄像头或者采集卡输出的原始视频流可以直接用 FFmpeg 转成 H.264 后进入 go2rtc。这种写法相当于把 go2rtc 当成 FFmpeg 的前端控制台配置文件里写清楚输入和参数就行比单独跑 FFmpeg 进程要干净。3.4 树莓派 OV5647 摄像头模块接入树莓派摄像头模块 OV5647 是很多人折腾家庭监控的第一步但它接入 go2rtc 的方式跟网络摄像头完全不同。它不产生 RTSP 流而是直接暴露成 Linux 下的/dev/video0设备节点需要借助 FFmpeg 读取并编码。go2rtc 里的配置可以这样写streams: pi_cam: - ffmpeg:video/dev/video0#videoh264#audio0这里#videoh264的意思是强制输出 H.264 编码方便浏览器直接播放。容器启动时需要把设备节点透传进去否则容器里看不到/dev/video0。对应的 docker-compose 要在服务里加上设备映射services: go2rtc: image: alexxit/go2rtc:latest network_mode: host devices: - /dev/video0:/dev/video0 privileged: trueprivileged: true不是必须的但某些树莓派摄像头驱动对权限要求比较敏感加上可以少走弯路。启动后如果日志里报权限错误优先检查宿主机/dev/video0是否属于当前用户或video组必要时在 compose 里加group_add和宿主机对应组 ID。3.5 小米摄像头这类特殊设备的接入思路小米摄像头能不能接入 go2rtc核心问题不是 go2rtc 支不支持而是小米设备有没有把 RTSP 流放出来。部分型号在米家 App 里有一个“局域网 RTSP 协议”开关打开之后会生成一组独立账号密码然后在局域网里就能用它提供的地址取流。拿到地址后正常填进 go2rtc 的 streams 配置即可streams: mi_cam: - rtsp://mi_user:mi_pass192.168.1.101:554/stream1如果设备型号没有这个开关go2rtc 也确实无能为力因为它没法凭空让厂商开放私有协议。这时候可以继续用米家 App 看画面或者考虑在设备支持 ONVIF 的前提下用 ONVIF 方式接入但我这里不做强求。总之一句话go2rtc 能把“已经存在的流”接得好但不能凭空创造流。4. 低延迟播放与对外分发配置4.1 自带的 Web UI 比想象中好用go2rtc 启动后直接访问http://IP:1984就是它的 Web UI。页面非常朴素左边是 stream 列表点开就能播放。很多第一次用的人可能觉得它太简陋但真正方便的是它把每一路流的各种播放地址都给你列出来了复制链接给别的设备就能播。Web UI 还支持临时添加 stream不用改配置文件就能快速测试一个摄像头地址能不能用。我在排查故障时经常先在这里填一个地址试播确认没问题再写进 yaml 文件。注意 Web UI 里的配置是临时的重启容器后不会保留正式接入一定要落到go2rtc.yaml里。4.2 WebRTC 输出浏览器端低延迟的核心go2rtc 在智能家居圈子里被推崇很大一部分原因是它把 WebRTC 这件事做得很顺。WebRTC 可以在浏览器里实现亚秒级延迟播放不需要额外装插件这比传统 HLS 动辄几秒延迟体验好太多。为了把 WebRTC 跑稳容器网络模式我仍然推荐 host。因为 WebRTC 协商时要用到 UDP 端口如果是 bridge 模式下不定向暴露一堆 UDP 端口播放就会失败或者频繁卡住。用 host 模式之后浏览器打开 Web UI点击某一摄像头默认播放方式就是 WebRTC。局域网环境下画面从摄像头采集到浏览器显示的延迟通常在 0.2 到 0.5 秒看门口摄像头、看孩子房间这种对实时性要求高的场景这个延迟完全可用。4.3 输出成 HLS、HTTP-FLV 或 RTSP 给其他系统go2rtc 不只是给自己页面用它本身就是一台小型流媒体服务器可以对外输出标准协议。每一路 stream 都会自动对应几个播放地址比如我有一路摄像头叫front_door那么它会有类似下面的地址输出协议示例地址HLShttp://IP:1984/api/hls/front_door.m3u8HTTP-FLVhttp://IP:1984/api/stream/front_door.flvRTSPrtsp://IP:1984/front_doorWebRTCwebrtc://IP:1984/front_door这些地址可以直接接到任意播放器、Home Assistant、Frigate 或者录像软件里。Home Assistant 里想要接摄像头通常会给一个stream_source地址填入 go2rtc 的 RTSP 输出地址就能解决。Frigate 之类的识别软件也支持用 RTSP 取流这样 go2rtc 就成了所有下游服务的统一数据源。4.4 把流推送到其他流媒体服务除了让人来拉流go2rtc 还可以主动推流。假如你已经有一个 Nginx-RTMP 服务或者 SRS 服务想把这些摄像头统一推上去做直播只要在 stream 的列表里追加一条目标推流地址go2rtc 就会同时把流推过去streams: front_door: - rtsp://admin:pass192.168.1.64:554/Streaming/Channels/101 - rtmp://192.168.1.10:1935/live/front_door注意这里不是转码再推而更像是“复制一份流出去”所以对 CPU 的额外消耗很小。如果你希望推送前转成更低码率仍然要靠ffmpeg:前缀加转码参数。这个功能特别适合那种“摄像头在 A 局域网直播服务器在 B 局域网”的跨网段场景前置一台 go2rtc 做汇聚再统一上行。4.5 抓拍快照接口除了视频流go2rtc 还提供了一个很实用的抓帧接口格式是http://IP:1984/api/frame?srcfront_door这个接口会返回当前一帧 JPEG 图片适合做智能家居联动。我在实际项目中用这个接口做过简单的人体检测联动检测到有人移动的时候主动去抓一张当前画面推送到手机通知里。相比一直拉视频流分析抓拍单帧的负载低很多。不过要注意每次调用接口是实时去抓的如果摄像头刚好断流返回会失败做好重试逻辑就好。5. 常见问题与排查技巧实录5.1 H.265 摄像头在浏览器里黑屏或花屏家庭摄像头里 H.265 编码越来越常见但浏览器原生解码并不支持 H.265哪怕 Chrome、Edge 这些主流浏览器也不行。所以当你用 Web UI 打开某一路摄像头出现黑屏、花屏而 VLC 播同样的地址却正常时九成是编码问题。解决办法是让 go2rtc 在输出前转成 H.264。可以在输入地址后面加参数streams: living_room: - rtsp://admin:pass192.168.1.64:554/Streaming/Channels/101#videoh264这个写法会让 go2rtc 在需要时调用 FFmpeg 转码。代价是 CPU 占用会上去如果有多路 H.265 摄像头同时看建议给 go2rtc 所在的机器稍微“加鸡腿”或者干脆在摄像头端把子码流切换成 H.264 编码再接入。5.2 密码含特殊字符导致一直认证失败RTSP 地址的用户名密码要拼进 URL 里如果密码里有、:、/这类字符直接写上去轻则认证失败重则整个 URL 解析错误。我踩过最典型的是密码里带看起来地址没问题结果 go2rtc 一直在报 401 认证失败。后来才意识到需要做 URL 编码比如密码是admin123地址要写成rtsp://admin:admin%40123192.168.1.64:554/Streaming/Channels/101遇到其他特殊字符同理可以去查一下 URL 编码表把换成%40把:换成%3A。这个事情虽然小但排查起来特别浪费时间。5.3 容器访问不了 /dev/video0本地摄像头接入容器时常见两个错一个是找不到/dev/video0一个是Permission denied。前者通常是 compose 里没有配置devices映射后者往往是容器内用户权限不够。我处理树莓派摄像头时的最终 compose 片段是devices: - /dev/video0:/dev/video0 privileged: true如果这样还报权限问题就去宿主机执行ls -l /dev/video0看看它是属于video组还是某个用户然后在 compose 里用group_add把视频组加进去。总之本地摄像头接入的坑基本都在系统权限这层和 go2rtc 本身关系不大。5.4 摄像头断流后 go2rtc 不自动恢复go2rtc 对摄像头断流的处理在多数场景下是“按需重连”但如果你发现某一路摄像头在断网恢复后长时间不出画面需要先确认摄像头 IP 有没有变。很多路由器 DHCP 租约短摄像头重启后就换了地址go2rtc 里还是旧地址自然连不上。我给所有摄像头都做了静态 IP 绑定之后这类问题基本消失了。另外如果摄像头固件本身有休眠策略长时间没有拉流会自动断开下次访问时第一次会比较慢。这种问题可以尝试在 stream 地址后面加#videocopy#audiocopy等参数强制 go2rtc 保持一个最小唤醒机制但最终方案还是要调整摄像头侧的休眠设置。5.5 防火墙和端口访问问题容器里服务已跑起来但从另一台电脑访问不了http://IP:1984这多半是防火墙拦了 TCP 1984 端口。Linux 上先检查firewalld或ufw是否放行该端口。如果你要用 WebRTC 播放还需要放行对应的 UDP 端口。用 host 模式时go2rtc 会按需监听 UDP 端口最省事的方法是直接放行整个 lo 网卡和本地子网的 UDP 通信或者根据 go2rtc 日志里显示的监听端口单独放行。5.6 不要轻易把 1984 端口暴露到公网go2rtc 默认没有身份认证任何能访问到这个端口的人都能看到你所有的摄像头画面。我见过有人图方便把 1984 端口映射到公网结果被扫描工具发现画面直接被人看到了。如果确实需要远程看摄像头建议只在局域网内使用 go2rtc远程访问请通过正规的加密通道或路由器厂商提供的安全方案实现不要裸奔。5.7 改配置文件后不生效go2rtc 会在容器启动时读取/config/go2rtc.yaml但我不建议只改文件不重启。虽然部分版本支持自动重载但为了保险每改一次配置都执行docker restart go2rtc让新配置干净生效。如果你在 Web UI 里临时加过流重启后临时配置会消失别到时候以为配置丢了。6. 写在最后一点个人体会6.1 我最终采用的推荐组合如果你跟我一样是普通家庭用户我建议不要指望 go2rtc 一个软件解决所有问题。它最适合做的是“流媒体中枢”把多协议摄像头统一暴露成标准地址。录像和检测尽量交给更专业的系统。我目前实际跑下来的组合是go2rtc 负责接入海康、小米和树莓派摄像头Home Assistant 负责联动和告警Frigate 负责录像和移动检测。三个服务全部用 Docker 部署在 NAS 上互不干扰数据流全部通过 go2rtc 这一层中转整体非常清爽。6.2 如果你打算长期使用长期使用的话第一是给 go2rtc 容器配置自动重启也就是 compose 里的restart: unless-stopped否则 NAS 一重启摄像头就全瞎了。第二是定期备份go2rtc.yaml这个文件就是所有接入设备的“地图”丢了它等于重新接一遍线。第三是更新镜像前先看一眼新版本 changeloggo2rtc 迭代速度不慢偶尔会有配置格式调整先小范围验证再全量升级会更稳。6.3 给新手的最后一条经验我实际折腾下来最深的体会是先去弄一台“好接入”的摄像头跑通全流程再慢慢把不配合的设备加上去。开始就把小米、树莓派、海康全塞进去一旦出问题你根本分不清是 go2rtc 的问题、网络的问题还是摄像头协议的问题。先让一路 RTSP 摄像头在 Web UI 里正常播放再把复杂度逐步加上去这套流程能帮你省下大量排查时间。go2rtc 本身够轻Docker 部署也够简单真正需要耐心的是理解每一路流的来源和协议特性。把这一步想明白后面基本就是一马平川了。
上一篇/下一篇内容由系统自动关联 返回资讯列表 →