xsh_1997 пре 1 месец
родитељ
комит
400ad41f9a

+ 1 - 1
ruoyi-ui/package.json

@@ -24,7 +24,7 @@
24 24
     "url": "https://gitee.com/y_project/RuoYi-Vue.git"
25 25
   },
26 26
   "dependencies": {
27
-    "@liveqing/liveplayer": "^2.7.40",
27
+    "@ezuikit/player-hls": "^0.1.5",
28 28
     "@riophae/vue-treeselect": "0.4.0",
29 29
     "axios": "0.30.3",
30 30
     "clipboard": "2.0.8",

BIN
ruoyi-ui/public/decoder.wasm


Разлика између датотеке није приказан због своје велике величине
+ 8 - 0
ruoyi-ui/public/decoder.worker.js


+ 0 - 1
ruoyi-ui/public/index.html

@@ -6,7 +6,6 @@
6 6
     <meta name="renderer" content="webkit">
7 7
     <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
8 8
     <link rel="icon" href="<%= BASE_URL %>favicon.ico">
9
-    <script type="text/javascript" src="<%= BASE_URL %>js/liveplayer-lib.min.js"></script>
10 9
     <title><%= webpackConfig.name %></title>
11 10
     <!--[if lt IE 11]><script>window.location.href='/html/ie.html';</script><![endif]-->
12 11
 	  <style>

Разлика између датотеке није приказан због своје велике величине
+ 0 - 1
ruoyi-ui/public/js/liveplayer-component.min.js


Разлика између датотеке није приказан због своје велике величине
+ 0 - 1
ruoyi-ui/public/js/liveplayer-lib.min.js


+ 166 - 0
ruoyi-ui/src/components/EzvizHlsPlayer/index.vue

@@ -0,0 +1,166 @@
1
+<template>
2
+  <div :id="containerId" ref="containerRef" class="ezviz-hls-player" />
3
+</template>
4
+
5
+<script>
6
+import HlsPlayer from "@ezuikit/player-hls"
7
+
8
+let containerSeq = 0
9
+
10
+export default {
11
+  name: "EzvizHlsPlayer",
12
+  props: {
13
+    url: {
14
+      type: String,
15
+      default: ""
16
+    }
17
+  },
18
+  data() {
19
+    containerSeq += 1
20
+    return {
21
+      containerId: `ezviz-hls-player-${containerSeq}`,
22
+      player: null,
23
+      resizeObserver: null
24
+    }
25
+  },
26
+  computed: {
27
+    decoderStaticPath() {
28
+      const base = process.env.BASE_URL || "/"
29
+      return `${base}ezuikit-player-hls/`
30
+    }
31
+  },
32
+  watch: {
33
+    url(val) {
34
+      this.rebuildPlayer(val)
35
+    }
36
+  },
37
+  mounted() {
38
+    this.bindResizeObserver()
39
+    if (this.url) {
40
+      this.$nextTick(() => {
41
+        this.initPlayer(this.url)
42
+      })
43
+    }
44
+  },
45
+  beforeDestroy() {
46
+    this.unbindResizeObserver()
47
+    this.destroyPlayer()
48
+  },
49
+  methods: {
50
+    getContainerSize() {
51
+      const el = this.$refs.containerRef
52
+      if (!el) {
53
+        return { width: 0, height: 0 }
54
+      }
55
+      const parent = el.parentElement
56
+      const width = el.clientWidth || (parent && parent.clientWidth) || el.offsetWidth || 0
57
+      const height = el.clientHeight || (parent && parent.clientHeight) || el.offsetHeight || 0
58
+      return { width, height }
59
+    },
60
+    bindResizeObserver() {
61
+      if (typeof ResizeObserver === "undefined") {
62
+        return
63
+      }
64
+      this.resizeObserver = new ResizeObserver(() => {
65
+        this.syncPlayerSize()
66
+      })
67
+      this.$nextTick(() => {
68
+        const el = this.$refs.containerRef
69
+        if (el && el.parentElement) {
70
+          this.resizeObserver.observe(el.parentElement)
71
+        }
72
+      })
73
+    },
74
+    unbindResizeObserver() {
75
+      if (this.resizeObserver) {
76
+        this.resizeObserver.disconnect()
77
+        this.resizeObserver = null
78
+      }
79
+    },
80
+    syncPlayerSize() {
81
+      if (!this.player || typeof this.player.resize !== "function") {
82
+        return
83
+      }
84
+      const { width, height } = this.getContainerSize()
85
+      if (width > 0 && height > 0) {
86
+        this.player.resize(width, height)
87
+      }
88
+    },
89
+    destroyPlayer() {
90
+      if (this.player) {
91
+        try {
92
+          this.player.destroy()
93
+        } catch (e) {
94
+          // ignore teardown errors
95
+        }
96
+        this.player = null
97
+      }
98
+      const el = this.$refs.containerRef
99
+      if (el) {
100
+        el.innerHTML = ""
101
+      }
102
+    },
103
+    rebuildPlayer(url) {
104
+      this.destroyPlayer()
105
+      if (url) {
106
+        this.$nextTick(() => {
107
+          this.initPlayer(url)
108
+        })
109
+      }
110
+    },
111
+    initPlayer(url, retryCount = 0) {
112
+      const text = url != null ? String(url).trim() : ""
113
+      if (!text) {
114
+        return
115
+      }
116
+      const el = document.getElementById(this.containerId)
117
+      if (!el) {
118
+        return
119
+      }
120
+      el.innerHTML = ""
121
+      const { width, height } = this.getContainerSize()
122
+      if (width <= 0 || height <= 0) {
123
+        if (retryCount < 8) {
124
+          requestAnimationFrame(() => {
125
+            this.initPlayer(url, retryCount + 1)
126
+          })
127
+        }
128
+        return
129
+      }
130
+      this.player = new HlsPlayer({
131
+        id: this.containerId,
132
+        url: text,
133
+        staticPath: '/',
134
+        isLive: true,
135
+        width,
136
+        height
137
+      })
138
+      this.player.play().catch(() => {
139
+        this.$emit("error")
140
+      })
141
+    }
142
+  }
143
+}
144
+</script>
145
+
146
+<style scoped>
147
+.ezviz-hls-player {
148
+  width: 100%;
149
+  height: 100%;
150
+  overflow: hidden;
151
+  background: #000;
152
+}
153
+
154
+.ezviz-hls-player ::v-deep .ezui-player-container,
155
+.ezviz-hls-player ::v-deep .ezui-hls-container {
156
+  width: 100% !important;
157
+  height: 100% !important;
158
+}
159
+
160
+.ezviz-hls-player ::v-deep canvas,
161
+.ezviz-hls-player ::v-deep video {
162
+  width: 100% !important;
163
+  height: 100% !important;
164
+  object-fit: contain;
165
+}
166
+</style>

+ 1 - 0
ruoyi-ui/src/lang/bo/videoSurveillance.js

@@ -58,6 +58,7 @@ export default {
58 58
     confirmDelete: "ཐོ་གཞུང་འདི་སུབ་རྒྱུ་གཏན་ཁེལ་ལམ?",
59 59
     msgLiveNoMonitorId: "摄像头 ID མེད",
60 60
     msgLiveNoStream: "བརྙན་ཟློས་མེད",
61
+    msgLivePlayFail: "播放失败",
61 62
     viewMonitorId: "摄像头 ID",
62 63
     viewMonitorName: "བརྙན་ཟློས་མིང་།",
63 64
     viewOwner: "གཙོ་བོ།",

+ 1 - 0
ruoyi-ui/src/lang/zh/videoSurveillance.js

@@ -58,6 +58,7 @@ export default {
58 58
     confirmDelete: "是否确认删除这条数据?",
59 59
     msgLiveNoMonitorId: "该监控点位缺少摄像头 ID,无法获取播放地址",
60 60
     msgLiveNoStream: "暂无直播流",
61
+    msgLivePlayFail: "直播播放失败,请稍后重试",
61 62
     viewMonitorId: "摄像头 ID",
62 63
     viewMonitorName: "监控名称",
63 64
     viewOwner: "所属主体",

+ 19 - 14
ruoyi-ui/src/views/videoSurveillance/livestockMonitor/index.vue

@@ -232,18 +232,8 @@
232 232
       @close="closeLiveView"
233 233
     >
234 234
       <div v-loading="liveLoading" class="live-player-wrap">
235
-        <LivePlayer
236
-          :video-url="liveVideoUrl"
237
-          :video-title="liveVideoTitle"
238
-          :alt="vsT('msgLiveNoStream')"
239
-          live
240
-          fluent
241
-          :autoplay="!!liveVideoUrl"
242
-          stretch
243
-          aspect="16:9"
244
-          :controls="true"
245
-          :muted="true"
246
-        />
235
+        <EzvizHlsPlayer v-if="liveVideoUrl" :key="liveVideoUrl" :url="liveVideoUrl" @error="onLivePlayerError" />
236
+        <div v-else-if="!liveLoading" class="live-player-empty">{{ vsT("msgLiveNoStream") }}</div>
247 237
       </div>
248 238
       <div slot="footer" class="dialog-footer">
249 239
         <el-button @click="closeLiveView">{{ vsCommon("close") }}</el-button>
@@ -253,7 +243,7 @@
253 243
 </template>
254 244
 
255 245
 <script>
256
-import LivePlayer from "@liveqing/liveplayer"
246
+import EzvizHlsPlayer from "@/components/EzvizHlsPlayer/index.vue"
257 247
 import videoSurveillanceLocaleMixin from "@/mixins/videoSurveillanceLocaleMixin"
258 248
 import {
259 249
   listLivestockMonitor,
@@ -283,7 +273,7 @@ function createEmptyForm() {
283 273
 export default {
284 274
   name: "VideoSurveillanceLivestockMonitor",
285 275
   components: {
286
-    LivePlayer
276
+    EzvizHlsPlayer
287 277
   },
288 278
   mixins: [videoSurveillanceLocaleMixin],
289 279
   data() {
@@ -638,6 +628,9 @@ export default {
638 628
       this.liveOpen = false
639 629
       this.liveLoading = false
640 630
     },
631
+    onLivePlayerError() {
632
+      this.$modal.msgError(this.vsT("msgLivePlayFail"))
633
+    },
641 634
     handleSync() {
642 635
       this.runSyncWithLoading(() => syncLivestockMonitor())
643 636
         .then((res) => {
@@ -714,8 +707,20 @@ export default {
714 707
 
715 708
 .live-player-wrap {
716 709
   position: relative;
710
+  display: flex;
717 711
   width: 100%;
718 712
   height: 540px;
713
+  overflow: hidden;
719 714
   background: #000;
720 715
 }
716
+
717
+.live-player-empty {
718
+  display: flex;
719
+  align-items: center;
720
+  justify-content: center;
721
+  width: 100%;
722
+  height: 100%;
723
+  color: #909399;
724
+  font-size: 14px;
725
+}
721 726
 </style>

+ 0 - 5
ruoyi-ui/vue.config.js

@@ -79,11 +79,6 @@ module.exports = {
79 79
         minRatio: 0.8,                                 // 压缩比例,小于 80% 的文件不会被压缩
80 80
         deleteOriginalAssets: false                    // 压缩后删除原文件
81 81
       }),
82
-      new CopyPlugin([
83
-        { from: 'node_modules/@liveqing/liveplayer/dist/component/crossdomain.xml'},
84
-        { from: 'node_modules/@liveqing/liveplayer/dist/component/liveplayer.swf'},
85
-        { from: 'node_modules/@liveqing/liveplayer/dist/component/liveplayer-lib.min.js', to: 'js/'},
86
-      ])
87 82
     ],
88 83
   },
89 84
   chainWebpack(config) {