hikvision-player.vue 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351
  1. <!-- 海康威视组件
  2. https://blog.csdn.net/weixin_53322542/article/details/134334347
  3. -->
  4. <template>
  5. <div :id="state.id" class="playWnd"></div>
  6. <img class="fullscreen" src="@/assets/images/video/fullscreen.png" @click.stop="doubleClick" />
  7. </template>
  8. <script setup lang="ts" name="hikvision-player">
  9. const WebControl = window.WebControl; //index.html引入 直接从window里面拿到sdk
  10. const JSEncrypt = window.JSEncrypt; //index.html引入 直接从window里面拿到sdk
  11. const props = defineProps({
  12. wsUrl: {
  13. type: String //视频监控code
  14. },
  15. objData: {}
  16. });
  17. const emits = defineEmits(['exitFullScreen']);
  18. const objData = props.objData;
  19. // console.log(props.wsUrl, '====>wsurl')
  20. const state = reactive({
  21. id: 'playWnd' + Math.random().toString(16).slice(2), //多个监控同时显示需要不同的id
  22. idWidth: 0 as any,
  23. idHeight: 0 as any,
  24. initCount: 0,
  25. pubKey: '',
  26. oWebControl: null as any
  27. });
  28. // console.log(state)
  29. //创建播放实例
  30. const initPlugin = () => {
  31. console.log('initPlugin');
  32. state.oWebControl = new WebControl({
  33. szPluginContainer: state.id, // 指定容器id
  34. iServicePortStart: 15900, // 指定起止端口号,建议使用该值
  35. iServicePortEnd: 15900,
  36. // szClassId: '23BF3B0A-2C56-4D97-9C03-0CB103AA8F11', // 用于IE10使用ActiveX的clsid
  37. cbConnectSuccess: function () {
  38. // 创建WebControl实例成功
  39. state.oWebControl
  40. .JS_StartService('window', {
  41. // WebControl实例创建成功后需要启动服务
  42. dllPath: './VideoPluginConnect.dll' // 值"./VideoPluginConnect.dll"写死
  43. })
  44. .then(
  45. () => {
  46. console.log('启动成功');
  47. // 启动插件服务成功
  48. state.oWebControl.JS_SetWindowControlCallback({
  49. // 设置消息回调
  50. cbIntegrationCallBack: cbIntegrationCallBack
  51. });
  52. state.oWebControl.JS_CreateWnd(state.id, state.idWidth, state.idHeight).then(() => {
  53. console.log('JS_CreateWnd success');
  54. //JS_CreateWnd创建视频播放窗口,宽高可设定
  55. init(); // 创建播放实例成功后初始化
  56. });
  57. },
  58. function () {
  59. console.log('启动失败');
  60. // 启动插件服务失败
  61. }
  62. );
  63. },
  64. cbConnectError: function () {
  65. // 创建WebControl实例失败
  66. state.oWebControl = null;
  67. console.log('插件未启动,正在尝试启动,请稍候...');
  68. WebControl.JS_WakeUp('VideoWebPlugin://'); // 程序未启动时执行error函数,采用wakeup来启动程序
  69. state.initCount++;
  70. if (state.initCount < 3) {
  71. setTimeout(function () {
  72. initPlugin();
  73. }, 3000);
  74. } else {
  75. console.log('插件启动失败,请检查插件是否安装!');
  76. }
  77. },
  78. cbConnectClose: function (bNormalClose) {
  79. // 异常断开:bNormalClose = false
  80. // JS_Disconnect正常断开:bNormalClose = true
  81. console.log('cbConnectClose', bNormalClose);
  82. state.oWebControl = null;
  83. if (!bNormalClose) {
  84. console.log('插件未启动,正在尝试启动,请稍候...');
  85. WebControl.JS_WakeUp('VideoWebPlugin://');
  86. state.initCount++;
  87. if (state.initCount < 3) {
  88. setTimeout(function () {
  89. initPlugin();
  90. }, 3000);
  91. } else {
  92. console.log('插件启动失败,请检查插件是否安装!');
  93. }
  94. }
  95. }
  96. });
  97. };
  98. // 设置窗口控制回调
  99. const setCallbacks = () => {
  100. state.oWebControl.JS_SetWindowControlCallback({
  101. cbIntegrationCallBack: cbIntegrationCallBack
  102. });
  103. };
  104. // 推送消息
  105. const cbIntegrationCallBack = (oData) => {
  106. console.log(oData.responseMsg, '--oData');
  107. if (oData.responseMsg.type === 7) {
  108. doubleClick();
  109. }
  110. if(oData.responseMsg.msg.result == 1025) {
  111. emits('exitFullScreen');
  112. }
  113. };
  114. // 双击窗口放大
  115. const doubleClick = () => {
  116. state.oWebControl
  117. .JS_RequestInterface({
  118. funcName: 'setFullScreen'
  119. })
  120. .then(function (oData) {
  121. console.log(oData);
  122. // showCBInfo(JSON.stringify(oData ? oData.responseMsg : ''))
  123. });
  124. };
  125. //初始化
  126. const init = () => {
  127. getPubKey(() => {
  128. // 请自行修改以下变量值
  129. let appkey = objData.appkey; //综合安防管理平台提供的appkey,必填
  130. let secret = setEncrypt(objData.secret); //综合安防管理平台提供的secret,必填
  131. let ip = objData.ip; //综合安防管理平台IP地址,必填
  132. let playMode = objData.playMode; //初始播放模式:0-预览,1-回放
  133. let port = objData.port; //综合安防管理平台端口,若启用HTTPS协议,默认443
  134. let snapDir = 'D:\\SnapDir'; //抓图存储路径
  135. let videoDir = 'D:\\VideoDir'; //紧急录像或录像剪辑存储路径
  136. let layout = objData.layout; //playMode指定模式的布局
  137. let enableHTTPS = 1; //是否启用HTTPS协议与综合安防管理平台交互,这里总是填1
  138. let encryptedFields = 'secret'; //加密字段,默认加密领域为secret
  139. let showToolbar = objData.showToolbar; //是否显示工具栏,0-不显示,非0-显示
  140. let showSmart = 0; //是否显示移动框线框,0-不显示,非0-显示
  141. let buttonIDs = '0,16,256,257,258,259,260,512,513,514,515,516,517,768,769'; //自定义工具条按钮
  142. // 请自行修改以上变量值
  143. state.oWebControl
  144. .JS_RequestInterface({
  145. funcName: 'init',
  146. argument: JSON.stringify({
  147. appkey: appkey, //API网关提供的appkey
  148. secret: secret, //API网关提供的secret
  149. ip: ip, //API网关IP地址
  150. playMode: playMode, //播放模式(决定显示预览还是回放界面)
  151. port: port, //端口
  152. snapDir: snapDir, //抓图存储路径
  153. videoDir: videoDir, //紧急录像或录像剪辑存储路径
  154. layout: layout, //布局
  155. enableHTTPS: enableHTTPS, //是否启用HTTPS协议
  156. encryptedFields: encryptedFields, //加密字段
  157. showToolbar: showToolbar, //是否显示工具栏
  158. showSmart: showSmart, //是否显示智能信息
  159. buttonIDs: buttonIDs //自定义工具条按钮
  160. })
  161. })
  162. .then(function (oData: any) {
  163. console.log(oData, 'oData');
  164. state.oWebControl.JS_Resize(state.idWidth, state.idHeight); // 初始化后resize一次,规避firefox下首次显示窗口后插件窗口未与DIV窗口重合问题
  165. props.wsUrl && previewClick('') && doubleClick();
  166. });
  167. });
  168. };
  169. //获取公钥
  170. const getPubKey = (callback: any) => {
  171. state.oWebControl
  172. .JS_RequestInterface({
  173. funcName: 'getRSAPubKey',
  174. argument: JSON.stringify({
  175. keyLength: 1024
  176. })
  177. })
  178. .then((oData: { responseMsg: { data: string } }) => {
  179. console.log('getPubKey', oData);
  180. if (oData.responseMsg.data) {
  181. state.pubKey = oData.responseMsg.data;
  182. callback();
  183. }
  184. });
  185. };
  186. //RSA加密
  187. const setEncrypt = (value: string) => {
  188. var encrypt = new JSEncrypt();
  189. encrypt.setPublicKey(state.pubKey);
  190. return encrypt.encrypt(value);
  191. };
  192. // 监听resize事件,使插件窗口尺寸跟随DIV窗口变化
  193. window.addEventListener('resize', () => {
  194. console.log('resize');
  195. if (state.oWebControl != null) {
  196. getElementWidth();
  197. state.oWebControl.JS_Resize(state.idWidth, state.idHeight);
  198. // setWndCover();
  199. }
  200. });
  201. // 监听滚动条scroll事件,使插件窗口跟随浏览器滚动而移动
  202. window.addEventListener('scroll', () => {
  203. if (state.oWebControl != null) {
  204. getElementWidth();
  205. state.oWebControl.JS_Resize(state.idWidth, state.idHeight);
  206. // setWndCover();
  207. }
  208. });
  209. //视频预览功能
  210. const previewClick = (data) => {
  211. let wsUrl = props.wsUrl;
  212. let urlList = wsUrl.split(",");
  213. console.log('previewClick ===========>>>>', urlList);
  214. urlList.forEach((indexCode)=>{
  215. var cameraIndexCode = indexCode; //获取输入的监控点编号值,必填
  216. var streamMode = 1; //主子码流标识:0-主码流,1-子码流
  217. var transMode = 1; //传输协议:0-UDP,1-TCP
  218. var gpuMode = 1; //是否启用GPU硬解,0-不启用,1-启用
  219. var wndId = -1; //播放窗口序号(在2x2以上布局下可指定播放窗口)
  220. state.oWebControl.JS_RequestInterface({
  221. funcName: 'startPreview',
  222. argument: JSON.stringify({
  223. cameraIndexCode: cameraIndexCode, //监控点编号
  224. streamMode: streamMode, //主子码流标识
  225. transMode: transMode, //传输协议
  226. gpuMode: gpuMode, //是否开启GPU硬解
  227. wndId: wndId //可指定播放窗口
  228. })
  229. });
  230. console.log(state.oWebControl.JS_RequestInterface, ' ------face');
  231. console.log('当前的编号', cameraIndexCode);
  232. console.log('执行完成');
  233. })
  234. return true;
  235. };
  236. const playbackClick = (data, begin_time, end_time) => {
  237. console.log('playbackClick ===========>>>> ');
  238. var cameraIndexCode = data ? data : (props.wsUrl as any);
  239. var startTimeStamp = begin_time; //回放开始时间戳
  240. var endTimeStamp = end_time; //回放结束时间戳
  241. var recordLocation = 0; //录像存储位置:0-中心存储,1-设备存储
  242. var transMode = 1; //传输协议:0-UDP,1-TCP
  243. var gpuMode = 0; //是否启用GPU硬解,0-不启用,1-启用
  244. var wndId = -1; //播放窗口序号(在2x2以上布局下可指定播放窗口)
  245. state.oWebControl.JS_RequestInterface({
  246. funcName: 'startPlayback',
  247. argument: JSON.stringify({
  248. cameraIndexCode: cameraIndexCode, //监控点编号
  249. startTimeStamp: Math.floor(startTimeStamp / 1000).toString(), //回放开始时间戳
  250. endTimeStamp: Math.floor(endTimeStamp / 1000).toString(), //回放结束时间戳
  251. recordLocation: recordLocation, //录像存储位置
  252. transMode: transMode, //传输协议
  253. gpuMode: gpuMode, //是否开启GPU硬解
  254. wndId: wndId //可指定播放窗口
  255. })
  256. });
  257. console.log(state.oWebControl.JS_RequestInterface, ' ------face');
  258. console.log('当前的编号', cameraIndexCode);
  259. console.log('执行完成');
  260. };
  261. // 停止全部预览
  262. const stopAllPreview = () => {
  263. state.oWebControl.JS_RequestInterface({
  264. funcName: 'stopAllPreview'
  265. });
  266. console.log('stopAllPreview');
  267. };
  268. // 获取元素宽高
  269. const getElementWidth = () => {
  270. let scale = window.innerWidth / 3840;
  271. state.idWidth = document.getElementById(state.id)?.offsetWidth;
  272. state.idHeight = document.getElementById(state.id)?.offsetHeight;
  273. state.idWidth = parseInt(state.idWidth * scale);
  274. state.idHeight = parseInt(state.idHeight * scale);
  275. };
  276. onMounted(() => {
  277. getElementWidth();
  278. initPlugin();
  279. });
  280. onActivated(() => {
  281. getElementWidth();
  282. initPlugin();
  283. });
  284. onDeactivated(() => {
  285. console.log('销毁了');
  286. state.oWebControl.JS_HideWnd();
  287. state.oWebControl.JS_Disconnect().then(
  288. function () {
  289. //断开与插件服务连接成功
  290. console.log('断开与插件服务连接成功');
  291. },
  292. function () {
  293. //断开与插件服务连接失败
  294. console.log('断开与插件服务连接失败');
  295. }
  296. );
  297. });
  298. onUnmounted(() => {
  299. console.log('销毁了');
  300. state.oWebControl.JS_HideWnd();
  301. state.oWebControl.JS_Disconnect().then(
  302. function () {
  303. //断开与插件服务连接成功
  304. console.log('断开与插件服务连接成功');
  305. },
  306. function () {
  307. //断开与插件服务连接失败
  308. console.log('断开与插件服务连接失败');
  309. }
  310. );
  311. });
  312. // 暴露给父组件调用
  313. defineExpose({
  314. previewClick,
  315. playbackClick,
  316. stopAllPreview
  317. });
  318. </script>
  319. <style>
  320. .playWnd {
  321. width: 100%;
  322. height: 100%;
  323. }
  324. .fullscreen {
  325. width: 28px;
  326. height: 28px;
  327. background: url('@/assets/images/video/fullscreen.png');
  328. cursor: pointer;
  329. position: absolute;
  330. top: 20px;
  331. right: 20px;
  332. z-index: 10;
  333. }
  334. </style>