WEB端播放华为海康大华视频方案

  • A+
所属分类:.NET技术

WEB端播放华为海康大华视频方案

类似标题:谷歌浏览器播放华为海康大华视频方案 

方案

以下方案相当于给需要播放视频的WEB系统做了一个专用的浏览器,通过专用浏览器的CS客户端组件播放视频,当然,这个专用浏览器是需要安装的 
  1. 使用WPF编写一个客户端程序,嵌入CefSharp浏览器控件,除了浏览器之外无其它界面元素,客户端窗体也没有边框和标题栏,如效果图所示
  2. 浏览器加载WEB系统,WEB系统登录后把Token传给WPF客户端,客户端使用Token可以请求WEB系统的接口,获取数据。
  3. WEB系统需要播放实时视频或录像回放时,使用nanoid.js为播放器生成一个唯一标识,计算播放器在浏览器中的位置、长宽,然后把播放器唯一标识、位置、长宽、摄像机设备ID集合通过JS调用C#方法传给客户端,客户端根据位置、长宽显示播放器组件。

说明

  1. WEB端为Vue开发的系统,WEB系统内有Tab页,如果有子系统跳转,或window.open,客户端会打开新窗体加载跳转页

效果图

WEB端播放华为海康大华视频方案

效果图说明

  1. 页面为BS页面,视频弹窗是用layui做的,也是BS的,视频播放是CS控件,WPF通过WindowsFormsHost加载的Winform控件播放视频
  2. 当BS弹窗最大化、还原、移动时,通过JS调用C#方法更新视频播放CS控件的位置、长宽
  3. BS弹窗最小化时隐藏视频播放CS控件,还原时显示
  4. BS弹窗关闭时,释放视频播放CS控件占用的资源
  5. 视频播放CS控件,全屏功能正常,单视频全屏功能正常,单视频仅在视频播放CS控件中最大化显示功能正常

WEB端测试页面代码

