基于Docker部署go2rtc:打通RTSP/RTMP/WebRTC多协议摄像头接入

发布时间:2026/9/20 6:45:48
基于Docker部署go2rtc:打通RTSP/RTMP/WebRTC多协议摄像头接入 玩摄像头久了几乎都会遇到同一个问题家里、工作室、公司园区里的设备五花八门海康、大华、小米、TP-Link、杂牌 IPC有的走 RTSP有的只能吐 RTMP 或 MJPEG还有的干脆是 HLS 直播地址。手里一堆链接想在浏览器里随时看浏览器又不原生支持 RTSP装 VLC 也就算了想接到自己的平台、App、Home Assistant 里统一预览更是折腾。后来我换成了 go2rtc这个问题基本就终结了。它用 Go 写的单二进制就能跑专治各种协议不互通把 RTSP、RTMP、HLS、MJPEG、WebRTC 全部揉在一起对外统一输出。再用 Docker 一包配置写在 yaml 里几行搞定重启不丢配置迁移也方便。这篇文章就基于我的实操经历从部署、配置、协议接入、播放测试到问题排查完整过一遍这套基于 Docker 的 go2rtc 多协议流媒体平台搭建过程。不管你是刚接触自建监控还是想把现有摄像头体系盘活都可以直接照着抄。1. go2rtc 是什么为什么摄像头接入这么麻烦1.1 摄像头协议分裂的现状与核心痛点说 go2rtc 之前得先理解摄像头接入为什么让人头大。IPC 摄像头行业虽然发展了这么多年协议层面却一直很分裂。主流的接入方式大概是这几类RTSP大部分专业安防品牌和网络摄像头都支持比如海康、大华、TP-Link 的不少型号默认端口 554。但每个厂家的 RTSP 路径长得都不一样有的叫/h264/ch1/main/av_stream有的叫/Streaming/Channels/101甚至同品牌不同型号还有差异。RTMP很多国产云台摄像头、直播类设备首选端口常见 1935路径通常是/live/stream这种。HLS云摄像头、纯网络平台输出用的多最典型的就是http://ip/live/xxx.m3u8这种地址延迟几秒起步胜在兼容性好。MJPEG古董级摄像头和一部分 USB 摄像头会提供http://ip/video.cgi这种裸 MJPG 流几乎所有浏览器都能看但帧率和体积感人。私有协议小米、萤石这类带云服务的品牌虽然底层也是 RTSP但官方常常不直接给你地址要自己在 App 里打开“局域网协议”开关或者用 ONVIF 去探测。问题就来了你手上有 5 个摄像头可能就有 3 种协议、5 种网址格式。有些能 VLC 看有些只能在网页里看有些只能用厂商 App 看。如果要做一个统一的监控页面或者接到自己写的后端里就得自己写代码去适配每一种协议、处理底层解码和推流这个工作量非常大而且视频流这东西UDP 丢包、TCP 阻塞、时间戳错乱每一样都够折腾一阵。1.2 go2rtc 的工作原理与设计理念go2rtc 的思路很直接你只需要把每一路摄像头源写在配置文件里它负责按需往对应的摄像头拉流然后对外统一提供多种访问协议。它拉流是“按需”的不是把所有流都常驻拉进来这点对 CPU 和带宽非常友好。它的核心处理流程说白了就是“源协议进、目标协议出”上游是 RTSP 也行、RTMP 也行、HLS 也行输出端可以是 WebRTC、HLS、MSE、RTSP、RTMP、MP4 文件随便挑。它内部有转发和转码两条链路。能直接转发的协议就尽量转发不改编码、不重编码消耗极低遇到浏览器播放不了的情况再调用内置的 FFmpeg 做一次转码。这里最值得关注的其实是 WebRTC。传统 RTSP 摄像头没法直接在浏览器里播放HLS 延迟又高拉流播放总是好几秒。go2rtc 利用 WebRTC 把视频包通过 UDP 直接推给浏览器延迟能压到 0.2 到 0.5 秒左右差不多是实时看监控的体验。这个能力是 go2rtc 相比很多传统转流服务的核心竞争力。1.3 它和 ZLMediaKit、MediaMTX、FFmpeg 工具链的区别很多接触过流媒体的人会问用 FFmpeg 自己转流不就行了为什么还要上 go2rtc说实话FFmpeg 命令行确实能做单路转推但那只是“一次性任务”每增加一个客户端、每增加一路摄像头都要手动起进程、维护端口、做鉴权长期用非常痛苦。ZLMediaKit、MediaMTX 这类流媒体服务可以做统一收流和分发但部署重、配置复杂对普通玩家来说更像是一个正规军武器用来搞大规模商业场景没问题自己家里看几路监控就有点杀鸡用牛刀了。go2rtc 的定位更像是轻量全能中转站部署成本极低、配置简单、自带 Web 界面和 API而且它明显是为 Home Assistant 生态设计的和智能家居联动非常方便很适合个人用户、家庭监控、中小型工作室的场景。一句话总结FFmpeg 是工具ZLMediaKit 是平台go2rtc 是“即插即用”的中转节点。2. Docker 部署前的准备与镜像拉取2.1 部署前需要确定的环境开始部署前建议先把下面的信息理一遍省得装到一半才发现网络或目录不对。运行环境一台能跑 Docker 的机器即可可以是群晖/威联通 NAS也可以是家里的旧电脑、云服务器甚至树莓派。go2rtc 本身很轻内存占用低的时候只有几十 MB对硬件没有要求但如果你有大量摄像头需要转码建议给 CPU 留点余量。Docker 版本Docker 20.10 以上基本都行不需要特殊内核模块。Windows 上用 Docker DesktopLinux 上直接用 docker enginemacOS 也一样。注意不要用特别古老的版本拉镜像、挂载卷、端口映射这些基础功能稳定就好。端口规划go2rtc 默认 Web 管理界面和 API 都在 1984 端口WebRTC 相关的端口默认是 8555TCP 和 UDP。如果 1984 被占了Docker 映射时改成如 8084:1984 就行。需要 UDP 8555 这个端口能被访问到否则 WebRTC 的媒体协商和数据传输会出问题。目录规划准备一个专门放配置的目录我习惯放在/data/go2rtc/config下面里面就放一个 go2rtc.yaml 文件。容器内统一挂载到/config这样以后升级镜像配置不会丢。2.2 拉取官方镜像与加速配置go2rtc 的镜像名是alexxit/go2rtc这是项目作者自己维护的跟着 GitHub 主仓库持续构建。拉取命令很简单docker pull alexxit/go2rtc在国内网络环境下有些用户会遇到镜像拉取慢、超时的情况。这通常不是 go2rtc 的问题而是 Docker Hub 的默认源访问不畅。可以在 Docker 的 daemon.json 里配置 registry-mirrors 来走加速源。修改配置文件之后一定要重启 Docker 服务和容器这个很关键。配置大致这样{ registry-mirrors: [https://docker.mirrors.example.com] }至于具体填哪个加速地址不同地区的网络情况差别很大我不做统一推荐你可以结合自己实际能访问的加速源来配置。如果不想折腾加速也可以从 GitHub Packages 拉取ghcr.io/alexxit/go2rtc这个镜像地址两条路二选一。2.3 最简部署一条 docker run 命令不想写复杂配置的话直接用 docker run 也能跑起来。先看看最快能跑通的样子docker run -d --name go2rtc \ --restart unless-stopped \ -p 1984:1984 \ -p 8555:8555/tcp \ -p 8555:8555/udp \ -v /data/go2rtc/config:/config \ alexxit/go2rtc这里每个参数都值得说一句-d --name go2rtc后台运行名字叫 go2rtc。--restart unless-stopped容器挂了或者机器重启之后自动拉起除非你手动停止否则它不会死。-p 1984:1984把容器里的 Web/API 接口映射到宿主机。-p 8555:8555/udpWebRTC 的媒体通道走的是 UDP记得把 UDP 也映射出来。这个特别容易被漏掉漏了之后浏览器画面能出但经常会卡顿或连接失败。-v /data/go2rtc/config:/config配置目录挂载。第一次启动后浏览器访问http://你的IP:1984看到 go2rtc 自带的 Web 界面就说明跑起来了。这时候页面里没有流因为配置文件还没写界面上有一个输入框可以临时测试拉流地址这个我们后面再说。3. docker-compose 完整部署与目录规划3.1 为什么更推荐 docker-composedocker run 适合快速验证但真正长期使用我更推荐用 docker-compose。原因很简单run 命令一长串升级的时候容易记混而 compose 文件把镜像、端口、卷、重启策略、环境变量全部固化下来放在项目目录里团队协作或换机器部署时一条docker compose up -d就能还原整套环境。版本兼容性方面新的 Docker 版本已经直接用docker compose子命令老的 compose 也可以继续用docker-compose二者区别不大。3.2 docker-compose.yml 逐段解析我的 go2rtc 部署目录大概是这样的/data/go2rtc/ ├── docker-compose.yml └── config/ └── go2rtc.yamldocker-compose.yml 内容如下version: 3.8 services: go2rtc: image: alexxit/go2rtc:latest container_name: go2rtc restart: unless-stopped ports: - 1984:1984 # Web 管理界面 / API - 8555:8555/tcp # WebRTC 信令辅助 - 8555:8555/udp # WebRTC 媒体通道 volumes: - ./config:/config environment: - TZAsia/Shanghai # 日志时间按本地时区显示 logging: driver: json-file options: max-size: 10m max-file: 3这个配置里有几个细节restart: unless-stopped是家庭服务器、NAS 场景的首选。机器重启后容器只要没被手动 stop就会自动拉起。./config:/config用的是相对路径要求你创建这个目录后再cd进去执行 compose 命令。如果你有强迫症写成绝对路径/data/go2rtc/config:/config也可以。TZAsia/Shanghai保证容器内日志时间不是 UTC查日志的时候不会差 8 小时。logging里给日志加上轮转防止跑几个月之后日志把磁盘塞满。这个对长期运行的项目很重要。然后启动cd /data/go2rtc docker compose up -d查看状态和日志docker ps docker logs -f go2rtc看到日志里出现api listening on :1984之类的信息就代表启动成功了。3.3 配置文件与容器内路径的对应关系go2rtc 兼容两种配置文件后缀新版本推荐用go2rtc.yaml旧版本习惯写go2rtc.conf实际内容都是 YAML 格式。挂载到/config后容器会自动去/config找配置文件。需要注意如果你改完配置想让 go2rtc 重新加载不一定非要重启容器。Web 界面上有一个“Reload”按钮点击后会重新读取配置不断开现有连接这个体验很省心。如果是大改、改了 API 鉴权这类配置保险起见就直接docker restart go2rtc。4. 摄像头多协议接入的配置实战4.1 config 文件基本结构go2rtc 的配置文件核心就是streams字段它定义“哪些流叫什么名字、去哪里拉流”。一个最基础的配置长这样streams: front_door: rtsp://admin:password192.168.1.108:554/h264/ch1/main/av_stream backyard: rtsp://admin:password192.168.1.109:554/Streaming/Channels/101 living_room_mjpeg: http://192.168.1.110/video.cgi media_server: rtmp://192.168.1.120:1935/live/stream每一行的格式都是流名称: 流地址。流名称建议用英文和下划线后面在播放地址里会用到比如http://IP:1984/api/webrtc?srcfront_door。如果源地址带有用户名密码直接嵌在 URL 里注意密码里如果有特殊字符要先把、:、#、空格这类字符做 URL 编码比如编码成%40不然解析会出问题。4.2 不同协议摄像头源的接入写法不同品牌、不同协议在 go2rtc 里的写法差别不大本质上就是把能拉流的地址填进去。但有几个典型场景值得单独记录RTSP 摄像头绝大多数专业摄像头都用这种。常见写法streams: cam1: rtsp://user:pass192.168.1.64:554/stream1如果走的 UDP 传输不稳定或者画面经常卡顿可以在地址后面加 TCP 参数强制走 TCP 通道streams: cam1: rtsp://user:pass192.168.1.64:554/stream1?tcp我自己实测下来局域网内大部分摄像头走 TCP 反而更稳定尤其是无线摄像头UDP 丢包会导致花屏、卡顿。RTMP 推流源很多直播摄像头、编码器支持 RTMP 输出。go2rtc 直接支持streams: live_encoder: rtmp://192.168.1.50:1935/live/camHLS 直播地址如果你手上的源本身就是一个 m3u8 地址比如一些云平台的直播流go2rtc 也能直接拉streams: cloud_cam: http://example.com/live/stream.m3u8MJPEG 源老摄像头或者 USB 摄像头常见streams: old_cam: http://192.168.1.88:8080/video.cgi“不知道是什么协议”的源go2rtc 支持在源地址前加一个ffmpeg:前缀强制用 FFmpeg 进程去拉流。这个方法适合那些协议不标准、RTSP 解析失败或者需要额外转码的源streams: weird_cam: ffmpeg:rtsp://user:pass192.168.1.123:554/live加了前缀之后go2rtc 会调起内置的 FFmpeg 去建立连接把源处理成标准流再给 go2rtc 转发。代价是多一次进程开销但兼容性确实好很多。4.3 常见品牌摄像头的 RTSP 地址参考很多新手卡在“不知道摄像头 RTSP 地址到底填什么”。我整理了常见的几个品牌参考覆盖大多数家用和半专业设备品牌常见 RTSP 地址模式海康威视rtsp://user:passIP:554/h264/ch1/main/av_stream大华rtsp://user:passIP:554/cam/realmonitor?channel1subtype0TP-Linkrtsp://user:passIP:554/stream1小米rtsp://user:passIP:554/ch0_0.h264部分型号需在米家开启局域网协议萤石rtsp://user:passIP:554/h264/ch1/main/av_stream需要说明两点。第一同一品牌的固件版本不同地址可能完全不同这个表只能作为起步参考。第二很多家用摄像头默认关闭 RTSP 服务需要先去厂商 App 里找到“局域网 RTSP”、“ONVIF 开关”之类的选项打开然后再去探测地址。如果实在找不到建议按摄像头 IP 段扫描一下比如用 ONVIF Device Manager 这类工具批量探测支持的流地址能省不少事。4.4 用 FFmpeg 转码解决 H.265 / 格式不兼容现在很多摄像头默认主码流是 H.265/HEVC 编码画质好、码率低但问题在于浏览器原生是不支持 H.265 直接播放的至少 Chrome、Firefox 都不行。你通过 WebRTC 拉流结果显示黑屏或者无法解码大概率就是编码格式问题。go2rtc 解决这个问题的思路是要么改编码格式要么转码。改编码格式的方法是在 RTSP 地址后面加#videoh264这样的过滤器让摄像头输出 H.264 编码streams: cam_h265: rtsp://user:passIP:554/stream1#videoh264这个方案的原理是go2rtc 会尝试通过 RTSP 的编码参数协商要求摄像头以 H.264 格式输出。部分摄像头支持部分不支持所以它不是万能的。如果摄像头不支持改编码就只能硬转码了也就是强制走 ffmpeg 通道streams: cam_h265: ffmpeg:rtsp://user:passIP:554/stream1#videoh264这个#videoh264在 ffmpeg 模式下会作为 FFmpeg 的输出编码参数把 H.265 源转成 H.264 再交给 go2rtc。代价是 CPU 占用会上去我实测一路 1080P H.265 转 H.264普通 x86 平台大概占 10% 到 20% 的单核资源低功耗 ARM 设备可能更吃力所以没必要时不建议每路都转。5. 多协议播放从 WebRTC 到 HLS 的完整链路5.1 WebRTC 低延迟播放实测视频秒开go2rtc 部署完成的最高光时刻就是在浏览器里直接看到摄像头的实时画面而且延迟低到几乎无法察觉。go2rtc 的 Web 页面http://IP:1984会把配置文件里所有流都列出来点击任意一个流它会默认通过 WebRTC 协议播放。播放页面上显示的延迟我实测局域网环境下通常在 0.2 到 0.5 秒之间基本就是“摄像头拍到手、屏幕立刻显示”的效果非常适合看猫、看门、看打印机这种需要实时交互的场景。如果自己写页面或者用第三方前端WebRTC 播放的 API 地址是http://IP:1984/api/webrtc?srcfront_door前端通过 RTCPeerConnection 和 go2rtc 做 SDP 协商go2rtc 负责把摄像头源转成 WebRTC 需要的 RTP 包直接推到浏览器。这整个链路不需要你写任何服务端推流代码go2rtc 全包了。5.2 用 VLC、ffplay、HLS 兼容其他播放端WebRTC 虽然体验好但并不是所有场景都适合。比如你要在电视盒子、手机原生播放器、老终端上看或者要拿给不支持 WebRTC 的程序消费那就得用其他协议。go2rtc 支持把同一路流同时以多种协议输出不需要额外配置直接拼 URL 就行RTSP 转发播放rtsp://IP:1984/front_door可以直接用 VLC、ffplay 打开。HLS 播放http://IP:1984/api/hls?srcfront_door适合 iPhone 自带播放器、网页 Video 标签。MSE 播放http://IP:1984/api/mse?srcfront_door适合浏览器里用 MSE 方式播放兼容性更好。MP4 录像回放http://IP:1984/api/stream.mp4?srcfront_door适合临时录像。我常用的临时验证方法是ffplay -rtsp_transport tcp rtsp://127.0.0.1:1984/front_door这样一条命令就能确认 go2rtc 转发链路是否正常。如果这条能出画面说明源和 go2rtc 之间没问题剩下的只是在浏览器端选择合适协议。5.3 多路同时预览与 API 接口把好几个摄像头一起放到同一个页面里预览是监控场景的刚需。go2rtc 的 Web 界面本身就支持多路同时打开每个画面一个独立窗口可以用 MSE 方式多开。如果你要自己做一个监控面板可以直接调用 go2rtc 的 JSON API 获取流列表和状态信息curl http://IP:1984/api/streams返回结果是一个 JSON包含所有已配置和已连接的流以及当前的转发状态、客户端数等。有了这些数据你可以很容易在自建页面里做一个动态的摄像头列表再配合 WebRTC 播放器和 HLS 回退基本就是一个完整的自建监控平台了。6. 常见问题与排查技巧实录6.1 容器启动失败、反复重启出现这种情况先用一句话定位问题docker logs go2rtc如果日志里显示yaml: line X: mapping values are not allowed那就是配置文件里有语法错误比如冒号后面没加空格、缩进不统一。YAML 对缩进非常敏感这个只能仔细检查。如果日志显示bind: address already in use说明 1984 端口被宿主机上的其他程序占用了换一个宿主机映射端口即可比如-p 1985:1984。6.2 画面黑屏或一直 loading黑屏大概率是编码格式不兼容优先检查摄像头的主码流是不是 H.265。可以临时加一个ffmpeg:前缀做转码或者让摄像头把主码流切到 H.264。另一个常见原因是浏览器放不了 WebRTC 需要的媒体格式这时候可以先临时改用 MSE 播放如果 MSE 能出画面基本就是 WebRTC 协商或网络层面的问题。还有一种情况是摄像头源本身拉不通但配置没报错。这种建议先打开http://IP:1984/api/streams看流的状态如果显示连接错误多半是用户名密码、RTSP 路径不对或者摄像头没有开启局域网访问。也可以直接在 Web 界面的输入框里粘贴原始流地址测试go2rtc 会返回拉流是否成功非常直观。6.3 延迟高、画面卡顿延迟高先区分是哪种播放方式。如果用 HLS自带几秒延迟是物理特性不是 go2rtc 的问题。要低延迟就切 WebRTC。如果 WebRTC 还是卡重点检查网络和摄像头码流摄像头码流太大建议用子码流做实时预览主码流只用来录像。RTSP 默认 UDP 传输局域网内如果丢包率偏高在地址后面加?tcp强制走 TCP。确认容器的 UDP 8555 端口映射了且宿主机防火墙放行了 UDP。WebRTC 的媒体数据走 UDP映射少了画面会断断续续或者干脆出不来。6.4 暴露公网时的鉴权与安全go2rtc 的 Web 界面默认没有任何鉴权谁拿到 IP 端口就能看你的摄像头。如果只在内网使用问题不大但如果要远程访问不建议直接把 1984 端口裸暴露到公网。有两个更稳的选择一是给 go2rtc 的 API 加上用户名密码在配置里增加api: listen: :1984 username: admin password: 改成强密码二是用带身份认证的反向代理比如 Nginx 或 Caddy把 Web 和 API 路径走 HTTPS Basic Auth甚至只暴露 Tailscale 虚拟局域网内的地址。我自己就是三层防护内网直接用外网走带鉴权的反代摄像头本身再用 VLAN 隔离这样基本就不担心隐私泄露的问题了。6.5 与 Home Assistant 等智能家居平台联动如果你家里装了 Home Assistantgo2rtc 几乎是无缝接入的。Home Assistant 的 Stream 组件本身支持 go2rtc 作为默认流提供者配置好之后HA 里的摄像头实体可以直接调用 go2rtc 的流地址。最典型的用法是把海康的 RTSP 流接入 go2rtc然后 HA 里直接通过 go2rtc 的方式生成摄像头实体再配合自动化做有人检测、录像、推送到手机基本一套组合拳就能把厂家的云服务完全扔掉。我自己实际踩过几次坑之后最后的体会是go2rtc 这个项目理念非常克制它不追求做一个大而全的流媒体平台而是把所有协议转换的脏活累活都藏在背后让使用者只关心“源是什么、想用什么方式看”。Docker 又把这个过程变成了目录里一个几十行的 yaml 文件。你甚至可以把这个 compose 目录打包带走换一台机器docker compose up -d摄像头配置原样恢复。如果后面想继续扩展我建议可以从这几个方向入手给 go2rtc 配上强制转码缓存接入多路 4K 摄像头时显著降低重复拉流压力用断言 API 做流健康检查把断流自动重启的脚本接到容器里或者把 Web 界面放到自己的导航页里做成一个真正的家庭监控中心。这套基础打好了往上加东西会非常顺手。

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询