当前位置:   article > 正文

Springboot+Vue3 整合海康获取视频流并展示_mgc取流服务

mgc取流服务

目录

1.后端

1.1 导入依赖

1.2 代码实战

2.前端

2.1 首先安装海康的web插件,前端vue3代码如下:


1.后端

1.1 导入依赖

  1. <dependency>
  2. <groupId>com.hikvision.ga</groupId>
  3. <artifactId>artemis-http-client</artifactId>
  4. <version>1.1.3</version>
  5. </dependency>
  6. <dependency>
  7. <groupId>com.alibaba</groupId>
  8. <artifactId>fastjson</artifactId>
  9. <version>1.2.51</version>
  10. </dependency>

1.2 代码实战

新建ArtemisPostTest类,代码如下,设置认证信息,设置ArtemisConfig的host,appKey(AK),appSecret(SK)。设置接口URL。.设置接口入参。接口调用,调用doPostStringArtemis方法(该方法内部实现了登入认证逻辑),传入接口URL,接口入参,数据提交类型等信息,完成接口调用。

  1. public class ArtemisPostTest {
  2. static {
  3. ArtemisConfig.host = "";// 代理API网关nginx服务器ip端口
  4. ArtemisConfig.appKey = "";// 秘钥appkey
  5. ArtemisConfig.appSecret = "";// 秘钥appSecret
  6. }
  7. /**
  8. * 能力开放平台的网站路径
  9. * TODO 路径不用修改,就是/artemis
  10. */
  11. private static final String ARTEMIS_PATH = "/artemis";
  12. public static String path="";
  13. public static JSONObject jsonBody=new JSONObject();
  14. /**
  15. * 调用POST请求类型(application/json)接口,这里以入侵报警事件日志为例
  16. * https://open.hikvision.com/docs/918519baf9904844a2b608e558b21bb6#e6798840
  17. *
  18. * @return
  19. */
  20. public static String callPostStringApi(){
  21. /**
  22. * http://10.33.47.50/artemis/api/scpms/v1/eventLogs/searches
  23. * 根据API文档可以看出来,这是一个POST请求的Rest接口,而且传入的参数值为一个json
  24. * ArtemisHttpUtil工具类提供了doPostStringArtemis这个函数,一共六个参数在文档里写明其中的意思,因为接口是https,
  25. * 所以第一个参数path是一个hashmap类型,请put一个key-value,query为传入的参数,body为传入的json数据
  26. * 传入的contentType为application/json,accept不指定为null
  27. * header没有额外参数可不传,指定为null
  28. *
  29. */
  30. final String getCamsApi = ARTEMIS_PATH +ArtemisPostTest.path;
  31. Map<String, String> path = new HashMap<String, String>(2) {
  32. {
  33. put("https://", getCamsApi);//根据现场环境部署确认是http还是https
  34. }
  35. };
  36. String body = jsonBody.toJSONString();
  37. String result = ArtemisHttpUtil.doPostStringArtemis(path,body,null,null,"application/json",null);// post请求application/json类型参数
  38. return result;
  39. }
  40. }

新建实体类Camera代码如下:

  1. @Data
  2. @AllArgsConstructor
  3. @NoArgsConstructor
  4. @Accessors(chain = true)
  5. public class Camera {
  6. String cameraIndexCode;
  7. String camereName;
  8. String url;
  9. }

在Controller中进行调用,代码如下:

首先根据分页获取监控点列表,这里获取的是第三页,每一页为六个监控点。

查询监控点列表v2

接口说明

根据条件查询目录下有权限的监控点列表

接口版本

v2

接口地址

/api/resource/v2/camera/search

请求方法

POST

数据提交方式

application/json

 然后根据监控点唯一的标识获取预览url

接口说明

1.平台正常运行;平台已经添加过设备和监控点信息。
2.平台需要安装mgc取流服务。
3.三方平台通过openAPI获取到监控点数据,依据自身业务开发监控点导航界面。
4.调用本接口获取预览取流URL,协议类型包括:hik、rtsp、rtmp、hls。
5.通过开放平台的开发包进行实时预览或者使用标准的GUI播放工具进行实时预览。
6.为保证数据的安全性,取流URL设有有效时间,有效时间为5分钟。

接口版本

v2

接口地址

/api/video/v2/cameras/previewURLs

请求方法

POST

数据提交方式

application/json

