Unity3d C#快速打开萤石云监控视频流(ezopen)支持WebGL平台,替代UMP播放视频流的方案(含源码)

news2024/11/16 7:28:03

前言

Universal Media Player算是视频流播放功能常用的插件了,用到现在已经不知道躺了多少坑了,这个插件虽然是白嫖的,不过被甲方和领导吐槽的就是播放视频流的速度特别慢,可能需要几十秒来打开监控画面,等待的时间较久。还有当输出WebGL的时候视频无法播放,这个问题也一直没法解决。而我们常用的萤石云监控视频流在小程序端或者Web端打开却快速了很多,这也就启发了在Unity3d中也使用这种嫁接的方式来实现。就是通过打开网页,在网页中播放视频流的方式来解决该问题。实验结果就是能比Universal Media Player打开快2-3倍。本文是Unity3d 2020.3.28f1c1 Personal版本以萤石云的ezopen协议为例,实现该功能。

效果

Windows效果一:
在这里插入图片描述

Windows效果二:

在这里插入图片描述

WebGL平台:

在这里插入图片描述

如果设备有问题会直接提示在播放界面上:

在这里插入图片描述

以上动态图没有展示成功的画面,因为设备非个人持有,所以播放成功的画面未进行直接展示。

工作准备

笔者所用的插件:

