wvp-GB28181-pro 拉流代理实战将 RTSP/RTMP 流共享到国标平台【免费下载链接】wvp-GB28181-pro基于GB28181-2016、部标808、部标1078标准实现的开箱即用的网络视频平台。自带管理页面支持NAT穿透支持海康、大华、宇视等品牌的IPC、NVR接入。支持国标级联支持将普通摄像机/直播流/直播推流转国标共享到国标平台。项目地址: https://gitcode.com/GitHub_Trending/wv/wvp-GB28181-pro本文围绕 wvp-GB28181-pro 的「拉流代理」功能展开。该功能用于解决一类常见痛点摄像机或录像设备不支持 GB/T 28181 协议、也不支持主动推流但可以提供 RTSP或 RTMP播放地址。通过拉流代理WVP-PRO 可以把这路普通视频流转成国标通道供上级国标平台点播共享读者读完后可掌握两种代理模式ZLM 直接拉流、FFmpeg 拉流转码的完整配置方式、全部参数含义以及从管理页面到 ZLMediaKit 底层调用的整条实现链路。一、为什么需要拉流代理只有 RTSP 地址的设备如何接入国标体系不是所有摄像机都支持国标协议或者推流但这些设备通常可以得到一个视频播放地址一般为 RTSP 协议。以大华为例rtsp://{user}:{passwd}{ipc_ip}:{rtsp_port}/cam/realmonitor?channel1subtype0可以得到这样一个流地址可以直接用 VLC 进行播放。此时的思路是既然地址可以被拉取就可以通过拉流代理功能将这个设备“推送”给其他国标平台——由 WVP-PRO 代拉这路流再以国标通道形式对外共享。原文档给出的整体流程如下摄像机/源流流信息到达 ZLMediaKitZLMediaKit收到 hook 通知WVP-PRO 得到流信息上级国标平台向 WVP-PRO 点播这路视频WVP-PRO通知 ZLMediaKit 推流送 RTP到上级国标平台。这个流程对应源码中的两个关键角色流状态跟踪StreamProxyServiceImpl 通过监听MediaArrivalEvent流到达与MediaDepartureEvent流离开事件把rtspschema 的流变更同步到代理记录的pulling状态即流程中的第 1、2 步国标点播入口SourcePlayServiceForStreamProxyImpl 是拉流代理通道的ISourcePlayService实现当上级国标平台Platform对代理通道发起点播时调用playService.start(...)真正开始拉流对应流程中的第 3、4 步。二、两种代理模式ZLM 直接拉流与 FFmpeg 拉转拉流代理支持两种方式与编辑页面 web/src/views/streamProxy/edit.vue 中「类型」下拉框的取值一一对应模式type 取值实现方式是否支持转码ZLM 中直接代理流default调用 ZLM 的addStreamProxy接口直接代理 RTSP/RTMP 流否FFmpeg 拉转ffmpeg调用 ZLM 的addFFmpegSource接口借助 FFmpeg 完成拉转是通过修改 FFmpeg 命令模板实现两种模式在 ZLMMediaNodeServerService.startProxy 中分叉default模式先构造本机目标地址rtsp://127.0.0.1:{rtsp端口}/{app}/{stream}然后调用addStreamProxy把srcUrl、app、stream、音频/MP4 开关、RTSP 拉流方式rtspType与超时时间一并传给 ZLMffmpeg模式从 ZLM 配置中取出ffmpeg.cmd模板getFFmpegCMDs会读取 ZLM 节点配置里所有ffmpeg.cmd开头的键值并从模板中解析-f参数确定输出格式RTSP 输出用 rtsp 端口FLV/RTMP 输出用 rtmp 端口构造目标地址后调用addFFmpegSource。FFmpeg 模式下若超时时间为 0 会默认取 15 秒。PSFFmpeg 默认模板不需修改需要修改参数时自行去 ZLM 配置文件中添加一个ffmpeg.cmd键即可——后端正是通过 getFFmpegCMDs 把 ZLM 配置中所有ffmpeg.cmd前缀的模板暴露给前端选择的。三、代理参数详解StreamProxy 的完整字段拉流代理的实体定义在 StreamProxy.java它继承自CommonGBChannel国标通道通用字段核心字段如下字段说明备注type类型default流媒体直接拉流默认或ffmpegFFmpeg 实现拉流app应用名必填与stream共同唯一标识一路代理stream流 ID必填srcUrl拉流地址如前文的rtsp://...地址timeout收流超时时间秒拉流/收流的等待超时ffmpegCmdKeyFFmpeg 模板 KEY仅ffmpeg类型有效对应 ZLM 配置中ffmpeg.cmd的键名rtspTypeRTSP 拉流方式0TCP1UDP2组播relatesMediaServerId固定选择的流媒体服务 ID为空时自动选择负载最低的节点mediaServerId当前拉流使用的流媒体服务 ID运行时写入enable是否启用未启用的代理无法开始拉流enableAudio是否启用音频透传给 ZLM 拉流参数enableMp4是否启用 MP4 录制透传给 ZLM 拉流参数enableDisableNoneReader无人观看时自动停用前端“无人观看”选项中取值为“停用”时生效streamKeyZLM 返回的代理 key用于停止拉流代理delStreamProxypulling拉流状态由流到达/离开事件维护gbDeviceId/gbName国标编码 / 通道名称配置后才能共享到其他国标平台补充两点实现细节节点选择在 StreamProxyPlayServiceImpl.startProxy 中若未固定relatesMediaServerId则调用mediaServerService.getMediaServerForMinimumLoad(null)自动挑选负载最低的媒体节点分布式部署若该代理由其他 WVP 服务节点管理serverId不一致会通过redisRpcPlayService.playProxy(...)转发到对应节点执行保证集群下行为一致。四、添加代理的完整操作步骤4.1 页面操作打开「拉流代理」页面点击「添加代理」填写类型默认ZLM 直接拉流或 FFmpeg应用名 / 流 ID代理流在 ZLM 中的app/stream二者唯一确定一路代理重复会提示“APPSTREAM已经存在”见 StreamProxyServiceImpl.add拉流地址设备的 RTSP/RTMP 播放地址超时时间秒收流超时节点选择自动选择或固定到某个 ZLM 节点FFmpeg 命令模板FFmpeg 类型时选择选项来自对应 ZLM 节点配置的ffmpeg.cmd模板拉流方式RTSPTCP / UDP / 组播无人观看不做处理 / 停用 / 移除其他选项启用、开启音频、录制MP4。保存后如需把该路流共享推送到其他国标平台进入编辑页的「国标通道配置」选项卡配置国标编码即gbDeviceId。源码中add/update一旦检测到gbDeviceId非空就会通过gbChannelService.add/update(streamProxy.buildCommonGBChannel())同步创建/更新一条国标通道记录buildCommonGBChannel会把通道数据类型标记为STREAM_PROXY未填通道名称时默认使用app - stream。4.2 对应的 REST 接口代理接口全部集中在 StreamProxyController/api/proxy前缀前端调用封装见 web/src/api/streamProxy.js方法路径说明GET/api/proxy/list分页查询代理支持query、pulling是否正在拉流、mediaServerId过滤POST/api/proxy/add新增代理type缺省为defaultgbId为空时不建国标通道POST/api/proxy/update更新代理缺少id会返回 400GET/api/proxy/ffmpeg_cmd/list获取指定 ZLM 节点的ffmpeg.cmd模板列表GET/api/proxy/start开始拉流点播代理基于DeferredResult异步等待收流结果GET/api/proxy/stop停止拉流DELETE/api/proxy/delete按id移除代理前端播放入口对应 play(id) / stopPlay(id)即start/stop接口。五、底层链路从 start 到 ZLM 收流的超时与 Hook 机制开始拉流页面点击播放或国标平台点播触发时的核心调用链为StreamProxyController.start→IStreamProxyPlayService.start→StreamProxyPlayServiceImpl.startProxy→ZLMMediaNodeServerService.startProxy→ ZLMaddStreamProxy/addFFmpegSource。其中 startProxy 做了几件值得注意的事前置校验代理未启用enablefalse直接回调“代理未启用”若该流已在本节点存在mediaServerId命中且流仍在直接复用现有StreamInfo不会重复拉流收流超时任务注册一个on_media_arrival的 Hook 订阅同时用dynamicTask.startDelay挂一个延时任务超时时间为userSetting.getPlayTimeout()若超时前 ZLM 没有回调“流到达”则返回收流超时的错误码流到达回调收到 Hook 通知后停止超时任务构建StreamInfo返回给调用方管理页面的播放组件或国标 INVITE 应答流程并把代理标记为pullingtrue写回数据库。停止拉流时stopProxy若持有 ZLM 返回的streamKey则调用delStreamProxy精确停止代理否则退化为按app/stream关闭流closeStreams随后清理数据库中的流状态。此外还有两个自愈机制无人观看自动处理StreamProxyServiceImpl 监听MediaNotFoundEvent当流因无观众被 ZLM 移除时若代理配置了“无人观看时自动停用/重启”会自动重新发起拉流自动点播节点在线状态同步ZLM 节点上线MediaServerOnlineEvent时以数据库为基准比对 ZLM 中实际存在的PULL/FFMPEG_PULL源流修正代理的pulling与关联国标通道的在线/离线状态节点离线时则批量将关联国标通道置为离线保证“数据库中数据为根本”的三者数据库、Redis 缓存、ZLM 内存状态一致。六、共享到上级国标平台代理流如何变成国标通道配置了国标编码的拉流代理在上级平台点播时走的是与普通国标通道一致的点播流程SourcePlayServiceForStreamProxyImpl.play拿到通道关联的代理 ID 后调用playService.start(id, record, callback)成功后把StreamInfo交给 GB28181 应答模块由 WVP-PRO 通知 ZLM 向平台送流。整个过程即原文档流程图第 3、4 步的落地实现。需要注意的适用前提与限制default 模式不支持转码源流为 H.265 等上级平台不编码时无法直接共享可改用ffmpeg模式并通过自定义ffmpeg.cmd模板增加转码参数FFmpeg 模式的输出格式由模板中的-f参数决定源码仅显式适配了 RTSP/FLV/RTMP 三种输出见 ZLMMediaNodeServerService代理流的国标在线状态跟随实际拉流状态流到达时通道置为在线流离开或节点离线时置为离线上级平台目录中看到的通道在线情况与真实拉流状态一致appstream全局唯一删除代理时会同时停止正在进行的拉流并删除关联的国标通道见 delete。小结wvp-GB28181-pro 的拉流代理把“只有 RTSP/RTMP 地址”的普通视频源纳入了国标体系页面填写流地址并保存即可生成代理配合「国标通道配置」赋予国标编码后即可共享给上级平台default模式零配置、由 ZLM 直接拉流ffmpeg模式通过 ZLM 配置中的ffmpeg.cmd模板支持转码。实现上依赖 ZLM hook 通知与收流超时任务保证状态可靠并通过国标通道服务维持与上级平台的在线状态同步。相关代码可进一步查看StreamProxyController、StreamProxyPlayServiceImpl、StreamProxyServiceImpl、ZLMMediaNodeServerService 与前端 web/src/views/streamProxy/。【免费下载链接】wvp-GB28181-pro基于GB28181-2016、部标808、部标1078标准实现的开箱即用的网络视频平台。自带管理页面支持NAT穿透支持海康、大华、宇视等品牌的IPC、NVR接入。支持国标级联支持将普通摄像机/直播流/直播推流转国标共享到国标平台。项目地址: https://gitcode.com/GitHub_Trending/wv/wvp-GB28181-pro创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