<!DOCTYPE html> <html>  <head>     <title>CefSharpDemo</title>      <meta charset="utf-8" />     <meta http-equiv="X-UA-Compatible" content="IE=edge">     <meta name="viewport" content="width=device-width, initial-scale=1">      <script type="text/javascript" src="jquery-1.9.1.js"></script>     <script type="text/javascript" src="nanoid.js"></script>     <script src="layui/layui.js"></script>      <style type="text/css">         input {             height: 21px;             line-height: 21px;             border: solid 1px #666;             outline: none;         }     </style>      <script type="text/javascript">         //测试JS调用C#方法         function testCallCSharp() {             if (jsObjExists()) jsObj.TestCallCSharp("测试参数123");         }          //测试C#调用JS方法         function testCallJs(data) {             alert("测试C#调用JS方法:" + data);         }          //判断jsObj是否存在         function jsObjExists() {             return typeof (jsObj) != typeof (undefined);         }          //获取url参数         getQueryString = function (name) {             var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)");             var r = window.location.search.substring(1).match(reg);             if (r != null) return decodeURIComponent(r[2]);             return null;         }     </script> </head>  <body>     <div style="margin-bottom: 10px; font-weight: bold;">         <span id="title"></span>     </div>     <div style="height: 30px;">         <span>测试输入框:</span><input type="text" />     </div>     <div style="height: 30px; user-select: none;">         <span id="msg" style="line-height: 30px;"></span>     </div>     <div style="height: 30px; user-select: none;">         <span id="msg2" style="line-height: 30px;"></span>     </div>      <div style="user-select: none;">         <input type="button" value="测试调用C#方法" title="测试调用C#方法" onclick="testCallCSharp()" />         <input type="button" value="跳转" title="跳转" onclick="openNew()" />         <input type="button" value="设置Token或登录信息" title="设置Token或登录信息" onclick="setToken()" />     </div>     <div style="user-select: none; margin-top: 20px;">         <input type="button" value="播放单个视频" title="播放单个视频" onclick="playSingle()" />         <input type="button" value="播放多路视频" title="播放多路视频" onclick="playMulti()" />         <input type="button" value="追加播放" title="追加播放" onclick="appendToPlayMulti()" />         <input type="button" value="录像回放" title="录像回放" onclick="playRecord()" />         <input type="button" value="追加录像回放" title="追加录像回放" onclick="appendToPlayRecord()" />     </div>     <div style="position: absolute; float: right; top:5px;right:5px;">         <input type="button" value="关闭" title="关闭" onclick="closeApp()" />     </div>      <!-- 一个BS组件 -->     <div         style="position: absolute; float: right; top: 200px; right: 100px; width: 300px; height: 300px; background-color:#FFEE33; padding: 10px; color: #333333;">         <span>             这是一个BS组件,视频能把我挡住         </span>         <br />         <span style="margin-top: 100px; display: block;">             这是一个BS组件,视频能把我挡住         </span>         <br />         <span style="margin-top: 100px; display: block;">             这是一个BS组件,视频能把我挡住         </span>     </div>      <script type="text/javascript">         //JS调用C#方法的接口,jsObj.XXX(...)         //下面所有方法,调用的C#方法是首字母大写          let title = getQueryString("title");         $("#title").text(title);          //页面加载完成时调用C#方法         if (jsObjExists()) jsObj.WebPageLoaded(title);          //跳转         function openNew() {             window.open("http://localhost:8066/?title=跳转页");         }          //设置Token或登录信息         function setToken() {             if (jsObjExists()) jsObj.SetToken("这是登录信息或Token");         }          //窗口ID         let windowIdForSingle;         let windowIdForMulti;         let windowIdForPlayRecord;          //播放单个视频         function playSingle() {             if (windowIdForSingle) {                 if (jsObjExists()) jsObj.ShowWindow(windowIdForSingle);                 alert("单个视频播放窗口已存在");                 return;             }              let moveWindow = function () {                 if (!windowIdForSingle) return;                 let left = parseFloat($("#layui-layer" + handle).css('left').replace('px', ''));                 let top = parseFloat($("#layui-layer" + handle).css('top').replace('px', '')) + 51;                 let width = $("#layui-layer" + handle).width();                 let height = $("#layui-layer" + handle).height() - 51;                 jsObj.MoveWindow(windowIdForSingle, left, top, width, height);             }              let interval = setInterval(() => {                 moveWindow();             }, 100);              windowIdForSingle = nanoid(); //窗口ID             let handle = layer.open({                 type: 1,                 title: '视频',                 shadeClose: false,                 shade: false,                 maxmin: true, //开启最大化最小化按钮                 area: ['500px', '351px'],                 content: '<div>空白页面</div>',                 cancel: function () {                     if (jsObjExists()) {                         clearInterval(interval);                         jsObj.CloseWindow(windowIdForSingle);                         windowIdForSingle = undefined;                     }                 },                 min: function () {                     if (jsObjExists()) {                         jsObj.HideWindow(windowIdForSingle);                     }                 },                 restore: function () {                     if (jsObjExists()) {                         jsObj.ShowWindow(windowIdForSingle);                         moveWindow();                     }                 },                 full: function () {                     moveWindow();                 }             });              let left = parseFloat($("#layui-layer" + handle).css('left').replace('px', ''));             let top = parseFloat($("#layui-layer" + handle).css('top').replace('px', '')) + 51;             let width = 500;             let height = 300;              let cameraId = "BC77ACF9F04D1A48E053070C0822157A"; //摄像机设备ID              if (jsObjExists()) jsObj.PlaySingle(left, top, width, height, windowIdForSingle, cameraId);         }          //播放多个视频         function playMulti() {             if (windowIdForMulti) {                 if (jsObjExists()) jsObj.ShowWindow(windowIdForMulti);                 alert("多路视频播放窗口已存在,您可以追加播放");                 return;             }              let moveWindow = function () {                 if (!windowIdForMulti) return;                 let left = parseFloat($("#layui-layer" + handle).css('left').replace('px', ''));                 let top = parseFloat($("#layui-layer" + handle).css('top').replace('px', '')) + 51;                 let width = $("#layui-layer" + handle).width();                 let height = $("#layui-layer" + handle).height() - 51;                 jsObj.MoveWindow(windowIdForMulti, left, top, width, height);             }              let interval = setInterval(() => {                 moveWindow();             }, 100);              windowIdForMulti = nanoid(); //窗口ID             let handle = layer.open({                 type: 1,                 title: '视频',                 shadeClose: false,                 shade: false,                 maxmin: true, //开启最大化最小化按钮                 area: ['1100px', '651px'],                 content: '<div>空白页面</div>',                 cancel: function () {                     if (jsObjExists()) {                         clearInterval(interval);                         jsObj.CloseWindow(windowIdForMulti);                         windowIdForMulti = undefined;                     }                 },                 min: function () {                     if (jsObjExists()) {                         jsObj.HideWindow(windowIdForMulti);                     }                 },                 restore: function () {                     if (jsObjExists()) {                         jsObj.ShowWindow(windowIdForMulti);                         moveWindow();                     }                 },                 full: function () {                     moveWindow();                 }             });              let left = parseFloat($("#layui-layer" + handle).css('left').replace('px', ''));             let top = parseFloat($("#layui-layer" + handle).css('top').replace('px', '')) + 51;             let width = 1000;             let height = 600;             let cameraIds = "BC77ACF9F04D1A48E053070C0822157A,BC77ACF9EFE01A48E053070C0822157A"; //摄像机设备ID              if (jsObjExists()) jsObj.PlayMulti(left, top, width, height, windowIdForMulti, cameraIds);         }          //追加播放         function appendToPlayMulti() {             let cameraIds = "BC77ACF9EFCE1A48E053070C0822157A,BC77ACF9F0801A48E053070C0822157A"; //摄像机设备ID              if (jsObjExists()) jsObj.AppendToPlayMulti(windowIdForMulti, cameraIds);         }          //录像回放         function playRecord() {             layer.msg("请稍等......", { icon: 1, offset: "t" });              if (windowIdForPlayRecord) {                 if (jsObjExists()) jsObj.ShowWindow(windowIdForPlayRecord);                 alert("视频回放弹框已存在,您可以追加回放");                 return;             }              let moveWindow = function () {                 if (!windowIdForPlayRecord) return;                 let left = parseFloat($("#layui-layer" + handle).css('left').replace('px', ''));                 let top = parseFloat($("#layui-layer" + handle).css('top').replace('px', '')) + 51;                 let width = $("#layui-layer" + handle).width();                 let height = $("#layui-layer" + handle).height() - 51;                 jsObj.MoveWindow(windowIdForPlayRecord, left, top, width, height);             }              let interval = setInterval(() => {                 moveWindow();             }, 100);              windowIdForPlayRecord = nanoid(); //窗口ID             let handle = layer.open({                 type: 1,                 title: '视频',                 shadeClose: false,                 shade: false,                 maxmin: true, //开启最大化最小化按钮                 area: ['1100px', '651px'],                 content: '<div style="padding: 20px;">请稍等......</div>',                 cancel: function () {                     if (jsObjExists()) {                         clearInterval(interval);                         jsObj.CloseWindow(windowIdForPlayRecord);                         windowIdForPlayRecord = undefined;                     }                 },                 min: function () {                     if (jsObjExists()) {                         jsObj.HideWindow(windowIdForPlayRecord);                     }                 },                 restore: function () {                     if (jsObjExists()) {                         jsObj.ShowWindow(windowIdForPlayRecord);                         moveWindow();                     }                 },                 full: function () {                     moveWindow();                 }             });              let left = parseFloat($("#layui-layer" + handle).css('left').replace('px', ''));             let top = parseFloat($("#layui-layer" + handle).css('top').replace('px', '')) + 51;             let width = 1100;             let height = 600;              let cameraId = "BC77ACF9F04D1A48E053070C0822157A"; //摄像机设备ID             let startTime = "2022-03-11 15:00:00";             let endTime = "2022-03-11 16:00:00";              if (jsObjExists()) jsObj.PlayRecord(left, top, width, height, windowIdForPlayRecord, cameraId, startTime, endTime);         }          //追加录像回放         function appendToPlayRecord() {             layer.msg("请稍等......", { icon: 1, offset: "t" });              let cameraIds = "BC77ACF9EFCE1A48E053070C0822157A"; //摄像机设备ID             let startTime = "2022-03-11 16:00:00";             let endTime = "2022-03-11 17:00:00";              if (jsObjExists()) jsObj.AppendToPlayRecord(windowIdForPlayRecord, cameraIds, startTime, endTime);         }          //关闭App         function closeApp() {             if (jsObjExists()) jsObj.CloseApp();         }      </script> </body>  </html>