LitJson 用于生成/解析网络请求的json。
DOTweenPro 用于制作简单的窗口弹出、关闭动画;
3D WebView for Windows and macOS (Web Browser) 用于打开网页(使用说明(https://blog.csdn.net/qq_33789001/article/details/126180804))的插件(看需求使用Embedded Browser也可以),需要WebGL 平台的还需要2D WebView for WebGL (Web Browser IFrame)插件。

参考文章:
之前笔者写过关于萤石云监控相关的操作可以进行一些参考复用。
获取accessToken:https://blog.csdn.net/qq_33789001/article/details/117251545
获取视频流地址:https://blog.csdn.net/qq_33789001/article/details/128223680
Unity WebGl发布问题:
https://blog.csdn.net/qq_33789001/article/details/128900799

功能实现

获取accessToken

管理员账号根据appKey和secret获取accessToken接口.
请求地:https://open.ys7.com/api/lapp/token/get 请求方式:POST
① AccessToken,即访问令牌。接口调用必备的公共参数之一,用于校验接口访问/调用是否有权限,有效期为7天,有效期内不需要重复申请,可以重复使用;
② 有效期7天无法变更,请在业务端使用AccessToken的场景中,校验老Token的有效性和失效时重新获取Token的机制;
③ 新获取Token不会使老Token失效,每个Token独立拥有7天生命周期 接口列表如下:

返回字段
字段名 类型 描述
accessToken String 获取的accessToken
expireTime long 具体过期时间,精确到毫秒
这里的实现代码如下:

    //令牌相关
    [Header("设置萤石云的appKey")]
    public string appKey = "";
    [Header("设置萤石云的appSecret")]
    public string appSecret = "";
    string GetATUrl = "https://open.ys7.com/api/lapp/token/get";
    [HideInInspector]
    public string AT = "";
    DateTime AtEdTime; //令牌失效时间
//请求萤石云的令牌
    void GetAccessToken()
    {
        isGetATing = true;
        List<IMultipartFormSection> formData = new List<IMultipartFormSection>();
        formData.Add(new MultipartFormDataSection("appKey", appKey));
        formData.Add(new MultipartFormDataSection("appSecret", appSecret));

        Global.DoReqWebApiPost(GetATUrl, formData, (bytes) =>
        {
            try
            {
                if (string.IsNullOrEmpty(bytes)) return;
                JsonData datas = JsonMapper.ToObject(bytes);
                if (!datas.ContainsKey("data")) return;
                if (!datas["data"].ContainsKey("accessToken") || !datas["data"].ContainsKey("expireTime")) return;
                AT = datas["data"]["accessToken"].ToString();
                AtEdTime = ConvertToDateTime(datas["data"]["expireTime"].ToString());
            }
            catch (Exception e)
            {
                Debug.LogWarning("获取萤石云AccessToken异常:" + e);
            }
            finally {
                isGetATing = false;
            }
        });
}

要注意的是,如果程序长期运行,需要判断accessToken的过期时间,即使获取并更新,不然会导致功能异常。

获取监控视频流

获取单个的视频流地址,需要使用accessToken为参数,并且protocol的协议必须是ezopen,同时过期时间需要尽量长一些。

    [Header("是否同步流地址")]
    public bool isSyncUrl = true;
    [Header("选择视频流类型")]
    public Streaming_Type streamingType = Streaming_Type.ezopen;
    [Header("监控设备编号")]
    public string deviceSerial;
    [Header("监控频道号")]
public string channelNo;

 //获取视频地址
    void GetSteamingUrl()
    {
        List<IMultipartFormSection> formData = new List<IMultipartFormSection>();
        formData.Add(new MultipartFormDataSection("accessToken", YsAccessTokenMgr.instance.AT));
        formData.Add(new MultipartFormDataSection("deviceSerial", deviceSerial));
        formData.Add(new MultipartFormDataSection("channelNo", channelNo));
        formData.Add(new MultipartFormDataSection("expireTime", "2592000"));
        formData.Add(new MultipartFormDataSection("protocol", ((int)streamingType).ToString()));
        formData.Add(new MultipartFormDataSection("quality", "1"));

        Global.DoReqWebApiPost(StreamUrl, formData, (bytes) =>
        {
            try
            {
                if (string.IsNullOrEmpty(bytes))
                    return;
                JsonData datas = JsonMapper.ToObject(bytes);
                if (!datas.ContainsKey("data")|| !datas["data"].ContainsKey("url"))
                    return;
                videourl = datas["data"]["url"].ToString();
            }
            catch (Exception e)
            {
                Debug.LogWarning("获取萤石云视频流地址异常:" + e);
            }
        });
    }

这里也可以不获取视频流地址,只有视频嵌入式需要ezopen的地址,isSyncUrl 为false时,就不会获取。

打开网页播放视频

我们在点击了监控视频的标签后,就根据视频标签的信息打开监控视频的网页。
这里有两种方式进行播放视频流:视频嵌入式和跳转播放页式,详细说明请看:https://open.ys7.com/bbs/article/20
因为我们的视频窗口是在UI上,所以使用CanvasWebViewPrefab进行网页打开:

 canvasWebView.WebView.LoadUrl(url);

视频嵌入式

代码如下:

 string url = "https://open.ys7.com/ezopen/h5/iframe_se?url=" + path + "&autoplay=1&audio=0&accessToken=" + YsAccessTokenMgr.instance.AT;
        canvasWebView.WebView.LoadUrl(url);

说明如下:
url:监控地址,包含验证码、设备序列号、通道号、清晰度、播放类型
autoplay:1-开启自动播放,未显示字段-关闭自动播放
audio:1-开启音频,未显示字段-关闭音频
accessToken:访问令牌,播放监控地址的必要参数
笔者在测试该方式时发现,在WebGL时,这种方式在一定情况下会出现网页错误,视频未播放的情况:
在这里插入图片描述

跳转播放页式

代码如下:

 string url = " https://open.ys7.com/ezopen/h5/live?autoplay=1&audio=0&accessToken=" + YsAccessTokenMgr.instance.AT + "&hd=1&deviceSerial=" + camlab.deviceSerial + "&channelNo=" + camlab.channelNo;
        canvasWebView.WebView.LoadUrl(url);

说明如下:
live后缀:预览
rec后缀:回放
autoplay:1-开启自动播放,未显示字段-关闭自动播放
audio:1-开启音频,未显示字段-关闭音频
accessToken:访问令牌,播放监控地址的必要参数
validCode:验证码,加密设备播放需要验证码
hd:1-高清(实际为主码流),未显示字段-流畅(实际为子码流)
deviceSerial:设备序列号
channelNo:通道号

工程源码

完整的工程源码:https://download.csdn.net/download/qq_33789001/88135255
无法打开说明审核未通过。

现在工程后,打开项目中的Main.unity场景,选中FunNodes>YsAccessTokenMgr节点设置您自己的appKey和appSecret:
在这里插入图片描述

选中Icon_Camera修改视频标签的信息deviceSerial和channelNo:
在这里插入图片描述

确保的信息都是同一个账号下面的,运行后点击视频图标即可看到播放的效果了。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/817370.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

我的第一个前端(VS code ,Node , lite-server简易服务器,npm 运行)

第一种方式&#xff1a;使用Visual Studio Code创建并运行 第一个前端项目的步骤&#xff0c;如下&#xff1a; 1. 下载和安装Visual Studio Code&#xff1a; 访问Visual Studio Code官方网站&#xff08;Visual Studio Code - Code Editing. Redefined&#xff09;并根据你…

二十三种设计模式第二十篇--备忘录模式

备忘录模式&#xff0c;备忘录模式属于行为型模式。它允许在不破坏封装的情况下捕获和恢复对象的内部状态。保存一个对象的某个状态&#xff0c;以便在适当的时候恢复对象&#xff0c;该模式通过创建一个备忘录对象来保存原始对象的状态&#xff0c;并将其存储在一个负责管理备…

133. 克隆图

给你无向 连通 图中一个节点的引用&#xff0c;请你返回该图的 深拷贝&#xff08;克隆&#xff09;。 图中的每个节点都包含它的值 val&#xff08;int&#xff09; 和其邻居的列表&#xff08;list[Node]&#xff09;。 class Node { public int val; public List&…

互联网医院系统开发:打造便捷高效的医疗服务平台

随着互联网技术的飞速发展&#xff0c;互联网医院系统的出现为医疗行业带来了许多新的机遇和优势。互联网医院系统是一种基于互联网技术的医疗服务平台&#xff0c;旨在提供便捷、高效、个性化的医疗服务。下面将介绍互联网医院系统开发的优势。   提供便捷的医疗服务&#x…

【模仿学习】:离线和在线模仿

一、说明 模仿学习&#xff08;Imitation Learning &#xff09;是机器学习的一种&#xff0c;代理通过观察和模仿专家的行为来学习。在这种方法中&#xff0c;为代理提供了一组所需行为的演示或示例&#xff0c;并通过尝试复制专家的行为来学习输入观察和输出操作之间的映射。…

【单机多卡】torch改造代码为DDP单机多卡分布式并行

torch分布式数据并行DDPtorch.nn.parallel.DistributedDataParallel代码修改记录。&#xff08;要求pytorch_version>1.0&#xff09; 目录 1.&#x1f344;&#x1f344;要修改的地方概览 2.✏️✏️初始化 3.✏️✏️设置当前进程GPU 4.✏️✏️设置sampler 5.✏️✏…

HTML笔记(1)

介绍 浏览器中内置了HTML的解析引擎&#xff0c;通过解析标记语言来展现网页&#xff1b;HTML标签都是预定义好的&#xff1b;Java工程师&#xff1a;后台代码的编写&#xff0c;和数据库打交道&#xff0c;把数据给网页前端的工程师&#xff1b;网页前端工程师&#xff1a;写H…

拯救者Y9000K无线Wi-Fi有时不稳定?该如何解决?

由于不同品牌路由器的性能差异&#xff0c;无法完美兼容最新的无线网卡技术&#xff0c;在连接网络时&#xff08;特别是网络负载较大的情况下&#xff09;&#xff0c;可能会出现Wi-Fi信号断开、无法网络无法访问、延迟突然变大的情况&#xff1b;可尝试下面方法进行调整。 1…

go 如何知道一个对象是分配在栈上还是堆上?

如何判断变量是分配在栈&#xff08;stack&#xff09;上还是堆&#xff08;heap&#xff09;上&#xff1f; Go和C不同&#xff0c;Go局部变量会进行逃逸分析。如果变量离开作用域后没有被引用&#xff0c;则优先分配到栈上&#xff0c;否则分配到堆上。判断语句&#xff1a;…

Stable Doodle:Stability AI推出的一款零门槛AI绘画神器

Stable Doodle是由Stability AI推出的一款零门槛AI绘画神器&#xff0c;可以将简单的草图转化为精美的图像。它可以将随手的塗鴉草稿转化为高畫質的完成圖&#xff0c;让用户能够以更快的速度将想法转化为精美的艺术作品。Stable Doodle利用最新的Stable Diffusion模型&#xf…

智能车域控制器设计

摘要: 本文主要针对ADCU从硬件设计到软件设计的开发流程进行详细阐述,主要包含了需求场景、关键硬件电路、电路可靠性、AUTOSAR架构、CAN通信简介、CAN通信软件设计等。最后基于以上硬件技术和软件技术开发出一款产品级智能驾驶域控制器。 // 智能驾驶域控制器研究现状 //…

iOS开发-实现自定义Tabbar及tabbar按钮动画效果

iOS开发-实现自定义Tabbar及tabbar按钮动画效果 之前整理了一个继承UITabbarController的Tabbar效果 查看 https://blog.csdn.net/gloryFlow/article/details/132012628 这里是继承与UIViewController的INSysTabbarViewController实现及点击tabbar按钮动画效果。 一、INSysT…

学习记录——TransNormerLLM

Scaling TransNormer to 175 Billion Parametes 线性注意力的Transformer大模型 2023 Transformer 存在局限。首要的一点&#xff0c;它们有着对于序列长度的二次时间复杂度&#xff0c;这会限制它们的可扩展性并拖累训练和推理阶段的计算资源和时间效率。 TransNormerLLM 是首…

中小企业如何低成本实施MES管理系统

中小企业在市场竞争中需要有高效的管理体系来支持其运营和发展。中小企业MES管理系统是一种先进的管理系统&#xff0c;可以提升工厂智能化水平&#xff0c;提高生产效率&#xff0c;是中小企业必须采取的有效管理工具。然而&#xff0c;由于资金和技术的限制&#xff0c;中小企…

Java API指南:掌握常用工具类与字符串操作

文章目录 1. API简介2. Java API的使用2.1 创建和使用Java API工具类2.2 使用String类进行字符串操作 结语 导语&#xff1a; Java作为一门功能强大的编程语言&#xff0c;其成功之处不仅在于语法结构的简洁明了&#xff0c;更因为其丰富的API&#xff08;Application Programm…

面向对象中的多态性

一、权限修饰符 public, 缺省&#xff0c; protected&#xff0c;private 二、this和super关键字 this:表示当前对象 super:表示父类声明的成员 原则&#xff1a;遵循就近原则和追根溯源原则。 三、Object类 java.lang.Object类是所有java类的超类&#xff0c;即所有的J…

微信小程序测试要点

一、什么是小程序&#xff1f; 可以将小程序理解为轻便的APP&#xff0c;不用安装就可以使用的应用。用户通过扫一扫或者搜索的方式&#xff0c;就可以打开应用。 小程序最主要的特点是内嵌于微信之中&#xff0c;而使用小程序的目的是为了能够方便用户不在受下载多个APP的烦…

更好搭建负载测试环境的六个技巧

如果你如我昨天谈到的客户一样&#xff0c;花费了24到48个小时用于每个负载测试环境的搭建&#xff0c;那你的测试及构建部署能力绝对是受限的。 搭建一个仿真测试环境对于做好负载测试非常重要&#xff0c;同时它也是一个非常具有挑战性的任务&#xff0c;需要考虑技术解决、…

2023 7-31

题目1 寻找不同二叉树两节点的公共祖先 递归解法 仔细看这个解法更加容易理解: l、r 非空时,说明 p、q 分居 root 的两侧,root 就是 LCAl、r 任一为空,说明 LCA 位于另一子树或其祖先中代码 /*** Definition for a binary tree node.* struct TreeNode {* int val;* …

展锐USB充电图标更新流程

介绍 power_supply 目录下online节点是用于判断是否插入battery、ac(外部电源) 和USB 的节点&#xff0c;目录在sys/class/power_supply/battery(ac、usb)/online&#xff0c;主要用于在StatusBar 上显示充电的闪电图标。 SystemUI层介绍 流程介绍 在SystemUI 中控制充电图…