大牛直播SDK(SmartMediaKit)Android平台Unity3D RTSP/RTMP播放器集成实践

发布时间:2026/5/20 1:17:06

大牛直播SDK(SmartMediaKit)Android平台Unity3D RTSP/RTMP播放器集成实践 摘要本文介绍大牛直播SDKSmartMediaKit在 Android 平台 Unity3D 工程中的 RTSP/RTMP 播放器集成方式适用于安防监控、工业可视化、无人机回传、智慧教室、数字孪生、远程巡检、车载视频、AR/VR 可视化等需要在 Unity 场景中嵌入实时视频画面的应用场景。通过大牛直播SDK提供的 Android Unity3D 播放器能力开发者可以在 Unity3D 工程中快速接入 RTSP/RTMP 实时流播放实现低延迟播放、播放状态回调、视频画面显示、本地录像、软硬解码配置、RTSP 传输策略配置、下载速度提示等能力。Unity 侧主要完成场景搭建、UI 控制、播放参数配置和视频承载SDK 侧负责实时流媒体播放、解码、事件回调和录像等核心能力。关键词大牛直播SDK、SmartMediaKit、Unity3D、Android、RTSP播放器、RTMP播放器、低延迟播放、Unity播放器集成、实时音视频SDK1. 方案概述在 Unity3D 项目中接入 RTSP/RTMP 实时流播放与普通本地视频文件播放不同。RTSP/RTMP 播放涉及实时网络连接、流媒体拉取、解码、缓冲控制、状态回调、画面显示和异常处理等多个环节。如果业务侧从零实现完整播放链路不仅开发周期长还需要持续处理不同视频源、不同 Android 设备、不同网络环境下的兼容性问题。大牛直播SDK Android Unity3D 播放器方案面向 Unity3D 实时视频集成场景提供标准化播放器能力。SDK 侧负责 RTSP/RTMP 拉流、播放控制、解码适配、状态事件、下载速度统计和录像等能力Unity 侧负责 UI 交互、播放地址输入、状态展示、显示区域承载和业务逻辑组织。当前示例工程已将 SDK 接口、播放器封装、播放实例、播放器管理器和 UI 控制进行了分层。NTSmartPlayerAPI负责 Android SDK JNI 包装业务层无需直接持有 AndroidJavaObjectNTPlayerWrapper负责句柄生命周期、播放/录像状态和配置下发PlayerInstance负责单路播放器实例、画面显示适配和事件处理PlayerManager负责 SDK 初始化、实例创建销毁和事件分发UIController负责界面按钮、输入框、状态文本和 RawImage 适配。2. 适用场景大牛直播SDK Android Unity3D RTSP/RTMP 播放器适用于需要在 Unity3D 中显示实时视频画面的 Android 应用。典型场景包括工业数字孪生系统中的现场视频叠加、无人机或车载系统中的实时回传画面显示、安防监控系统中的 RTSP 预览、智慧教室和无纸化会议中的实时同屏、远程巡检中的现场视频查看以及 AR/VR、仿真训练和应急指挥中的实时视频融合。这类项目通常更关注以下能力视频画面能否稳定播放、延迟是否可控、播放状态是否可感知、是否支持 RTSP/RTMP 常见视频源、是否便于接入 Unity UI 或场景对象、是否可以在播放过程中进行录像留痕。大牛直播SDK通过播放器模块和 Unity3D 示例工程将这些能力封装为相对清晰的集成流程便于开发者快速完成工程验证和业务集成。3. 集成前准备开始集成前建议准备以下内容项目说明Unity3D 工程Android 目标平台工程Android Native 插件大牛直播SDK提供的.so及相关依赖C# 脚本文件播放器接口层、管理层、实例层和 UI 控制层Material 与 Shader用于 Unity 侧视频画面显示测试流地址RTSP 或 RTMP 播放地址Android 真机建议使用真实设备验证播放、录像和性能Android 工程至少需要网络访问权限uses-permission android:nameandroid.permission.INTERNET /如果项目需要录像推荐优先使用应用私有目录保存录像文件。示例工程中提供了录像目录配置项当未指定录像目录时可使用Application.persistentDataPath/Record作为默认录像路径。4. 工程目录说明建议将播放器相关文件按职责放入 Unity 工程目录便于后续维护和复用。推荐目录结构如下Assets/ ├── NTSmartPlayerAPI.cs ├── NTPlayerEvent.cs ├── NTPlayerWrapper.cs ├── PlayerConfig.cs ├── PlayerInstance.cs ├── PlayerManager.cs ├── UIController.cs ├── Plugins/ │ └── Android/ │ ├── libSmartPlayer.so │ └── 其他依赖 .jar ├── Materials/ │ ├── MaterialYuv420.mat │ ├── MaterialNV21.mat │ └── MaterialNV12.mat └── Shaders/ ├── Unlit_YUV420.shader ├── Unlit_NV21.shader └── Unlit_NV12.shader各文件职责建议理解如下文件说明NTSmartPlayerAPI.csAndroid SDK JNI 静态包装层统一封装播放器底层接口NTPlayerEvent.cs播放器事件 ID 常量定义NTPlayerWrapper.cs播放器句柄生命周期、播放控制、录像控制和参数下发封装PlayerConfig.cs播放配置数据结构可在 Inspector 中调整PlayerInstance.cs单路播放器实例负责播放状态、事件处理和视频显示适配PlayerManager.cs单例管理器负责 SDK 初始化、播放器创建销毁和事件分发UIController.csUI 控制器负责按钮、输入框、状态文本和 RawImage 显示适配其中NTSmartPlayerAPI是 SDK 接口层内部负责初始化 Android 侧播放器对象并提供统一的NT_U3D_*接口NTPlayerWrapper进一步封装播放器句柄、播放状态、录像状态和配置下发PlayerManager是场景中的单例管理器UIController负责用户交互和显示区域适配。5. 插件、Material 与 Shader 放置Android Native 插件应放入Assets/Plugins/Android/ ├── libSmartPlayer.so └── 其他依赖 .jarUnity 在构建 Android APK 时会自动将该目录下的.so和.jar依赖打入应用包。请确保 SDK 库文件与目标 CPU 架构匹配例如 arm64-v8a 或 armeabi-v7a。视频显示相关 Material 和 Shader 建议放入Assets/Materials/ ├── MaterialYuv420.mat ├── MaterialNV21.mat └── MaterialNV12.mat Assets/Shaders/ ├── Unlit_YUV420.shader ├── Unlit_NV21.shader └── Unlit_NV12.shaderSDK 已对不同视频格式的显示链路进行适配开发者通常只需在 Inspector 中正确配置对应 Material即可完成 Unity 侧视频画面显示。示例工程中UIController会实例化 I420、NV21、NV12 三类 Material播放实例会根据实际视频格式选择对应显示材质。6. Unity 场景搭建推荐使用以下场景层级Canvas ├── PlayerManager 挂载 PlayerManager.cs └── Panel 挂载 UIController.cs ├── VideoArea │ └── RawImage └── ControlsArea ├── StatusText ├── InputField_Url └── ButtonRow ├── BtnDecoder ├── BtnMute ├── BtnStartStopPlayback └── BtnRecordPlayerManager用于 SDK 初始化、播放器实例管理和事件接收场景中通常只需要一个。Panel作为播放器 UI 面板挂载UIController用于控制播放、停止、录像、静音、软硬解码切换和状态显示。VideoArea用于承载视频显示区域建议设置黑色背景。其子节点RawImage用于显示视频画面。示例工程中UIController会根据视频分辨率和显示区域大小自动调整 RawImage 尺寸使画面按比例显示避免拉伸变形。PlayerManager在Awake()中完成 SDK 初始化并在Update()中驱动播放器刷新UIController在Start()中完成 Material 实例化、按钮事件绑定、默认 URL 设置和显示区域初始化。7. Inspector 接线说明完成场景搭建后需要在UIController的 Inspector 中配置以下字段字段赋值对象Render View场景中的 RawImageVideo Area RTVideoArea 的 RectTransformStatus TextStatusText 的 Text 组件Url InputInputField_UrlBtn Decoder软硬解码切换按钮Btn Mute静音/取消静音按钮Btn Play开始/停止播放按钮Btn Record开始/停止录像按钮Mat I420I420 对应 MaterialMat NV21NV21 对应 MaterialMat NV12NV12 对应 MaterialDefault Url默认 RTSP/RTMP 播放地址Record Directory录像目录留空则使用默认目录PlayerManager上的PlayerConfig可直接在 Inspector 中调整播放参数包括解码模式、缓冲时长、RTSP 传输策略、音频设置、低延迟模式、旋转角度和录像文件大小等。PlayerConfig已将常用配置项通过可视化字段暴露便于调试和项目集成。8. 播放参数配置PlayerConfig是播放器参数配置入口建议开发者优先通过 Inspector 调整。主要参数如下参数说明enableHardwareDecoder是否启用硬件解码bufferTimeMs播放缓冲时长0 表示最低延迟rtspUseTcp是否强制 RTSP TCP 模式rtspTimeoutSecRTSP 连接超时时间rtspAutoSwitchTcpUdpUDP 连接失败后是否自动切换 TCPmute默认是否静音volume默认音量范围 0–100useAudioTrack是否使用 AudioTrack 输出fastStartup是否启用快速首帧lowLatencyMode是否启用低延迟模式rotateDegrees视频旋转角度recMaxFileSizeMB单个录像文件最大体积对于低延迟场景可以将bufferTimeMs设置得较低并结合fastStartup、lowLatencyMode、RTSP TCP/UDP 策略进行测试。需要注意的是低延迟和抗网络抖动之间通常存在平衡关系。缓冲越低延迟越小但在网络波动较大的情况下卡顿或丢帧概率可能增加。因此建议结合实际视频源、码率、网络环境和目标设备进行综合调优。using System; using UnityEngine; [Serializable] public class PlayerConfig { [Header(解码)] [Tooltip(启用硬件解码H264/H265不支持时 SDK 自动回退到软解)] public bool enableHardwareDecoder false; [Header(缓冲)] [Tooltip(播放缓冲时长毫秒0 不缓冲最低延迟)] [Range(0, 8000)] public int bufferTimeMs 0; [Header(RTSP 传输)] [Tooltip(true 强制 TCPfalse 优先 UDP)] public bool rtspUseTcp false; [Tooltip(连接超时秒)] [Range(1, 30)] public int rtspTimeoutSec 10; [Tooltip(UDP 连接失败后自动切换为 TCP)] public bool rtspAutoSwitchTcpUdp true; [Header(音频)] public bool mute false; [Range(0, 100)] public int volume 100; [Tooltip(true AudioTrack 模式false 自动选择)] public bool useAudioTrack true; [Header(播放行为)] [Tooltip(快速首帧减少起播黑屏)] public bool fastStartup true; [Tooltip(超低延迟模式会增加丢帧概率)] public bool lowLatencyMode false; [Tooltip(画面顺时针旋转角度0 / 90 / 180 / 270)] [Range(0, 270)] public int rotateDegrees 0; [Header(录像)] [Tooltip(单个录像文件最大体积MB)] public int recMaxFileSizeMB 500; }9. RTSP/RTMP 播放流程在示例工程中播放流程已经封装到 UI 和播放器管理逻辑中。开发者在输入框中填入 RTSP 或 RTMP 地址后点击播放按钮即可启动播放。业务流程如下输入 RTSP/RTMP 地址 → 点击开始播放 → 创建播放器实例 → 应用播放配置 → 绑定 RawImage 显示目标 → 启动播放 → Unity 主线程刷新视频画面当前工程中UIController.OnPlayClicked()会根据当前状态决定开始播放或停止播放。开始播放时会获取或创建播放器实例绑定 RawImage 和 Material然后启动播放停止播放时会停止播放并清理画面如果当前没有录像任务则释放播放器实例。public void StartPlay() { if (!wrapper_.StartPlay()) return; need_get_frame_ true; need_init_texture_ true; StatusText 连接中...; } public void StopPlay() { if (!is_playing) return; wrapper_.StopPlay(); need_get_frame_ false; need_init_texture_ false; VideoWidth 0; VideoHeight 0; downloadSpeedBps_ -1; flrHundredths_ -1; lrHundredths_ -1; bufferStatus_ 0; bufferPercent_ 0; connectionStatus_ 0; StatusText ; }播放前需要确保 RawImage 和 Material 已正确配置。示例工程通过SetRenderTarget()将 RawImage 和三类 Material 绑定到播放器实例中保证播放器启动后可以将视频画面显示到 Unity UI 中。10. 视频画面显示说明播放器采用 Unity 主线程刷新画面的方式。SDK 负责准备解码后的视频帧Unity 侧在主线程中刷新并显示到 RawImage。该方式符合 Unity 的渲染机制便于与 Unity UI 和场景显示逻辑结合。开发者在集成时主要关注以下几点RawImage 是最终视频显示控件Material 和 Shader 用于不同视频格式的显示适配播放器会根据实际视频格式选择对应显示材质分辨率变化后UI 层会自动调整 RawImage 尺寸建议直接使用 SDK 示例工程提供的 Material 和 Shader。示例工程中播放器实例负责视频画面刷新UI 层负责根据显示区域和视频分辨率做等比适配。收到分辨率信息后UIController会记录视频宽高并在后续显示刷新中调整 RawImage 的尺寸。11. 事件回调与状态显示SDK 会向 Unity 层回调播放状态、连接状态、分辨率信息、缓冲状态、下载速度、录像文件生成等事件。业务层可根据这些事件更新 UI 状态、提示网络质量、展示当前分辨率或处理录像文件路径。常见事件类型包括连接中 / 已连接 / 连接失败 / 断开 分辨率变化 长时间无媒体数据 RTSP 状态码提示 缓冲开始 / 缓冲中 / 缓冲结束 下载速度 快照结果 录像文件生成 / 录像文件完成事件由 SDK 发送到PlayerManager再由播放器实例进行处理。示例工程中PlayerManager.onNTSmartEvent()是事件入口播放器实例会根据事件更新连接状态、缓冲状态、下载速度、录像状态和分辨率信息最终形成状态文本供 UI 展示。12. 下载速度与网络状态提示播放器支持下载速度上报可用于辅助判断网络质量。示例工程会在状态文本中展示当前速度信息并结合缓冲状态反馈播放体验。public static class NTPlayerEvent { private const int PLAYER_SDK 0x01000000; // EVENT_DANIULIVE_PLAYER_SDK // ── 连接 / 播放状态 ─────────────────────────────────────────────────── /// summary开始播放SDK 内部状态机已启动/summary public const int STARTED PLAYER_SDK | 0x1; /// summary连接中/summary public const int CONNECTING PLAYER_SDK | 0x2; /// summary连接失败/summary public const int CONNECTION_FAILED PLAYER_SDK | 0x3; /// summary已连接/summary public const int CONNECTED PLAYER_SDK | 0x4; /// summary断开连接/summary public const int DISCONNECTED PLAYER_SDK | 0x5; /// summary停止播放/summary public const int STOP PLAYER_SDK | 0x6; // ── 媒体信息 ────────────────────────────────────────────────────────── /// summary视频解码分辨率。p1width, p2height/summary public const int RESOLUTION_INFO PLAYER_SDK | 0x7; /// summary收不到媒体数据检查 URL 或网络/summary public const int NO_MEDIADATA PLAYER_SDK | 0x8; /// summary切换 URL 中/summary public const int SWITCH_URL PLAYER_SDK | 0x9; /// summary截取快照结果。p10 成功非 0 失败/summary public const int CAPTURE_IMAGE PLAYER_SDK | 0xA; /// summaryRTSP 状态码上报目前只上报 401。p1status code/summary public const int RTSP_STATUS_CODE PLAYER_SDK | 0xB; // ── 录像 ────────────────────────────────────────────────────────────── /// summary录像写入新文件。p3新文件完整路径/summary public const int RECORDER_NEW_FILE PLAYER_SDK | 0x21; /// summary一个录像文件写入完成。p3已完成文件完整路径/summary public const int RECORDER_FILE_DONE PLAYER_SDK | 0x22; // ── 缓冲 ────────────────────────────────────────────────────────────── /// summary开始缓冲/summary public const int START_BUFFERING PLAYER_SDK | 0x81; /// summary缓冲中。p1百分比进度0–100/summary public const int BUFFERING PLAYER_SDK | 0x82; /// summary缓冲结束恢复正常播放/summary public const int STOP_BUFFERING PLAYER_SDK | 0x83; // ── 下载速度 ────────────────────────────────────────────────────────── /// summary /// 下载速度上报。p1速度(Byte/s)。 /// p2 bit 编码 /// bit311 → 高 15 位为前向丢包率 FLRQ8.8 定点÷256 得实际比例 /// bit151 → 低 15 位为综合丢包率 LR Q8.8 定点÷256 得实际比例 /// /summary public const int DOWNLOAD_SPEED PLAYER_SDK | 0x91; }当用户反馈“播放卡顿”“延迟高”“画面不连续”时可优先检查以下内容当前是否已连接是否频繁进入缓冲下载速度是否低于视频实际码率视频分辨率和码率是否过高RTSP 使用 TCP 还是 UDP当前网络是否存在明显抖动目标设备解码性能是否满足要求。示例工程中已经包含下载速度事件和缓冲事件的状态处理逻辑业务侧可根据项目需要决定是否在 UI 中展示。13. 录像能力说明播放器支持播放过程中启动本地录像适用于安防留痕、巡检归档、远程会诊记录、问题复盘等场景。录像目录可在 Inspector 中配置如果未配置可使用应用私有目录下的默认路径。业务流程如下点击开始录像 → 确定录像目录 → 启动录像 → SDK 写入录像文件 → 回调新文件路径或文件完成事件 → 业务侧展示、上传或归档当前工程中录像和播放可以共享同一个播放器实例。点击录像按钮时如果播放器实例不存在会先创建播放器实例再启动录像停止录像时如果当前没有播放任务可以释放播放器资源。// ── 录像控制 ────────────────────────────────────────────────────────────── public void StartRecorder(string directory) { int maxMB PlayerManager.Instance?.config?.recMaxFileSizeMB ?? 500; if (!wrapper_.StartRecorder(directory, maxMB)) Debug.LogError([PlayerInstance] StartRecorder failed); } public void StopRecorder() { wrapper_.StopRecorder(); }录像过程中SDK 会通过事件回调通知新文件生成和文件完成业务侧可以根据回调路径进行文件展示、上传、归档或后续处理。14. 软硬解码与低延迟建议示例工程提供软硬解码切换能力。硬解码通常 CPU 占用更低适合分辨率较高或设备性能有限的场景软解码兼容性相对更稳适合调试阶段或设备差异较大的项目。首次集成时建议先使用软解码验证播放链路确认播放地址、网络连通性和场景接线均正常后再切换硬解码进行性能测试。示例工程中软硬解码按钮用于切换当前解码模式并在播放或录像运行中禁用避免运行过程中切换关键解码参数。静音按钮则支持播放中实时切换。低延迟调优可重点关注以下参数调优项建议bufferTimeMs越低延迟越小但抗抖动能力下降fastStartup可用于减少起播等待lowLatencyMode适合强实时场景rtspUseTcp网络复杂时 TCP 更稳rtspAutoSwitchTcpUdp建议保留自动切换能力enableHardwareDecoder需结合目标设备测试兼容性低延迟播放效果受视频源、编码参数、网络质量、缓冲策略、解码方式和设备性能共同影响。建议在目标场景中进行端到端测试以获得更符合业务需求的参数组合。15. Android 打包注意事项打包 Android 前建议重点检查以下内容Assets/Plugins/Android/下的.so和.jar依赖是否完整AndroidManifest 是否包含网络权限目标 CPU 架构是否与 SDK 库匹配Material 和 Shader 是否正确放入工程并参与打包Scene 中是否存在PlayerManager对象UIController的 Inspector 字段是否全部接好默认播放地址是否可访问Android 真机是否与播放源处于可连通网络中录像目录是否可写目标设备是否满足播放分辨率和解码性能要求。建议优先使用真机进行测试。编辑器环境可用于 UI 布局和业务逻辑预览Android Native SDK 相关能力应以真机测试结果为准。16. 常见问题16.1 点击播放后没有画面建议按以下顺序排查确认 RTSP/RTMP 地址是否可用确认 Android 设备与播放源网络是否互通确认 AndroidManifest 已配置网络权限确认 RawImage、Material、Shader 已正确接线查看是否收到连接、分辨率或错误状态事件尝试切换软解码或 RTSP TCP 模式。16.2 连接失败可以先使用 VLC 或其他播放器验证播放地址。如果是 RTSP 流可尝试启用 TCP 模式或开启 UDP 失败后自动切 TCP。若播放源需要鉴权请确认 URL 中的用户名、密码和端口配置正确。16.3 画面比例异常示例工程会根据视频分辨率和显示区域自动调整 RawImage 尺寸。请确认 VideoArea 的 RectTransform 设置合理RawImage 不要额外添加会影响尺寸计算的布局组件。收到分辨率信息后UI 层会按视频宽高比进行显示适配。16.4 播放卡顿或延迟较高可结合缓冲时长、低延迟模式、RTSP TCP/UDP 策略、下载速度和视频码率综合调整。低延迟场景建议减少缓冲但在网络波动明显时可适当增加缓冲以提升流畅性。16.5 录像文件找不到请检查 Inspector 中的录像目录配置。如果留空通常使用应用私有目录下的默认 Record 路径。可通过录像文件事件查看实际文件路径。16.6 是否支持播放中切换软硬解码不建议在播放过程中切换软硬解码。软硬解码属于播放前关键配置示例工程中播放或录像运行时会禁用解码模式切换按钮。17. 总结大牛直播SDKSmartMediaKitAndroid Unity3D RTSP/RTMP 播放器方案面向需要在 Unity3D 场景中接入实时音视频画面的 Android 应用提供了低延迟播放、播放状态回调、视频画面适配、本地录像、软硬解码配置、RTSP/RTMP 地址接入等能力。通过示例工程提供的分层封装开发者可以快速完成 SDK 插件放置、场景搭建、Inspector 接线、播放参数配置和真机运行验证。在实际项目中开发者可根据业务需求灵活调整 UI 布局、播放地址、缓冲策略、软硬解码模式、录像目录和状态展示方式。对于安防监控、工业可视化、无人机回传、智慧教室、数字孪生、远程巡检、车载视频、AR/VR 可视化等场景该方案能够帮助开发者在 Unity3D 中快速构建稳定、低延迟、易集成的 RTSP/RTMP 实时视频播放能力。大牛直播SDK将持续围绕跨平台低延迟播放、实时音视频采集、推流、录像、轻量级服务、GB28181 接入等方向完善产品能力为企业级实时音视频应用提供稳定可靠的底层技术支撑。 CSDN官方博客音视频牛哥-CSDN博客

相关新闻