From 69213dac0358b7f904c73d05d113b6cd6456712c Mon Sep 17 00:00:00 2001
From: lixuefeng <1126141216@qq.com>
Date: Tue, 9 Dec 2025 17:58:30 +0800
Subject: [PATCH] =?UTF-8?q?=E7=B1=BB=E5=9E=8B=EF=BC=9A=E5=BC=80=E5=8F=91?=
=?UTF-8?q?=20=E6=8F=8F=E8=BF=B0=EF=BC=9A?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/views/monitor/components/box-2.vue | 243 +++++++++++++++++--------
1 file changed, 163 insertions(+), 80 deletions(-)
diff --git a/src/views/monitor/components/box-2.vue b/src/views/monitor/components/box-2.vue
index cb1f7ff..ede3fbb 100644
--- a/src/views/monitor/components/box-2.vue
+++ b/src/views/monitor/components/box-2.vue
@@ -2,27 +2,24 @@
-
-
-
-
- {{ item.dictLabel }}
+
+
+
+ {{ item }}
-
-
- 收藏夹
-
-
-
-
+
+
+ 收藏夹
+
+
@@ -52,7 +49,7 @@
alt=""
/>
{{resource.regions}}
-
+
-
+
@@ -202,18 +199,19 @@
postVideoControlApi,
postVideoCollectApi
} from '@/api/monitor'
+ import mpegtsjs from 'mpegts.js'
import { debounce } from 'lodash'
import pubSub from 'pubsub-js'
import Hls from 'hls.js'
- const Z00M_IN = 'ZOOM_IN' // 焦距变大
- const Z00M_OUT = 'ZOOM_OUT' // 焦距变小
- const UP = 'UP' // 上转
- const DOWN = 'DOWN' // 下转
- const LEFT = 'LEFT' // 左转
- const RIGHT = 'RIGHT' // 右转
- const STOP = 'STOP' // 停止操作
+ const Z00M_IN = 'zoomin' // 焦距变大
+ const Z00M_OUT = 'zoomout' // 焦距变小
+ const UP = 'up' // 上转
+ const DOWN = 'down' // 下转
+ const LEFT = 'left' // 左转
+ const RIGHT = 'right' // 右转
+ const STOP = 'stop' // 停止操作
let ACTION = '0'
const props = {
@@ -249,41 +247,97 @@
let timer = null
const postVideoRemain = async () => {
- if(!videoList.value.length) return false;
- timer = setInterval(() => {
- postVideoRemainApi({
- cameraIndexCode: videoList.value.map((item) => item.cameraIndexCode)
- })
- }, 2000)
+ // if(!videoList.value.length) return false;
+ // timer = setInterval(() => {
+ // postVideoRemainApi({
+ // cameraIndexCode: videoList.value.map((item) => item.cameraIndexCode)
+ // })
+ // }, 2000)
}
+ const createPlayer = (cameraIndexCode,videoElement) => {
+ getPreviewUrlApi({
+ type: 'hls',
+ cameraIndexCode: cameraIndexCode
+ }).then(res=>{
+ const url = res.data.url;
+ if(url.startsWith('ws')){
+ const player = mpegtsjs.createPlayer({
+ url: url,
+ type: 'flv',
+ isLive: true,
+ hasAudio: false
+ })
+ player.attachMediaElement(videoElement)
+ player.load()
+ player.play()
+ // 错误处理和重连机制
+ player.on(mpegtsjs.Events.ERROR, (err) => {
+ console.error('播放器错误【'+cameraIndexCode+'】:', err)
+ player.unload();
+ player.destroy();
+ // 3 秒后尝试重新加载
+ setTimeout(() => {
+ console.error('重新加载【'+cameraIndexCode+'】' )
+ createPlayer(cameraIndexCode,videoElement);
+ }, 3000)
- const initVideo = () => {
- clearHlsRefs()
- nextTick(() => {
- videoList.value.forEach(async (item, index) => {
- const video = document.getElementById(`monitorVideo${index}`)
- const hls = new Hls({
+ })
+ player.on(mpegtsjs.Events.LOADING_COMPLETE, (err) => {
+ console.error('加载完成:', err)
+ })
+ hlsRefs.push(player)
+ }
+ else{
+ const player = new Hls({
maxBufferLength: 10, // 最大缓冲长度(秒)
maxMaxBufferLength: 15, // 缓冲区长度的上限
maxBufferSize: 30 * 1000 * 1000 // 最大缓冲大小(字节)
})
- hls.loadSource(item.hlsUrl)
- hls.attachMedia(video)
- hls.on(Hls.Events.MANIFEST_PARSED, () => {
- video.play()
+ player.loadSource(url)
+ player.attachMedia(videoElement)
+ player.on(Hls.Events.MANIFEST_PARSED, () => {
+ videoElement.play()
})
- hlsRefs.push(hls)
+ player.on(Hls.Events.ERROR, (event, data) => {
+ // 根据错误类型进行处理
+ if (data.fatal) {
+ switch (data.type) {
+ case Hls.ErrorTypes.NETWORK_ERROR:
+ console.log('网络错误,尝试重新加载');
+ player.startLoad();
+ break;
+ case Hls.ErrorTypes.MEDIA_ERROR:
+ console.log('媒体错误,尝试修复');
+ player.recoverMediaError();
+ break;
+ default:
+ console.log('无法恢复的错误,销毁播放器');
+ // hls.destroy();
+ break;
+ }
+ }
+ })
+ hlsRefs.push(player)
+ }
+ })
+ }
+ const initVideo = () => {
+ clearHlsRefs()
+ nextTick(() => {
+ videoList.value.forEach(async (item, index) => {
+ const videoElement = document.getElementById(`monitorVideo${index}`)
+ createPlayer(item.cameraIndexCode,videoElement);
})
})
}
const onInput = debounce((e) => {
-
+
if(e){
getVideoRegions('search')
}else{
getVideoRegions()
}
-
+
}, 500)
const clearHlsRefs = () => {
if (hlsRefs.length > 0) {
@@ -303,7 +357,7 @@
videoList.value = []
getVideoList()
}
-
+
}
const getColletList = async () => {
clearHlsRefs()
@@ -338,30 +392,60 @@
initVideo()
}
let thisVideo = ref(null)
- const handleItemVideo = (url, type, code,item) => {
- thisVideo.value = item
+ const handleItemVideo = async (url, type, code, item) => {
+ let res = await getPreviewUrlApi({
+ cameraIndexCode: code,
+ type: 'hls'
+ })
+ url = res.data.url
+ thisVideo.value = item
videoLog.value = 2
cameraIndexCode.value = code
setTimeout(() => {
- hlsRef = new Hls({
- maxBufferLength: 10, // 最大缓冲长度(秒)
- maxMaxBufferLength: 15, // 缓冲区长度的上限
- maxBufferSize: 30 * 1000 * 1000 // 最大缓冲大小(字节)
- })
- hlsRef.loadSource(url)
- hlsRef.attachMedia(videoRef.value)
- hlsRef.on(Hls.Events.MANIFEST_PARSED, () => {
- videoRef.value.play()
- })
+ if (url.startsWith('ws')) {
+ hlsRef = mpegtsjs.createPlayer({
+ url: url,
+ type: 'flv',
+ isLive: true,
+ hasAudio: false
+ })
+ hlsRef.attachMediaElement(videoRef.value)
+ hlsRef.load()
+ hlsRef.play()
+ // 错误处理和重连机制
+ hlsRef.on('error', (err) => {
+ console.error('播放器错误:', err)
+ // 3 秒后尝试重新加载
+ hlsRef.unload()
+ hlsRef.destroy()
+ // 3 秒后尝试重新加载
+ setTimeout(() => {
+ console.error('重新加载【' + cameraIndexCode + '】')
+ handleItemVideo(url, 101, code, item);
+ }, 3000)
+ })
+ } else {
+ hlsRef = new Hls({
+ maxBufferLength: 10, // 最大缓冲长度(秒)
+ maxMaxBufferLength: 15, // 缓冲区长度的上限
+ maxBufferSize: 30 * 1000 * 1000 // 最大缓冲大小(字节)
+ })
+ hlsRef.loadSource(url)
+ hlsRef.attachMedia(videoRef.value)
+ hlsRef.on(Hls.Events.MANIFEST_PARSED, () => {
+ videoRef.value.play()
+ })
+ }
+
if (type == 100) initVideo()
}, 1000)
}
const handleAction = async (e) => {
+ command.value = e
if (e == STOP) {
ACTION = '1'
} else {
ACTION = '0'
- command.value = e
}
await postVideoControlApi({
action: ACTION,
@@ -381,18 +465,17 @@
}
const handleRegList = (item,i,x)=>{
regionList.value[i].resourcesList[x].show = !regionList.value[i].resourcesList[x].show
-
+
}
const handleCamera = async (itemCode,resource) => {
show.value = true
let res = await getPreviewUrlApi({
type: 'hls',
- cameraIndexCode:itemCode
+ cameraIndexCode: itemCode
})
- console.log(res,'rrrrrrrrrrrrrr')
cameraIndexCode.value = itemCode;
- isCollect.value = resource.isCollect
- isDiy.value = resource.isDiy
+ isCollect.value = resource.isCollect
+ isDiy.value = resource.isDiy
videoSrc.value = res.data.url
}
const handleCollect = async (id, status, index) => {
@@ -451,7 +534,7 @@
let res = await getVideoListApi(params)
total.value = res.total
if (res.data.length > 0) {
-
+
videoList.value = res.data
// console.log(videoList.value,'1111111111111111111111')
// postVideoRemain()
@@ -485,13 +568,13 @@
break;
default:
console.log('无法恢复的错误,销毁播放器');
-
+
// hls.destroy();
break;
}
}
})
-
+
hlsRefs.push(hls)
})
})
@@ -520,7 +603,7 @@
cameraName: cameraName.value,
businessScenicArea: params.businessScenicArea
})
-
+
regionList.value = res.data
regionList.value.videoResources = res.data.videoResources
// regionList.value[0].show = true
@@ -532,7 +615,7 @@
r.show = false
})
})
-
+
if(search=='search'){
regionList.value.forEach((item,index)=>{
item.show = true
@@ -541,7 +624,7 @@
})
})
}
-
+
console.log(regionList.value, ' regionList.value')
}
const onMonitorChange = () => {
@@ -557,8 +640,8 @@
getVideoType()
getVideoRegions()
},1500)
-
-
+
+
})
}
onMounted(() => {
@@ -588,7 +671,7 @@