最后就是进行属性的赋值,赋值给建立的Camera 实体类。

  1. @GetMapping("/test")
  2. public List<Camera> test(){
  3. ArtemisPostTest.path="/api/resource/v1/cameras";
  4. ArtemisPostTest.jsonBody.clear();
  5. ArtemisPostTest.jsonBody.put("pageNo", 3);
  6. ArtemisPostTest.jsonBody.put("pageSize", 6);
  7. String StringeResult = ArtemisPostTest.callPostStringApi();
  8. JSONObject result = (JSONObject) JSONObject.parse(StringeResult);
  9. String data = result.get("data").toString();
  10. JSONObject resultdata = (JSONObject) JSONObject.parse(data);
  11. JSONArray list = resultdata.getJSONArray("list");
  12. // System.out.println("StringeResult结果示例: "+JSONObject.toJSON(StringeResult));
  13. // callPostImgStringApi();
  14. ArtemisPostTest.path="/api/video/v2/cameras/previewURLs";
  15. List<Camera> cameraList=new ArrayList<>();
  16. for (Object i : list) {
  17. Camera camera=new Camera();
  18. JSONObject jsonObject = (JSONObject) JSONObject.parse(i.toString());
  19. String cameraIndexCode = jsonObject.get("cameraIndexCode").toString();
  20. String cameraName = jsonObject.get("cameraName").toString();
  21. ArtemisPostTest.jsonBody.clear();
  22. ArtemisPostTest.jsonBody.put("cameraIndexCode",cameraIndexCode);
  23. ArtemisPostTest.jsonBody.put("protocol","rtsp");
  24. String m = ArtemisPostTest.callPostStringApi();
  25. JSONObject jsonObject1 = (JSONObject) JSONObject.parse(m);
  26. JSONObject data1 = (JSONObject) jsonObject1.get("data");
  27. String url = data1.get("url").toString();
  28. camera.setCameraIndexCode(cameraIndexCode).setCamereName(cameraName).setUrl(url);
  29. cameraList.add(camera);
  30. }
  31. return cameraList;
  32. }

2.前端

