go2rtc 的 ONVIF 协议支持全解析:Profile 规范、设备接入与服务端实现
go2rtc 的 ONVIF 协议支持全解析Profile 规范、设备接入与服务端实现【免费下载链接】go2rtcUltimate camera streaming application项目地址: https://gitcode.com/GitHub_Trending/go/go2rtcgo2rtc 将 ONVIF开放网络视频接口论坛协议能力同时内置在客户端与服务端两个方向既能通过onvif://源自动探测摄像头、协商 RTSP 流地址也能把自己伪装成一个标准的 ONVIF 设备被 Home Assistant、ONVIF Device Manager 等第三方客户端直接发现与取流。本文以 pkg/onvif/README.md 为骨架结合仓库源码深入讲解 ONVIF Profiles 与 Services 标准、常见摄像头认证差异、onvif://配置方法以及 go2rtc 服务端实现的底层原理读完即可掌握在 go2rtc 中接入任意 ONVIF 摄像头、并让 go2rtc 反向暴露为 ONVIF 设备的完整方案。ONVIF 标准 Profiles四种能力档位ONVIF Profile 定义了设备必须实现的最小功能集合用于让客户端无需事先了解厂商差异即可按 Profile 名称判断设备能力。go2rtc 的 README 明确列出了四种常用 ProfileProfile定位核心能力Profile A访问控制门禁访问控制配置Profile C门禁控制与事件门控操作与事件管理Profile S基础视频流视频流与配置最常用Profile T高级视频流H.264 / H.265 视频压缩、成像设置、移动侦测与遮挡事件、元数据流、双向音频其中Profile T是当前消费级安防摄像头普遍支持的高级档位它把编码H.264/H.265、画质调节Imaging、报警事件Motion alarm / Tampering与双向语音都纳入了能力范围。go2rtc 服务端在向客户端暴露自身时会声明onvif://www.onvif.org/Profile/Streaming见 pkg/onvif/server.go 中GetScopesResponse的 Scope 定义即把自己归入 Streaming 类别。核心 Services三大 WSDL 端点ONVIF 设备能力通过 SOAP/XML 服务暴露go2rtc 依赖以下三个 WSDL 端点原 README 的 Services 章节https://www.onvif.org/ver10/device/wsdl/devicemgmt.wsdl # Device 设备管理 https://www.onvif.org/ver20/imaging/wsdl/imaging.wsdl # Imaging 成像控制 https://www.onvif.org/ver10/media/wsdl/media.wsdl # Media 媒体服务对应到源码中这三个服务在 pkg/onvif/client.go 的NewClient中被解析为三个独立的端点地址deviceURL默认http://host/onvif/device_service常量PathDevice用于GetCapabilities、GetDeviceInformation、GetSystemDateAndTime、GetScopes、GetNetworkInterfaces等设备管理操作mediaURL从GetCapabilities响应中通过正则Media.?XAddr提取默认回退/onvif/media_service用于GetProfiles、GetStreamUri、GetSnapshotUri等媒体操作imaginURL通过正则Imaging.?XAddr提取默认回退/onvif/imaging_service用于快照 URI 获取。客户端启动时会先发GetCapabilities探测设备FindTagValue用正则从 XML 响应中抓取 XAddr这套解析逻辑在 pkg/onvif/onvif_test.go 的TestGetCapabilities中针对大华Dahua的紧凑与格式化两种响应形态都有断言验证。ONVIF 客户端一行配置接入任意摄像头go2rtc 从 v1.5.0 起支持 ONVIF 客户端模式见 internal/onvif/README.md。如果你已经知道摄像头的 RTSP 地址和快照地址ONVIF 源并非必需但当你不知道这些地址时onvif://源会自动走完取能力 → 取 Profile → 协商 RTSP URI的完整流程。streams 配置示例streams: dahua1: onvif://admin:password192.168.1.123 reolink1: onvif://admin:password192.168.1.123:8000 tapo1: onvif://admin:password192.168.1.123:2020语法要点onvif://user:passhost[:port][/path]用户名密码会用于 SOAP 请求的 WSSE 认证端口按厂商默认给出大华默认80Reolink 默认8000TP-Link 默认2020且路径为/onvif/device_service若摄像头端点路径不是标准的/onvif/device_service可在 URL 中显式给出路径pkg/onvif/client.go 的GetPath会做兼容处理。子码流subtype与快照GetURIpkg/onvif/client.go支持两个查询参数?subtypeN按索引选择 Profile0 为主码流、1 为子码流索引越界会返回onvif: wrong subtype错误snapshot将操作切换为GetSnapshotUri返回快照 HTTP 地址而非 RTSP 地址。取回的 URI 会做html.UnescapeString解码很多摄像头把转义为amp;并自动补上 URL 中缺失的认证信息u.User nil c.url.User ! nil分支。整个解码逻辑在 pkg/onvif/onvif_test.go 的TestGetStreamUri中被覆盖测试数据包括大华、通用设备以及 go2rtc 自身作为服务端返回的 URI。WebUI 自动发现WebUI 的Add页面www/add.html内置 ONVIF 自动发现按钮点击后调用api/onvif其实现位于 internal/onvif/onvif.go 的apiOnvif。发现逻辑在 pkg/onvif/helpers.go 的DiscoveryStreamingDevices中向组播地址239.255.255.250:3702发送 WS-DiscoveryProbe报文等待 5 秒收集响应过滤不含onvif关键字的设备避免打印机等设备混入从XAddrs提取设备 URL并对http://0.0.0.0:8080/...这类异常地址做 IP 修正从Scopes解析设备名称name与硬件型号hardware拼装为onvif://user:passhost形式的源地址用户只需把占位的user:pass换成真实凭据即可。前提条件go2rtc 必须与摄像头处于同一子网使用 Docker 部署时必须采用host 网络模式否则组播发现报文无法到达摄像头。认证差异三厂商请求认证要求对照不同厂商对 ONVIF 各操作的认证策略并不一致go2rtc 实测整理如下原 README 的 TMP 章节操作DahuaReolinkTP-LinkGetCapabilitiesno authno authno authGetServicesno authno authno authGetServiceCapabilitiesno authno authauthGetSystemDateAndTimeno authno authno authGetNetworkInterfacesauthauthauthGetDeviceInformationauthauthauthGetProfilesauthauthauthGetScopesauthauthauth从中可以提炼出两个工程结论能力探测类请求Capabilities / Services / 时间三家都不强制认证因此 go2rtc 客户端可以匿名握手、凭据取流信息与媒体类请求网卡、设备信息、Profile、Scope三家全部要求认证因此onvif://源必须携带用户名密码。认证通过 SOAP Header 中的WSSE UsernameToken实现见 pkg/onvif/envelope.go 的NewEnvelopeWithUser使用随机 Nonce UTC 时间戳 密码做 SHA-1 摘要按PasswordDigest类型 Base64 编码放入wsse:Security头。这也是 go2rtc 能够兼容大华、Reolink、TP-Link 三家私有实现差异的关键——它对服务地址、URI 解码、WSSE 摘要都做了宽容处理。ONVIF 服务端go2rtc 反向伪装成 ONVIF 设备go2rtc 同时实现了 ONVIF 服务端。真实摄像头通常有一个视频源GetVideoSources和两个 ProfileGetProfiles而 go2rtc 的映射规则是每个 stream 对应一个视频源 一个 ProfileProfile 名称即 stream 名称见 internal/onvif/onvif.go 的onvifDeviceService。服务端注册在/onvif/路径下api.HandleFunc(/onvif/, onvifDeviceService)通过 pkg/onvif/server.go 的GetRequestAction从请求体正则提取 SOAP 操作名后分派GetCapabilities→ 声明 Device/Media 端点并声明仅支持RTP_RTSP_TCPTCP 传输GetDeviceInformation→ 返回Manufacturer / Modelgo2rtc / FirmwareVersion版本序列号取r.Host保证每个实例有唯一 IDHome Assistant 依赖该字段GetProfiles/GetVideoSources/GetVideoSourceConfigurations→ 用streams.GetAllNames()动态枚举当前所有 streamGetStreamUri→ 返回rtsp://host:rtsp端口/ProfileToken即把 go2rtc 自己的 RTSP 服务地址交给客户端GetSnapshotUri→ 返回http://host/api/frame.jpeg?srcProfileToken快照地址SystemReboot→ 返回 OK 并延时 1 秒退出进程模拟设备重启。静态响应GetSystemDateAndTime、GetVideoEncoderConfiguration(s)、GetServiceCapabilities、GetScopes等由StaticResponse与responses映射表统一生成其中编码配置固定声明为 H.264 Main、1920x1080、30fps、8192kbps。已实测兼容的 ONVIF 客户端按 README 记录以下第三方客户端已实测可正常使用 go2rtc 的 ONVIF 服务端Happytime onvif clientWindowsHome Assistant ONVIF integrationLinuxOnvierAndroidONVIF Device ManagerWindows限制说明服务端目前仅支持 RTSP 协议的 TCP 传输UDP 与 HTTP 传输尚未实现GetCapabilitiesResponse中RTP_RTSP_TCPtrue、RTPMulticastfalse、RTP_TCPfalse即为此能力的声明。源码调用链与独立调试工具把 ONVIF 源接入 streams 的入口在 internal/onvif/onvif.go 的streamOnvifNewClient建立客户端 →GetURI拿到 RTSP 地址 → 追加原始 URL 中#之后的参数 → 交给streams.GetProducer复用 go2rtc 既有的 RTSP 拉流链路。这意味着 ONVIF 源最终落到普通 RTSP 处理天然继承 go2rtc 的全部转码、录制、多协议输出能力。仓库还提供了一个独立调试工具examples/onvif_client/main.go可对任意 ONVIF 设备逐个发起原始 SOAP 操作并把响应保存为 XML 文件用于排查厂商兼容性问题# 获取设备能力并保存为 host_GetCapabilities.xml go run examples/onvif_client/main.go onvif://user:pass192.168.1.123 GetCapabilities # 获取主码流 URI go run examples/onvif_client/main.go onvif://user:pass192.168.1.123 GetStreamUri profile-token支持的操作与 pkg/onvif/server.go 中定义的常量一一对应覆盖Device*系列与Media*系列的全部查询操作。实测设备与固件兼容性按 internal/onvif/README.md 的Tested cameras章节go2rtc 作为 ONVIF 客户端已在以下摄像头实测通过Dahua IPC-K42OpenIPCReolink RLC-520ATP-Link Tapo TC60结合 pkg/onvif/onvif_test.go 的测试数据可见大华返回的 URI 形如rtsp://ip:554/cam/realmonitor?channel1subtype1unicasttrueprotoOnvif而 go2rtc 自身作为服务端返回的则是rtsp://host:8554/stream名两者都能被同一套FindTagValue Unescape Parse管线正确解析——这正是一个客户端兼容厂商私有实现与自家服务端的设计体现。小结接入摄像头onvif://user:passhost[:port]配合?subtypeN与snapshot参数选择码流或快照发现设备WebUI Add 页的 ONVIF 按钮基于 WS-Discovery 组播要求同子网、Docker 需 host 网络反向集成go2rtc 以/onvif/端点暴露为 ONVIF 设备每个 stream 对应一个 Profile可被 Home Assistant 等客户端直接发现取流调试排查借助 examples/onvif_client 逐个请求原始 SOAP 操作快速定位厂商认证或服务路径差异。【免费下载链接】go2rtcUltimate camera streaming application项目地址: https://gitcode.com/GitHub_Trending/go/go2rtc创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考