从拉流、叠加到国标多平台分发:SmartMediaKit 多模态融合推流方案设计

从拉流、叠加到国标多平台分发:SmartMediaKit 多模态融合推流方案设计
前言这篇文章到底想解决什么问题在工业巡检、环境监测、应急通信、移动作业、特种设备监管等场景里现场设备往往不只是“采集一路视频并推上平台”这么简单。很多项目真正需要的是一套完整的边缘侧融合系统既要接入主视频画面也要接入本地辅助摄像头画面既要看到实时画面也要把关键状态信息叠加到画面上既要通过 GB28181 对接一个或多个平台也要通过 MQTT 上报结构化数据既要实时推流也要本地录像、快照、回放、导出既要支持报警联动也要保证推流、存储、UI、数据上报之间互不影响。所以这类系统的难点不在于某一个功能点而在于如何把“视频链路、数据链路、协议链路、本地业务链路”组织成一个稳定可运行的整体。本文结合 RK3588 平台以及大牛直播 SDKSmartMediaKit中的 SmartRelayDemoV3 工程梳理一套多模态感知融合推流系统的设计思路。这里重点不是讲某个硬件接口怎么接也不是把所有项目需求逐条罗列而是从 SmartMediaKit 的模块能力出发说明这套系统应该怎么设计、Demo 中哪些代码已经支撑了核心链路、后续项目中如何扩展到真实行业场景。整体设计思路一条主链路四类扩展能力这套系统可以理解为一条主链路加上四类扩展能力。主链路是视频接入 → 解码/取帧 → 图层合成 → 编码输出 → 协议推送在这条主链路之上再扩展PIP 画中画能力OSD 状态叠加能力GB28181 多平台并行推送能力本地录像、快照、回放、导出能力结构化数据上报与报警联动能力。SmartRelayDemoV3 的价值就在于它不是单独演示“播放”或“推流”而是把播放器、推流器、图层、摄像头叠加、录像、GB28181 fanout 等模块放在一个工程里形成了一套可继续裁剪和扩展的工程基础。从工程结构上看可以抽象成下面几层感知接入层主视频源、辅助摄像头、设备状态、传感数据媒体处理层拉流、解码、外部视频输入、图层合成、OSD、PIP、编码协议分发层GB28181、RTMP、RTSP、MQTT本地业务层实时预览、录像、快照、历史回放、文件管理、数据导出平台应用层监管平台、业务平台、移动端、运维平台。SmartMediaKit 在系统中承担的是“媒体核心引擎”的角色负责把多路画面和业务信息合成为一路统一的视频输出再通过不同协议送到平台或本地存储业务层负责传感数据、设备状态、报警逻辑、UI交互和数据上报。SmartRelayDemoV3 的工程基础在 SmartRelayDemoV3 中SmartPlayer.java是整体业务组织的核心 Activity。它同时维护了播放器、推流器、录像、RTSP 服务、摄像头叠加、状态水印、GB28181 多平台等模块。从代码结构可以看出几个重要设计点。播放器侧由SmartPlayerJniV2和LibPlayerWrapper封装负责 RTSP/RTMP 等视频源的播放、拉流、录像、回调和资源释放。推流侧由SmartPublisherJniV2和LibPublisherWrapper封装负责编码、图层投递、RTMP 推送、RTSP 服务、GB28181 媒体流等能力。CameraOverlay 由CameraOverlayHelper负责把 Camera2 采集到的 YUV_420_888 数据作为图层投递给 publisher实现 PIP 画中画。动态水印由LayerPostThread负责按固定图层编号向 publisher 投递文字、图片、矩形等图层数据。GB28181 fanout 由SmartPlayer.java中的多平台上下文管理每个平台有自己的 SIP 参数、注册状态、RTP Sender 和媒体流启动逻辑。录像文件管理由RecorderManager负责历史回放由RecorderPlayback负责形成了本地录像列表、点击播放、删除、返回刷新等基本闭环。这些代码说明Demo 已经具备了这类项目最关键的基础骨架能接入主视频能二次编码能叠加图层能叠加本地摄像头画面能推送到多个 GB28181 平台能录像能管理和回放录像文件能在 Activity 生命周期中统一释放资源。在此基础上项目侧要做的不是从零搭建音视频链路而是围绕业务数据、UI、报警、存储、平台参数配置做扩展。主视频链路从拉流到统一编码输出系统中的主视频一般来自网络摄像头、设备侧编码器、NVR或者其他标准视频源。SmartRelayDemoV3 中的主链路可以概括为播放器拉流 → 解码输出 → 外部视频帧进入 publisher → 图层合成 → 二次编码输出如果只是做透明转发系统可以使用透传模式直接把编码后的音视频数据送到下游推流模块。这样资源消耗低延迟更小。但一旦项目需要叠加 OSD、PIP、报警提示、水印、状态信息就必须进入二次编码模式。因为透传模式下码流不经过画面重绘无法把业务信息真正写入视频画面。这也是 Demo 中很关键的一个判断逻辑CameraOverlay 在透传模式下不支持叠加必须切换到二次编码模式。这个设计非常符合工程实际因为 PIP、OSD、本地状态叠加都属于“画面级处理”必须在编码前完成。所以在多模态感知系统中推荐把主视频链路设计为主视频接入解码为原始画面进入 SmartMediaKit 图层合成管线叠加 PIP、状态 OSD、报警信息、固定水印统一编码输出同时用于平台推流、本地录像、快照和回放。这样做的好处是平台端看到的画面、本地录像保存的画面、后续历史回放看到的画面都保持一致。PIP 画中画辅助视角如何进入编码画面多模态场景下单一路主画面往往不够。比如主画面展示远端设备或现场大视角本地 MIPI/USB 摄像头可以展示操作者视角、设备细节、周边环境或补充画面。SmartRelayDemoV3 中的CameraOverlayHelper就是为这个场景准备的。它的职责非常清晰封装 Camera2 的启动、停止、切换摄像头监听 Camera2 的 YUV_420_888 图像回调计算 PIP 窗口位置、大小和旋转角度通过PostLayerImageYUV420888ByteBuffer()把摄像头画面投递到指定图层将该图层交给 publisher 参与统一合成编码。在 Demo 的图层规划里主视频占用 Layer 0摄像头 PIP 占用 Layer 1。这样设计很清晰主视频是底图PIP 作为第二层叠加在主画面上方后面的 OSD 和水印再继续叠加。PIP 的工程细节比表面看起来复杂。因为 Camera2 返回的是 YUV_420_888不同设备的 rowStride、pixelStride、UV 平面布局可能不同。如果直接按连续内存处理很容易出现色彩错乱、画面偏移或花屏。Demo 中的做法是把 Y、U、V 三个 plane 的 ByteBuffer、offset、rowStride、pixelStride 都传给 SDK由 SDK 侧完成正确处理。这比简单转 NV21 或手动拷贝更适合长期稳定运行。另外PIP 还涉及旋转和缩放。摄像头竖屏采集时rotation90 或 270 的情况下叠加区域的宽高语义需要适配否则会出现子窗口比例不对、方向不对、位置不准的问题。Demo 中通过计算 rotation、effective width/height、overlay width/height并在必要时对调 scale_width 和 scale_height保证最终 PIP 子窗口正常显示。从方案角度看PIP 模块建议这样设计主画面固定为 Layer 0辅助摄像头固定为 Layer 1PIP 默认放在右下角或右侧中部PIP 尺寸按主画面宽高比例计算摄像头旋转角根据设备方向和 CameraCharacteristics 计算开启和关闭 PIP 时要显式 EnableLayer / RemoveLayer避免图层残留。这样PIP 既可以作为 Demo 功能演示也可以直接扩展到项目中的近端摄像头、MIPI 摄像头、USB 摄像头等场景。OSD 状态叠加让视频画面携带业务信息多模态系统的核心价值之一是把业务状态直接叠加到视频画面上。比如设备电量网络状态GPS 定位传感器实时数据报警状态机器码公司名称时间戳平台侧需要识别的业务标识。这些信息如果只显示在本地 UI 上平台端和录像文件里是看不到的。真正有价值的做法是通过 SmartMediaKit 的图层机制把这些信息写入编码输出画面。Demo 中LayerPostThread的设计就体现了这个思路。它把水印、文字、图片、矩形等内容放到独立线程中刷新并且规划了清晰的图层编号Layer 0主视频Layer 1摄像头 PIPLayer 2~6动态水印、文字、图片、矩形等扩展图层Layer 7状态 OSDLayer 8固定公司/设备标识水印。这种图层规划非常适合行业项目。因为业务越复杂越不能把所有文字和图片混在一个图层里。比如传感器数据每秒刷新电量可能几十秒才变化一次公司名称基本不变报警提示只有异常时显示。如果全部放在同一个 Bitmap 里频繁刷新会浪费资源也不利于维护。更合理的方式是固定水印使用独立图层初始化后投递一次状态 OSD 使用独立图层按秒刷新报警 OSD 使用独立图层异常时显示恢复后移除PIP 使用独立图层按摄像头帧率刷新主视频使用独立图层按主码流帧率刷新。这样做的好处是图层互不干扰刷新频率可控关闭某个业务能力时不影响其他图层平台推流和本地录像画面保持一致后续增加新的业务信息也更容易扩展。对于实际项目中的传感器数据比如四路气体数值可以由业务层维护一份实时状态对象然后 OSD 线程定时读取状态对象生成 Bitmap 或文字图层投递给 SDK。本地 UI 显示和视频 OSD 不建议互相依赖。正确方式是它们共享同一份业务数据但各自负责自己的呈现方式。多平台 GB28181 并行推送不是重复编码而是统一输出后分发行业项目中很常见的需求是同一台设备需要同时接入多个国标平台。如果每个平台都单独拉一路、解一路、编码一路资源消耗会非常高而且多个平台看到的画面可能不一致。SmartRelayDemoV3 的 GB28181 fanout 设计提供了更合理的方式主视频、PIP、OSD 先统一进入图层合成合成后的画面只做一次编码编码输出再分发给多个 GB28181 平台每个平台维护独立的 SIP 注册、心跳、Invite/ACK、RTP Sender 和媒体流状态。这样可以形成“一次合成编码多平台独立分发”的架构。在 Demo 中每个平台都有自己的 SIP 参数包括本地端口、服务器 ID、域、服务器地址、端口、用户名、密码、设备 ID 等。平台之间互相隔离一个平台异常不应该影响另外的平台。GB28181 媒体回传的关键流程可以理解为平台发起 Invite设备侧解析 SDP创建 RTP Sender获取本地 RTP 端口回应 200 OK收到 ACK 后启动媒体流将编码输出送入 GB28181 媒体发送链路。Demo 中 ACK 后才真正启动媒体流这是比较规范的处理方式。因为在国标流程中Invite/200 OK/ACK 是媒体会话建立的关键过程过早发送媒体可能导致平台侧未准备好接收。多平台 GB28181 并行推送要重点关注不同平台本地端口要隔离SIP 注册状态要独立维护心跳异常要能重连平台 BYE 后要正确释放 RTP SenderACK 后再启动媒体流异常平台不能影响主编码链路平台参数要配置化而不是写死在代码里。SmartMediaKit 支持以统一编码输出为中心把一路融合后的业务画面同时送到多个国标平台既节省资源又保证多平台画面一致。MQTT 数据通道结构化数据不要塞进视频协议里视频画面适合通过 GB28181、RTSP、RTMP 等媒体协议传输但设备状态、传感器数据、报警事件、定位信息更适合通过 MQTT 这种轻量消息协议上报。所以这套系统应该明确区分两条通道视频通道负责主画面、PIP、OSD、音视频编码、GB28181/RTSP/RTMP 推送、本地录像数据通道负责设备状态、定位、电量、网络状态、传感器数据、报警事件、平台业务消息。两者在业务上关联在链路上解耦。比如四路气体数据既可以叠加到视频 OSD 上也可以通过 MQTT 发送 JSON 给平台。视频 OSD 解决“平台值班人员直观看到异常”的问题MQTT 解决“平台业务系统结构化处理、入库、告警、统计”的问题。推荐的数据流是传感器/设备状态 → 业务解析层 → 状态缓存 → OSD 渲染线程传感器/设备状态 → 业务解析层 → MQTT 消息封装 → 发布队列 → 平台 Broker报警事件 → 报警状态机 → 本地 UI / OSD / 外设 / MQTT / 录像标记。这样设计后视频推流和数据上报互不阻塞。即使 MQTT Broker 临时不可用也不影响视频继续推即使视频网络弱也不影响关键报警数据走独立队列补发。文章中不一定需要展开具体 JSON 字段但可以强调结构化数据建议包含设备 ID时间戳定位信息网络状态电池状态多路传感器数值报警状态事件编号平台需要的扩展字段。本地录像、快照与历史回放形成现场留存闭环实时推流解决的是“现在看得到”录像和回放解决的是“以后查得到”。在 SmartRelayDemoV3 中录像、文件管理、历史回放已经形成了一个基础闭环。RecorderManager负责扫描录像目录后台加载文件列表读取文件大小、时长等信息并显示到 ListView。点击文件后跳转到RecorderPlayback进行播放。这个设计虽然是 Demo 级 UI但工程方向是对的文件扫描放到后台线程避免阻塞 UI文件列表展示名称、大小、时长等关键元信息点击文件进入回放界面删除后返回列表刷新回放界面提供播放、暂停、进度条、删除等基础能力。对于行业项目可以在这个基础上扩展按日期筛选录像按报警事件筛选录像按设备 ID 筛选录像视频文件和传感器数据文件按时间戳关联支持 USB 导出支持循环覆盖支持异常断电后的文件修复或索引重建支持本地 UI 中查看历史数据曲线。这里要强调一个设计原则推流和存储必须解耦。实时推流是网络链路录像是本地 IO 链路二者不能互相阻塞。录像写入速度变慢时不能影响平台实时预览平台网络抖动时也不能导致本地录像丢失。SmartMediaKit 的优势在于统一编码输出可以同时服务于推流和录像避免重复编码。业务层只需要做好文件管理、空间策略、导出逻辑和回放 UI 即可。UI 信息分层本地 UI 和编码输出不能混为一谈很多项目初期容易犯一个错误以为本地 UI 上显示了电量、定位、传感器数据平台端推流画面里就应该也有这些信息。实际上不是。本地 UI 是 Android View 体系平台端视频画面是编码输出结果。它们不是同一层东西。所以系统中要明确区分两类显示本地交互层按钮、输入框、文件列表、回放控制、参数配置、调试日志编码输出层状态 OSD、业务水印、PIP 画面、报警提示、设备编号、时间戳。本地 UI 可以用 TextView、ImageView、ListView、TextureView 来实现编码输出必须通过 SmartMediaKit 的图层投递接口写入视频画面。比较好的做法是业务状态统一维护本地 UI 订阅这份状态并刷新 ViewOSD 图层线程订阅这份状态并刷新视频图层报警状态机改变后同时驱动 UI 提示、视频 OSD、MQTT 上报和本地留存。这样才能保证本地看得到平台看得到录像里也看得到后续回放还能查得到。这就是“多模态感知融合”的关键不是简单把数据放到旁边显示而是让视频、状态、事件和留存真正形成统一闭环。报警联动从数值超标到事件闭环在这类系统里报警不能只理解成“弹一个提示框”。一个完整的报警事件至少应该包括异常条件识别报警状态切换本地 UI 提示视频画面 OSD 报警本地声光或外设联动MQTT 平台事件上报录像文件或日志中记录事件历史回放中可以按事件追溯。推荐在业务层设计一个报警状态机而不是让 UI、MQTT、OSD、外设模块各自判断。比如某一路传感器数值超过阈值后报警状态机生成一个报警事件然后统一通知各模块UI 模块显示红色提示OSD 模块在画面中叠加报警文字MQTT 模块上报报警消息录像模块记录事件时间点外设模块触发本地声光输出恢复正常后再生成恢复事件。这样报警链路才是闭环的。SmartMediaKit 负责把报警结果可视化地写入视频画面业务层负责报警规则、状态机、外设控制和平台数据上报。两者边界清晰系统才好维护。线程模型与资源释放长期运行比功能演示更重要这类系统通常不是运行几分钟就结束而是要长时间运行。因此线程模型和资源释放非常关键。SmartRelayDemoV3 中有几个值得保留的工程思路。第一耗时操作尽量放后台线程。比如 JNI 初始化、RTSP Server 初始化、释放播放/推流资源、GB28181 停止、录像文件扫描等都不应该阻塞 UI 主线程。第二图层刷新独立线程执行。LayerPostThread按固定周期刷新图层不直接依赖 UI 主线程。这样动态水印、状态 OSD 不会拖慢界面交互。第三CameraOverlay 独立封装生命周期。摄像头启动、停止、切换都收敛在CameraOverlayHelper中Activity 只负责调用不直接处理每一帧细节。第四Wrapper 管理 native handle。LibPlayerWrapper和LibPublisherWrapper对播放、推流、录像、RTSP、GB28181 状态做了封装释放时先停止运行状态再关闭 native handle避免资源泄漏。第五onDestroy 中要有完整释放顺序。Demo 中先停止 GB28181 平台再停止快照、音频、图层线程、摄像头叠加、状态水印然后异步释放播放、推流、RTSP Server、publisher、player 等 JNI 资源并清空 Handler 队列。这类释放顺序对长期运行非常重要。UI 主线程只做交互和状态展示媒体处理、协议操作、文件 IO、图层刷新、网络重连都必须后台化。推荐的项目实施路径为了降低联调复杂度项目不要一开始就把所有功能同时打开。建议按下面路径推进。第一阶段打通主视频接入。先验证 RTSP/GB28181 视频源能正常接入、播放、解码确认画面稳定、延迟可接受。第二阶段打通二次编码输出。在主视频基础上启用 publisher确认解码后的画面可以进入 SmartMediaKit 的图层合成和编码输出链路。第三阶段加入 OSD 状态叠加。先从固定文字、时间戳、水印做起再扩展到电量、网络、定位、传感器数据、报警状态。第四阶段加入 PIP 画中画。接入本地摄像头确认 Camera2 采集、YUV 投递、旋转、缩放、图层叠加、关闭释放都正常。第五阶段加入多平台 GB28181 fanout。先接一个平台再扩展到两个、三个平台。重点测试注册、心跳、Invite、ACK、BYE、断线重连、平台异常隔离。第六阶段加入 MQTT 数据通道。把设备状态、定位、传感器数据、报警事件通过 MQTT 上报和视频链路解耦。第七阶段完善录像、快照、回放、导出。把实时推流之外的本地留存能力补齐形成现场数据可追溯闭环。第八阶段加入报警联动。最后再整合阈值配置、报警状态机、UI提示、OSD报警、MQTT上报、外设联动、日志留存。这个顺序的好处是每一步都有明确验证目标出问题也容易定位到底是视频源问题、解码问题、图层问题、编码问题、协议问题、网络问题、存储问题还是业务状态同步问题。小结基于 RK3588 与大牛直播 SDKSmartMediaKit的多模态感知融合推流系统本质上不是一个简单的“拉流转推”项目而是一套边缘侧音视频与业务数据融合系统。SmartRelayDemoV3 已经把核心工程链路搭出来了主视频拉流与播放二次编码输出Layer 图层合成PIP 摄像头叠加动态 OSD 与水印多平台 GB28181 fanout本地录像与快照录像文件管理与历史回放生命周期和资源释放管理。在真实项目中业务侧只需要在这个基础上继续扩展传感器数据接入、MQTT 上报、报警状态机、UI配置、外设控制、文件导出和平台参数管理就可以形成一套完整的行业化方案。这套方案的核心价值可以概括为五点视频与数据融合本地画面、平台画面、录像画面一致一次合成编码多平台分发推流、存储、数据上报互相解耦Demo 工程具备可复用、可裁剪、可扩展的落地基础。对于工业巡检、环境监测、应急通信、移动作业、特种设备监管等场景这种以 SmartMediaKit 为核心的模块化架构既能降低音视频链路开发难度也能让项目更快从 Demo 验证走向工程交付。 CSDN官方博客音视频牛哥-CSDN博客