Browse Source

feat: 更改视频流连接方式

master
fajiao 2 years ago
parent
commit
825d28054d
  1. 1
      components.d.ts
  2. 20
      src/axios/core/zlmApi.ts
  3. 1
      src/axios/index.ts
  4. 2
      src/views/index.vue
  5. 250
      src/views/page/cameraCenter.vue

1
components.d.ts

@ -17,7 +17,6 @@ declare module '@vue/runtime-core' {
AMenu: typeof import('ant-design-vue/es')['Menu'] AMenu: typeof import('ant-design-vue/es')['Menu']
AMenuItem: typeof import('ant-design-vue/es')['MenuItem'] AMenuItem: typeof import('ant-design-vue/es')['MenuItem']
AModal: typeof import('ant-design-vue/es')['Modal'] AModal: typeof import('ant-design-vue/es')['Modal']
APopconfirm: typeof import('ant-design-vue/es')['Popconfirm']
ARow: typeof import('ant-design-vue/es')['Row'] ARow: typeof import('ant-design-vue/es')['Row']
ASelect: typeof import('ant-design-vue/es')['Select'] ASelect: typeof import('ant-design-vue/es')['Select']
ATree: typeof import('ant-design-vue/es')['Tree'] ATree: typeof import('ant-design-vue/es')['Tree']

20
src/axios/core/zlmApi.ts

@ -0,0 +1,20 @@
import {apiUrl} from "@/axios";
import {axios} from "@/utils/axios";
import qs from "qs";
enum Api {
AddStreamProxy = '/zlm/addStreamProxy',
DelStreamProxy = '/zlm/delStreamProxy',
GetMediaList = '/zlm/getMediaList',
IsMediaOnline = '/zlm/isMediaOnline',
}
const CisApiUrl = apiUrl.CisApiUrl;
export const AddStreamProxy = (params?: any) => axios.post(CisApiUrl + Api.AddStreamProxy, qs.stringify(params))
export const DelStreamProxy = (params?: any) => axios.post(CisApiUrl + Api.DelStreamProxy, qs.stringify(params))
export const GetMediaList = (params?: any) => axios.post(CisApiUrl + Api.GetMediaList, qs.stringify(params))
export const IsMediaOnline = (params?: any) => axios.post(CisApiUrl + Api.IsMediaOnline, qs.stringify(params))

1
src/axios/index.ts

@ -3,5 +3,6 @@ export const apiUrl = {
WebRtcUrl: 'http://192.168.1.119:8000', WebRtcUrl: 'http://192.168.1.119:8000',
OnvifApiUrl: 'http://192.168.1.119:800/api', OnvifApiUrl: 'http://192.168.1.119:800/api',
SysApiUrl: 'http://192.168.1.119:800/api', SysApiUrl: 'http://192.168.1.119:800/api',
ZlmWsStreamUrl: 'ws://192.168.1.119:8080',
// CisApiUrl: 'https://192.168.1.119:5001/api' // CisApiUrl: 'https://192.168.1.119:5001/api'
} }

2
src/views/index.vue

@ -21,7 +21,7 @@
<script lang="ts" setup> <script lang="ts" setup>
import CameraCenter from "@/views/page/cameraCenter.vue"; import CameraCenter from "@/views/page/cameraCenter.vue";
import UserEdit from "@/views/page/userEdit.vue" // import UserEdit from "@/views/page/userEdit.vue"
</script> </script>

250
src/views/page/cameraCenter.vue