2.1 首先安装海康的web插件,前端vue3代码如下:

  1. <template>
  2. <div style="display: flex;flex-direction: row;flex-wrap: wrap">
  3. <div v-for="item in state.list">
  4. <el-button @click="go(item.cameraIndexCode)">预览{{item.camereName}}</el-button>
  5. </div>
  6. </div>
  7. <div class="main" ref="playWndBox">
  8. <div
  9. id="playWnd"
  10. class="playWnd"
  11. :style="{
  12. height: playWndHeight + 'px',
  13. width: playWndWidth + 'px',
  14. }"
  15. ></div>
  16. </div>
  17. </template>
  18. <script setup>
  19. import { ref, onMounted, onBeforeUnmount, getCurrentInstance, nextTick,reactive } from 'vue'
  20. import axios from "../utils/axios.js"
  21. const playWndBox = ref(null)
  22. let playWndHeight = ref('')
  23. let playWndWidth = ref('')
  24. let pubKey = ref('')
  25. let oWebControl = ref(null)
  26. let objData = ref({
  27. appkey: "", //海康提供的appkey
  28. ip: "", //海康提供的ip
  29. secret: "", //海康提供的secret
  30. port: 443,
  31. playMode: 0, // 0 预览 1回放
  32. layout: "1x1", //页面展示的模块数【16】
  33. })
  34. const go=(data)=>{
  35. previewVideo(data)
  36. }
  37. const state=reactive({
  38. list:[]
  39. })
  40. const load=()=>{
  41. axios.get("/test").then(res=>{
  42. state.list=res
  43. console.log(res)
  44. })
  45. }
  46. load()
  47. onMounted(() => {
  48. // 获取页面的实例对象
  49. const pageInstance = getCurrentInstance();
  50. // 获取dom节点对象
  51. const tagDomObj = pageInstance.refs.playWndBox;
  52. playWndHeight.value = tagDomObj.clientHeight;
  53. playWndWidth.value = tagDomObj.clientWidth;
  54. // 监听scroll事件,使插件窗口尺寸跟随DIV窗口变化
  55. window.addEventListener("scroll", () => {
  56. console.log(5);
  57. // return
  58. if (oWebControl.value != null) {
  59. oWebControl.JS_Resize(
  60. tagDomObj.clientWidth,
  61. tagDomObj.clientHeight
  62. );
  63. this.setWndCover();
  64. }
  65. });
  66. // 监听resize事件,使插件窗口尺寸跟随DIV窗口变化
  67. window.addEventListener("resize", (e) => {
  68. console.log(0);
  69. if (oWebControl.value != null) {
  70. oWebControl.JS_Resize(
  71. tagDomObj.clientWidth,
  72. tagDomObj.clientHeight
  73. );
  74. this.setWndCover();
  75. }
  76. });
  77. // 初始化播放器插件
  78. nextTick(() => {
  79. initPlugin();
  80. })
  81. })
  82. onBeforeUnmount(() => {
  83. if (oWebControl.value != null) {
  84. // 先让窗口隐藏,规避可能的插件窗口滞后于浏览器消失问题
  85. oWebControl.JS_HideWnd();
  86. // 销毁当前播放的视频
  87. oWebControl.JS_RequestInterface({ funcName: "destroyWnd" });
  88. // 断开与插件服务连接
  89. oWebControl.JS_Disconnect();
  90. }
  91. })
  92. const initPlugin = () => {
  93. oWebControl = new WebControl({
  94. szPluginContainer: "playWnd", // 指定容器id
  95. iServicePortStart: 15900, // 指定起止端口号,建议使用该值
  96. iServicePortEnd: 15900,
  97. szClassId: "23BF3B0A-2C56-4D97-9C03-0CB103AA8F11", // 用于IE10使用ActiveX的clsid
  98. cbConnectSuccess: () => {
  99. // 创建WebControl实例成功
  100. oWebControl
  101. .JS_StartService("window", {
  102. // WebControl实例创建成功后需要启动服务
  103. // 值"./VideoPluginConnect.dll"写死
  104. dllPath: "./VideoPluginConnect.dll",
  105. })
  106. .then(
  107. function () {
  108. // 设置消息回调
  109. oWebControl.JS_SetWindowControlCallback({
  110. // cbIntegrationCallBack: cbIntegrationCallBack,
  111. });
  112. //JS_CreateWnd创建视频播放窗口,宽高可设定
  113. oWebControl
  114. .JS_CreateWnd("playWnd", 1152, 581, { bEmbed: true })//这一部分很重要,两个参数为你盒子的宽高,这样是写死是防止组件加载之前出现白屏;bEmbed: true 防止窗口闪烁
  115. .then(function () {
  116. // 创建播放实例成功后初始化
  117. init();
  118. });
  119. },
  120. function () {
  121. // 启动插件服务失败
  122. }
  123. );
  124. },
  125. // 创建WebControl实例失败
  126. cbConnectError: function () {
  127. // 这里写创建WebControl实例失败时的处理步骤,下面的代码仅做参看,具体实现步骤根据个人需求进行编写!!!!!!!!
  128. // console.log(0);
  129. // oWebControl.value = null;
  130. // // 程序未启动时执行error函数,采用wakeup来启动程序
  131. // window.WebControl.JS_WakeUp("VideoWebPlugin://");
  132. // initCount++;
  133. // if (initCount < 3) {
  134. // setTimeout(function () {
  135. // initPlugin();
  136. // }, 3000);
  137. // } else {
  138. // setTimeout(function () {
  139. // setTimeout(function () {
  140. // $router.push('/home/PlugDown')
  141. // }, 4000)
  142. // }, 4000)
  143. // }
  144. },
  145. cbConnectClose: () => {
  146. // 异常断开:bNormalClose = false
  147. // JS_Disconnect正常断开:bNormalClose = true
  148. // console.log("cbConnectClose");
  149. oWebControl.value = null;
  150. },
  151. });
  152. // oWebControl.JS_CuttingPartWindow(500, 500, 500, 500);
  153. }
  154. // 初始化
  155. const init = (callback) => {
  156. getPubKey(() => {
  157. let appkey = objData.value.appkey; //综合安防管理平台提供的appkey,必填
  158. let secret = setEncrypt(objData.value.secret); //综合安防管理平台提供的secret,必填
  159. let ip = objData.value.ip; //综合安防管理平台IP地址,必填
  160. let playMode = objData.value.playMode; //初始播放模式:0-预览,1-回放
  161. let port = objData.value.port; //综合安防管理平台端口,若启用HTTPS协议,默认443
  162. let snapDir = "D:\\SnapDir"; //抓图存储路径
  163. let videoDir = "D:\\VideoDir"; //紧急录像或录像剪辑存储路径
  164. let layout = objData.value.layout; //playMode指定模式的布局
  165. let enableHTTPS = 1; //是否启用HTTPS协议与综合安防管理平台交互,这里总是填1
  166. let encryptedFields = "secret"; //加密字段,默认加密领域为secret
  167. let showToolbar = 1; //是否显示工具栏,0-不显示,非0-显示
  168. let showSmart = 0; //是否显示移动框线框,0-不显示,非0-显示
  169. let buttonIDs =
  170. "0,16,256,257,258,259,260,512,513,514,515,516,517,768,769"; //自定义工具条按钮
  171. // var toolBarButtonIDs = "2049,2304" // 工具栏上自定义按钮
  172. oWebControl
  173. .JS_RequestInterface({
  174. funcName: "init",
  175. argument: JSON.stringify({
  176. appkey: appkey, //API网关提供的appkey
  177. secret: secret, //API网关提供的secret
  178. ip: ip, //API网关IP地址
  179. playMode: playMode, //播放模式(决定显示预览还是回放界面)
  180. port: port, //端口
  181. snapDir: snapDir, //抓图存储路径
  182. videoDir: videoDir, //紧急录像或录像剪辑存储路径
  183. layout: layout, //布局
  184. enableHTTPS: enableHTTPS, //是否启用HTTPS协议
  185. encryptedFields: encryptedFields, //加密字段
  186. showToolbar: showToolbar, //是否显示工具栏
  187. showSmart: showSmart, //是否显示智能信息
  188. buttonIDs, //自定义工具条按钮
  189. }),
  190. })
  191. .then(function (oData) {
  192. oWebControl.JS_Resize(playWndWidth.value, playWndHeight.value); // 初始化后resize一次,规避firefox下首次显示窗口后插件窗口未与DIV窗口重合问题
  193. if (callback) {
  194. callback();
  195. }
  196. // 隐藏
  197. // oWebControl.JS_HideWnd()
  198. });
  199. });
  200. }
  201. // RSA 加密
  202. let setEncrypt = (value) => {
  203. let encrypt = new window.JSEncrypt();
  204. encrypt.setPublicKey(pubKey);
  205. return encrypt.encrypt(value);
  206. }
  207. // 获取公钥
  208. const getPubKey = (callback) => {
  209. oWebControl
  210. .JS_RequestInterface({
  211. funcName: "getRSAPubKey",
  212. argument: JSON.stringify({
  213. keyLength: 1024,
  214. }),
  215. })
  216. .then(function (oData) {
  217. if (oData.responseMsg.data) {
  218. pubKey = oData.responseMsg.data;
  219. callback();
  220. }
  221. });
  222. }
  223. // 调用这个函数可进行视频播放
  224. // 视频预览功能
  225. const previewVideo = (data) => {
  226. let cameraIndexCode = data; // 获取输入的监控点编号值,必填
  227. let streamMode = 0; // 主子码流标识:0-主码流,1-子码流
  228. let transMode = 1; // 传输协议:0-UDP,1-TCP
  229. let gpuMode = 0; // 是否启用GPU硬解,0-不启用,1-启用
  230. let wndId = -1; // 播放窗口序号(在2x2以上布局下可指定播放窗口)
  231. oWebControl.JS_RequestInterface({
  232. funcName: "startPreview",
  233. argument: JSON.stringify({
  234. cameraIndexCode: cameraIndexCode, // 监控点编号
  235. streamMode: streamMode, // 主子码流标识
  236. transMode: transMode, // 传输协议
  237. gpuMode: gpuMode, // 是否开启GPU硬解
  238. wndId: wndId, // 可指定播放窗口
  239. }),
  240. })
  241. .then(function () {
  242. oWebControl.JS_SetWindowControlCallback({
  243. });
  244. });
  245. }
  246. </script>
  247. <style scoped>
  248. .main {
  249. position: fixed;
  250. top: 50%;
  251. left: 20%;
  252. transform: translateY(-50%);
  253. width: 60vw;
  254. height: 60vh;
  255. margin: auto;
  256. background-color: #ccc;
  257. }
  258. </style>

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/花生_TL007/article/detail/599535
推荐阅读
相关标签
  

闽ICP备14008679号