@ -6,10 +6,13 @@
@mousedown="mouseDownVideo"> @mousedown="mouseDownVideo">
</video> --> </video> -->
<div id="videoPlayer" @mousedown="mouseDownVideo"></div> <div id="videoPlayer" @mousedown="mouseDownVideo"></div>
<div v-for="item in labelList" :class="`labels ${item.groupName == '视频标签' ? 'lavels-video' : 'lavels-build'}`" <div v-for="item in labelList"
:key="item.id" :id="item.id" :class="`labels ${item.groupName == '视频标签' ? 'lavels-video' : 'lavels-build'}`"
:style="`top:${canvasHeight * item.canvasTopRatio}px;left:${canvasWidth * item.canvasLeftRatio}px`" :key="item.id"
@click="itemClick(item)"> :id="item.id"
:style="`top:${canvasHeight * item.canvasTopRatio}px;left:${canvasWidth * item.canvasLeftRatio}px`"
@click="itemClick(item)"
>
<a-dropdown :trigger="['contextmenu']"> <a-dropdown :trigger="['contextmenu']">
<div class="labels-item" v-if="item.groupName == '视频标签'"> <div class="labels-item" v-if="item.groupName == '视频标签'">
<!-- <div class="labels-item" v-if="item.inFlag"> --> <!-- <div class="labels-item" v-if="item.inFlag"> -->
@ -32,22 +35,9 @@
</a-menu> </a-menu>
</template> </template>
</a-dropdown> </a-dropdown>
<a-popconfirm
placement="bottomRight"
ok-text="Yes"
cancel-text="No"
:visible="item.windowVisible"
@cancel="windowCancel(item)"
>
<template #title>
<cameraWindow :itemData="item"></cameraWindow>
</template>
<!-- <a-button>TL</a-button> -->
</a-popconfirm>
</div> </div>
<div class="labels lavels-build" v-if="addLabel.isAddLabel && addLabel.labelType == '建筑标签'" <div class="labels lavels-build" v-if="addLabel.isAddLabel && addLabel.labelType == '建筑标签'"
:style="` pointer-events: none;top:${addLabelTop}px;left:${addLabelLeft}px`"> :style="` pointer-events: none;top:${addLabelTop}px;left:${addLabelLeft}px`">
<div class="labels-item" alt=""> <div class="labels-item" alt="">
<img src="@/assets/images/buildLabelLine.png"> <img src="@/assets/images/buildLabelLine.png">
<div> <div>
@ -57,7 +47,7 @@
</div> </div>
</div> </div>
<div class="labels lavels-video" v-if="addLabel.isAddLabel && addLabel.labelType == '视频标签'" <div class="labels lavels-video" v-if="addLabel.isAddLabel && addLabel.labelType == '视频标签'"
:style="`top:${addLabelTop}px;left:${addLabelLeft}px`"> :style="`top:${addLabelTop}px;left:${addLabelLeft}px`">
<div class="labels-item"> <div class="labels-item">
<!-- <div class="labels-item" v-if="item.inFlag"> --> <!-- <div class="labels-item" v-if="item.inFlag"> -->
<div> <div>
@ -76,14 +66,15 @@
<script setup lang='ts'> <script setup lang='ts'>
////@ts-nocheck ////@ts-nocheck
import { ExclamationCircleOutlined } from '@ant-design/icons-vue'; import {ExclamationCircleOutlined} from '@ant-design/icons-vue';
import { Modal } from 'ant-design-vue'; import {Modal} from 'ant-design-vue';
import { ref, h, onMounted, getCurrentInstance, ComponentInternalInstance, onUnmounted, watch, createVNode } from "vue"; import {ref, h, onMounted, getCurrentInstance, ComponentInternalInstance, onUnmounted, watch, createVNode} from "vue";
import * as markLabelApi from '@/axios/cameraMark/markLabelApi'; import * as markLabelApi from '@/axios/cameraMark/markLabelApi';
import * as markSearchApi from '@/axios/core/markSearchApi'; import * as markSearchApi from '@/axios/core/markSearchApi';
import { useStore } from '@/store/index'; import * as zlmApi from '@/axios/core/zlmApi';
import { apiUrl } from "@/axios"; import {useStore} from '@/store/index';
import { storeToRefs } from 'pinia'; import {apiUrl} from "@/axios";
import {storeToRefs} from 'pinia';
import Msg from "@/utils/message"; import Msg from "@/utils/message";
import CameraLeftMenu from '@/views/page/Aside/cameraLeftMenu.vue' import CameraLeftMenu from '@/views/page/Aside/cameraLeftMenu.vue'
import CameraRightMenu from '@/views/page/Aside/cameraRightMenu.vue' import CameraRightMenu from '@/views/page/Aside/cameraRightMenu.vue'
@ -91,7 +82,8 @@ import LabelEditModel from '@/views/page/Model/LabelEditModel.vue'
import cameraWindow from '@/views/page/cameraWindow.vue' import cameraWindow from '@/views/page/cameraWindow.vue'
import popup from "@/utils/popup"; import popup from "@/utils/popup";
import VideoControlSimple from './VideoControl/VideoControlSimple.vue'; import VideoControlSimple from './VideoControl/VideoControlSimple.vue';
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
const {proxy} = getCurrentInstance() as ComponentInternalInstance;
let piniaStore = useStore(); let piniaStore = useStore();
let player = <HTMLVideoElement>document.querySelector('#videoPlayer') let player = <HTMLVideoElement>document.querySelector('#videoPlayer')
let canvasWidth = ref(0) let canvasWidth = ref(0)
@ -102,7 +94,6 @@ let cameraMap = storeToRefs(piniaStore).cameraMap
let isActiveChoose = ref(false) let isActiveChoose = ref(false)
let labelList = ref<any[]>([]) let labelList = ref<any[]>([])
let addLabel = storeToRefs(piniaStore).addLabel let addLabel = storeToRefs(piniaStore).addLabel
let screenshot = storeToRefs(piniaStore).screenshot
let addLabelLeft = ref(0); let addLabelLeft = ref(0);
let addLabelTop = ref(0); let addLabelTop = ref(0);
var jessibuca = ref(); var jessibuca = ref();
@ -112,37 +103,18 @@ onMounted(() => {
player = <HTMLVideoElement>document.querySelector('#videoPlayer'); player = <HTMLVideoElement>document.querySelector('#videoPlayer');
loadVideoPlayer(); loadVideoPlayer();
loadVideoCanvas(); loadVideoCanvas();
changeVideoCanvasSize();
create()
} }
}) })
watch(screenshot, (newVal, oldVal) => {
if (newVal) {
console.log(123);
//jessibuca.value.isPlaying()
if (!jessibuca.value.isPlaying()) {
Msg.info("请先选择监控画面")
piniaStore.updateScreenshot(false)
return
}
jessibuca.value.screenshot("", "png", 1)
piniaStore.updateScreenshot(false)
}
})
watch(curSelectKey, (newVal, oldVal) => { watch(curSelectKey, (newVal, oldVal) => {
switchCamera(newVal) switchCamera(newVal)
}) })
watch(closeVideoKey, (newVal, oldVal) => { watch(closeVideoKey, (newVal, oldVal) => {
if (curVideoKey.value == newVal) { if (curVideoKey.value == newVal) {
destroyVideo() closeVideo()
piniaStore.updateCloseVideoKey("") piniaStore.updateCloseVideoKey("")
piniaStore.updateCurSelectKey("") piniaStore.updateCurSelectKey("")
} }
}) })
watch(addLabel, (newVal, oldVal) => { watch(addLabel, (newVal, oldVal) => {
if (newVal.isAddLabel) { if (newVal.isAddLabel) {
@ -154,24 +126,48 @@ watch(addLabel, (newVal, oldVal) => {
} }
} }
}) })
function destroyVideo() {
jessibuca.value.destroy(); function closeVideo() {
create() jessibuca.value.close();
labelList.value = [] labelList.value = []
} }
//
function create() { //
function deleteLabel(id: number) {
markLabelApi.Delete({id}).then((res: any) => {
if (judgeResponse(res)) return;
let flag = res.data.data;
let msg = flag === true ? "删除成功" : "删除失败";
if (flag) {
labelList.value = labelList.value.filter((element: any) => {
return element.id != id;
});
Msg.success("删除成功");
} else {
Msg.error("删除失败");
}
})
}
//
function itemClick(item: any) {
// console.log("",item);
popup("监控画面", [h(cameraWindow, {windowData: item})], "cameraWindow");
}
function loadVideoPlayer() {
var showOperateBtns = false; // var showOperateBtns = false; //
var forceNoOffscreen = true; // var forceNoOffscreen = true; //
jessibuca.value = new Jessibuca({ jessibuca.value = new Jessibuca({
container: player, container: player,
videoBuffer: 0.5, // videoBuffer: 0.2, //
isResize: false, isResize: false,
text: "", text: "",
loadingText: "", loadingText: "",
autoWasm: true,
useMSE: false, useMSE: false,
debug: false, debug: true,
showBandwidth: showOperateBtns, // showBandwidth: showOperateBtns, //
operateBtns: { operateBtns: {
fullscreen: showOperateBtns, fullscreen: showOperateBtns,
@ -181,6 +177,7 @@ function create() {
recorder: false recorder: false
}, },
forceNoOffscreen: forceNoOffscreen, forceNoOffscreen: forceNoOffscreen,
hasAudio: false,
isNotMute: false, isNotMute: false,
},); },);
@ -190,57 +187,22 @@ function create() {
jessibuca.value.onPlay = () => console.log('onPlay'); jessibuca.value.onPlay = () => console.log('onPlay');
jessibuca.value.onFullscreen = (msg: any) => console.log('onFullscreen', msg); jessibuca.value.onFullscreen = (msg: any) => console.log('onFullscreen', msg);
jessibuca.value.onMute = (msg: any) => console.log('onMute', msg); jessibuca.value.onMute = (msg: any) => console.log('onMute', msg);
} }
//
function deleteLabel(id: number) {
markLabelApi.Delete({ id }).then((res: any) => {
console.log(res.data);
if (res.data.code == 200) {
let msg = res.data.data == true ? "删除成功" : "删除失败"
if (res.data.data) {
labelList.value = labelList.value.filter((element: any) => {
return element.id != id
});
Msg.success("删除成功")
return
}
}
Msg.error("删除失败")
})
}
//
function itemClick(item: any) {
// console.log("",item);
// popup("", [h(cameraWindow, { windowData: item })], "cameraWindow");
//
item.windowVisible = true
}
//
function windowCancel(item: any){
item.windowVisible = false
}
function loadVideoPlayer() {
let elmId = 'videoPlayer';
let url = apiUrl.WebRtcUrl;
// webRtcServer.value = new WebRtcStreamer(elmId, url);
}
function loadVideoCanvas() { function loadVideoCanvas() {
window.addEventListener('resize', () => { window.addEventListener('resize', () => {
changeVideoCanvasSize(); changeVideoCanvasSize();
}); });
changeVideoCanvasSize();
} }
const onContextMenuClick = (item: any, menuKey: string,) => { const onContextMenuClick = (item: any, menuKey: string,) => {
console.log(`labelId: ${item.id}, menuKey: ${menuKey}`); console.log(`labelId: ${item.id}, menuKey: ${menuKey}`);
// console.log(`item: ${item}`); // console.log(`item: ${item}`);
// console.log(item); // console.log(item);
//key //key
if (menuKey == "edit") { if (menuKey == "edit") {
popup("编辑标签", [h(LabelEditModel, { modelData: item })], "editLabel"); popup("编辑标签", [h(LabelEditModel, {modelData: item})], "editLabel");
} else if (menuKey == "delete") { } else if (menuKey == "delete") {
Modal.confirm({ Modal.confirm({
zIndex: 10000, zIndex: 10000,
@ -249,11 +211,11 @@ const onContextMenuClick = (item: any, menuKey: string,) => {
content: () => content: () =>
h( h(
"span", "span",
{ style: { color: "black" } }, {style: {color: "black"}},
"是否确认删除该标签?" "是否确认删除该标签?"
), ),
okText: okText:
// () => h('span', { style: { color: 'black' } }, ''), // () => h('span', { style: { color: 'black' } }, ''),
"确定", "确定",
// okType: 'primary', // okType: 'primary',
cancelText: () => "取消", cancelText: () => "取消",
@ -274,6 +236,7 @@ const onContextMenuClick = (item: any, menuKey: string,) => {
} }
}; };
function changeVideoCanvasSize() { function changeVideoCanvasSize() {
canvasWidth.value = player.clientWidth; canvasWidth.value = player.clientWidth;
canvasHeight.value = player.clientHeight; canvasHeight.value = player.clientHeight;
@ -281,7 +244,6 @@ function changeVideoCanvasSize() {
function mouseDownVideo(e: MouseEvent) { function mouseDownVideo(e: MouseEvent) {
if (!isActiveChoose.value) return; if (!isActiveChoose.value) return;
// e.buttons == 1 // e.buttons == 1
if (e.buttons == 1) { if (e.buttons == 1) {
@ -307,17 +269,16 @@ function mouseDownVideo(e: MouseEvent) {
markLabelApi.AddReturnId({ markLabelApi.AddReturnId({
'entity': entity 'entity': entity
}).then((res: any) => { }).then((res: any) => {
if (judgeResponse(res)) return;
let markLabelId: number = res.data.data; let markLabelId: number = res.data.data;
console.log(markLabelId); console.log(markLabelId);
if (markLabelId <= 0) return; if (markLabelId <= 0) return;
markSearchApi.ActivateMarkLabel({ markSearchApi.ActivateMarkLabel({
'cameraId': cameraId, 'cameraId': cameraId,
'markLabelId': markLabelId 'markLabelId': markLabelId
}).then((res: any) => { }).then((res: any) => {
if (judgeResponse(res)) return;
let ret: boolean = res.data.data; let ret: boolean = res.data.data;
console.log(ret, 'ret');
if (ret) { if (ret) {
let obj = { let obj = {
cbCameraId: cameraId, cbCameraId: cameraId,
@ -329,20 +290,18 @@ function mouseDownVideo(e: MouseEvent) {
isDelete: false, isDelete: false,
inFlag: true, inFlag: true,
name: name, name: name,
groupName: name, groupName: name
windowVisible: false //
} }
labelList.value.push(obj) labelList.value.push(obj)
isActiveChoose.value = false isActiveChoose.value = false
piniaStore.updateIsAddLabel({ cmMarkGroupId: 0, labelType: "", isAddLabel: false }) piniaStore.updateIsAddLabel({cmMarkGroupId: 0, labelType: "", isAddLabel: false})
} }
}); });
}) })
} else { } else {
// //
isActiveChoose.value = false isActiveChoose.value = false
piniaStore.updateIsAddLabel({ cmMarkGroupId: 0, labelType: "", isAddLabel: false }) piniaStore.updateIsAddLabel({cmMarkGroupId: 0, labelType: "", isAddLabel: false})
} }
} }
@ -353,64 +312,77 @@ function switchCamera(cameraId: string) {
console.log('get camera obj.', cameraMap.value); console.log('get camera obj.', cameraMap.value);
let cameraObj = cameraMap.value.get(cameraId); let cameraObj = cameraMap.value.get(cameraId);
console.log(cameraObj, 'cameraObj'); console.log(cameraObj, 'cameraObj');
if (!cameraObj) { if (!cameraObj) {
console.log('camera obj not found.'); console.log('camera obj not found.');
return; return;
} }
destroyVideo() curVideoKey.value = cameraId;
console.log('connect webrtc-steamer.');
jessibuca.value.play("ws://192.168.1.117:8080/jessica/live/test.flv") // step2, activate stream.
curVideoKey.value = cameraId console.log('activate stream.');
zlmApi.AddStreamProxy({
'cameraId': cameraObj.id
}).then((res: any) => {
if (judgeResponse(res)) return;
// step3, connect stream.
// closeVideo();
let connInfo = res.data.data;
let app = connInfo.app;
let stream = connInfo.stream;
let wsStreamUrl = apiUrl.ZlmWsStreamUrl;
wsStreamUrl = `${wsStreamUrl}/${app}/${stream}.live.flv`;
jessibuca.value.play(wsStreamUrl);
}
);
// step4, active camera searcher. // step4, active camera searcher.
markSearchApi.IsExistsSearcher({ markSearchApi.IsExistsSearcher({
'cameraId': cameraObj.id 'cameraId': cameraObj.id
}).then((res: any) => { }).then((res: any) => {
if (judgeResponse(res)) return;
let flag: boolean = res.data.data; let flag: boolean = res.data.data;
if (!flag) { if (!flag) {
console.log('not exist searcher.'); console.log('not exist searcher.');
markSearchApi.ActiveSearcher({ markSearchApi.ActiveSearcher({
'cameraId': cameraObj.id 'cameraId': cameraObj.id
}).then((res: any) => { }).then((res: any) => {
if (judgeResponse(res)) return;
let flag: boolean = res.data.data; let flag: boolean = res.data.data;
console.log('activate searcher : ', flag); console.log('activate searcher : ', flag);
if (flag) { if (flag) {
console.log('load camera labels'); console.log('load camera labels');
getLabel(cameraObj.id) getLabel(cameraObj.id);
loadMarkLabelsByLoop(cameraObj); loadMarkLabelsByLoop(cameraObj);
} }
}); });
} else { } else {
console.log('load camera labels'); console.log('load camera labels');
getLabel(cameraObj.id) getLabel(cameraObj.id);
loadMarkLabelsByLoop(cameraObj); loadMarkLabelsByLoop(cameraObj);
} }
}) })
// step5, load camera labels. // step5, load camera labels.
} }
function getLabel(cbCameraId: string | number) {
let str = JSON.stringify({ cbCameraId })
markLabelApi.GetList({ queryJson: str }).then((res: any) => {
if (res.data.code == 200) {
console.log(res, 'res');
labelList.value = res.data.data
labelList.value = labelList.value.map((item: any) => {
let labelGroupList = piniaStore.labelGroupList
labelGroupList.forEach((element: any) => {
if (element.id == item.cmMarkGroupId) {
item.groupName = element.name
}
});
return item
})
console.log(labelList.value, 'labelList.value');
} function getLabel(cbCameraId: string | number) {
}) let str = JSON.stringify({cbCameraId})
markLabelApi.GetList({queryJson: str}).then((res: any) => {
if (judgeResponse(res)) return;
labelList.value = res.data.data
labelList.value = labelList.value.map((item: any) => {
let labelGroupList = piniaStore.labelGroupList
labelGroupList.forEach((element: any) => {
if (element.id == item.cmMarkGroupId) {
item.groupName = element.name
}
});
return item
})
console.log(labelList.value, 'labelList.value');
});
} }
function loadMarkLabelsByLoop(cameraObj: any, ms: number = 1000) { function loadMarkLabelsByLoop(cameraObj: any, ms: number = 1000) {
if (curSelectKey.value !== cameraObj.id) { if (curSelectKey.value !== cameraObj.id) {
console.log('load camera labels end.'); console.log('load camera labels end.');
@ -422,13 +394,14 @@ function loadMarkLabelsByLoop(cameraObj: any, ms: number = 1000) {
// clearTimeout(timer) // clearTimeout(timer)
// }, ms); // }, ms);
} }
function loadMarkLabels(cameraObj: any) { function loadMarkLabels(cameraObj: any) {
markSearchApi.GetMarkLabelCalcResultList({ markSearchApi.GetMarkLabelCalcResultList({
'cameraId': cameraObj.id 'cameraId': cameraObj.id
}).then((res: any) => { }).then((res: any) => {
if (judgeResponse(res)) return;
let list: Array<any> = res.data.data; let list: Array<any> = res.data.data;
console.log(list); console.log(list);
list.forEach((element: any) => { list.forEach((element: any) => {
labelList.value.forEach((item: any, index: number) => { labelList.value.forEach((item: any, index: number) => {
if (element.id == item.id) { if (element.id == item.id) {
@ -436,12 +409,21 @@ function loadMarkLabels(cameraObj: any) {
labelList.value[index].canvasTopRatio = element.canvasTopRatio labelList.value[index].canvasTopRatio = element.canvasTopRatio
labelList.value[index].inFlag = element.inFlag labelList.value[index].inFlag = element.inFlag
} }
}); });
}); });
}); });
} }
function judgeResponse(res: any): boolean {
let flag = false;
if (flag) promptError();
return flag;
}
function promptError() {
// promptError
}
// //
window.onbeforeunload = () => { window.onbeforeunload = () => {
jessibuca.value.destroy() jessibuca.value.destroy()
@ -480,7 +462,7 @@ onUnmounted(() => {
justify-content: center; justify-content: center;
align-items: center; align-items: center;
>div { > div {
position: relative; position: relative;
} }

Loading…
Cancel
Save