You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
duoji-frontend/src/views/videoPlayback/index.vue

411 lines
15 KiB
Vue

2 years ago
<template>
<a-row type="flex" :gutter="30">
<a-col :flex="1">
时间<a-date-picker v-model="date" format="YYYY-MM-DD" placeholder="请选择时间" @change="cameraRecord"/>
<section style="height: 80vh;overflow: hidden;
overflow-y: scroll;">
<a-tree
:tree-data="treeData"
:check-strictly="true"
@select="handleCheck">
</a-tree>
</section>
</a-col>
<a-col :flex="13">
<div>
<div class="time-display">
<!-- 视频 -->
<video ref="videoPlayer" muted style=" display: flex;" width="100%" >
<source :src="currentVideoUrl" type="video/mp4" />
</video>
</div>
<!-- 滑动轴 -->
<div class="zoom-buttons" width="100%" >
<!-- <a-button-group>
<a-button icon="arrows-alt" :disabled="zoom" @click="handleZoomIn"></a-button>
<a-button icon="shrink" :disabled="shrink" @click="handleZoomOut"></a-button>
</a-button-group> -->
</div>
<a-slider
ref="slider"
:marks="marks"
class="progress-bar"
:max="totalDuration"
:tip-formatter="formatter"
:value="currentTime"
:disabled="Object.keys(urls).length === 0"
@change="onSliderChange"
/>
<div class="time-display">
<a-button-group>
<a-button icon="step-backward" :disabled="Object.keys(urls).length === 0" @click="moveForward(-5)" />
<a-button v-if="isPlaying" :disabled="Object.keys(urls).length === 0" icon="pause" @click="pauseVideo" />
<a-button v-else icon="play-circle" :disabled="Object.keys(urls).length === 0" @click="playVideo" />
<a-button icon="step-forward" :disabled="Object.keys(urls).length === 0" @click="moveForward(5)" />
</a-button-group>
</div>
</div>
</a-col>
</a-row>
</template>
<script>
import { Slider, Button, ButtonGroup } from 'ant-design-vue';
import moment from 'moment'
import { message } from 'ant-design-vue';
export default {
components: {
ASlider: Slider,
AButton: Button,
AButtonGroup: ButtonGroup,
},
data() {
return {
totalDuration: 24*60*60, // 假设视频总时长为60s
//数据轴上的数值
currentTime: 0,
//数据轴上的开始时间
startTimeLong: 0,
//数据轴上的结束时间
endTimeLong: 24*60*60,
//当天记录的结束的时间绝对值
maxTimeLong:24*60*60,
//当天记录的开始的时间绝对值
minTimeLong: 0*60*60,
date: this.getYesterday() ,
currentVideoUrl: '', // 当前视频的 URL
value1: '2023-10-11',
urls:{
},
URLStartTime: 0,
isPlaying: false, // 视频是否正在播放
marks:{},
zoom:false,
shrink:true,
treeData: [],
cameraId:'',
};
},
mounted() {
const video = this.$refs.videoPlayer;
video.addEventListener('timeupdate', this.onVideoTimeUpdate);
video.addEventListener('ended', this.playNextVideo);
console.log(this.getTimeMap());
this.totalDuration = this.endTimeLong -this.startTimeLong;
this.marks = this.getTimeMap();
console.log(this.date);
this.getTree()
this.cameraRecord()
},
beforeDestroy() {
const video = this.$refs.videoPlayer;
video.removeEventListener('timeupdate', this.onVideoTimeUpdate);
video.removeEventListener('ended', this.playNextVideo);
},
methods: {
getYesterday(){
const now = moment();
return now.subtract(1, 'days')
},
scaleTime(rate) {
const middle = this.startTimeLong +this.currentTime;
// 计算开始时间到中间时间的毫秒数
const startToMiddleMs = middle - this.startTimeLong;
// 计算结束时间到中间时间的毫秒数
const endToMiddleMs = this.endTimeLong - middle;
// 缩小或放大开始时间
const scaledStart = middle -Math.floor( startToMiddleMs * rate);
console.log("开始缩小时间"+ scaledStart);
// 缩小或放大结束时间
const scaledEnd =middle +Math.floor( endToMiddleMs * rate);
console.log("结束缩小时间"+ scaledEnd);
// 检查是否超出当天时间的范围并赋值
this.startTimeLong = this.minTimeLong>scaledStart?this.minTimeLong : scaledStart;
this.endTimeLong = this.maxTimeLong<scaledEnd?this.maxTimeLong : scaledEnd;
//时间修改
if(this.minTimeLong<scaledStart || this.maxTimeLong>scaledEnd){
this.shrink=false;
}else{
this.shrink=true;
}
console.log("zhou"+middle);
this.updateslider(middle)
},
formatTime(seconds) {
seconds = seconds%(60*60*24);
const hour = Math.floor(seconds / 3600);
const minute = Math.floor((seconds % 3600) / 60);
const second = seconds % 60;
return `${hour.toString().padStart(2, '0')}:${minute.toString().padStart(2, '0')}:${second.toString().padStart(2, '0')}`;
},
// 点击放大按钮触发的方法
handleZoomIn() {
this.scaleTime(0.5)
},
// 点击缩小按钮触发的方法
handleZoomOut() {
this.scaleTime(2)
},
//根据开始时间修改时间轴(轴位置不变,请在外部修改)
updateslider(middle){
this.totalDuration = this.endTimeLong - this.startTimeLong;
console.log("轴上数值为:"+(middle-this.startTimeLong));
this.currentTime = (middle-this.startTimeLong);
this.marks = this.getTimeMap();
},
getTree(){
this.$api.httpApi.getAllStreet({
}).then(res => {
console.log("update data")
for(let i = 0;i<res.data.length;i++){
// 创建空对象
const obj = {};
// 添加属性和值
obj["title"] = res.data[i].name;
obj["key"] = res.data[i].id;
obj["type"] = 0
obj["children"] =[];
if( res.data[i].camera1Id !=""){
const obj1 = {};
obj1["title"] = res.data[i].camera1Name
obj1["key"] = res.data[i].camera1Id
obj1["type"] = 1
obj["children"].push(obj1)
}
if( res.data[i].camera2Id !=""){
const obj1 = {};
obj1["title"] = res.data[i].camera2Name
obj1["key"] = res.data[i].camera2Id
obj1["type"] = 1
obj["children"].push(obj1)
}
this.treeData.push(obj)
}
console.log(this.treeData);
}).catch(err => {
});
},
getTimeMap() {
const diff = this.endTimeLong - this.startTimeLong; // 计算时间差,单位为秒
console.log(diff + " qqq");
const map = {};
if (diff >= 60 * 60 * 3) {
this.TimeMapErgodic(60*60,map);
} else if (diff >= 60 * 60) {
// 如果大于等于1小时小于3小时每15分钟一个标识
this.TimeMapErgodic(15*60,map);
} else if (diff >= 60*20) {
this.zoom = false;
// 如果大于等于20分钟小于1小时每5分钟一个标识
this.TimeMapErgodic(5*60,map);
} else if (diff >= 5* 60) {
this.zoom = false;
// 如果大于等于5分钟小于20分钟每分钟一个标识
this.TimeMapErgodic(60,map);
} else if (diff >= 30) {
this.zoom = false;
// 如果小于5分钟大于1m每30s一个标识
console.log("如果小于5分钟大于1m每30s一个标识");
console.log(startTime +" "+endTime)
this.TimeMapErgodic(30,map);
} else if (diff >= 10) {
this.zoom = true;
// 如果小于1m大于10s 5s标识
this.TimeMapErgodic(5,map);
} else {
this.zoom = true;
// 如果小于10s 1s标识
this.TimeMapErgodic(1,map);
}
return map;
},
//遍历获取time映射
TimeMapErgodic(interval,map){
const startTime =Math.ceil(this.startTimeLong/(interval)) *interval;
const endTime =Math.floor(this.endTimeLong/(interval))*interval;
for (let i = startTime ; i<= endTime; i+=interval) {
const minuteDiff = (i - this.startTimeLong) ;
map[minuteDiff] = `${String(Math.floor(i/(60*60))).padStart(2, '0')}:${String(Math.floor((i%(60*60))/(60))).padStart(2, '0')}:${String((i%(60))).padStart(2, '0')}`;
}
return map;
},
//将秒数转为 时分秒
formatter(value) {
const i = this.startTimeLong + value
// 格式化输出新的时间
const hours = String(Math.floor(i/(60*60))).padStart(2, '0');
const minutes = String(Math.floor((i%(60*60))/(60))).padStart(2, '0');
const seconds = String(Math.floor((i%(60)))).padStart(2, '0');
return `${hours}:${minutes}:${seconds}`;
},
//二分法
binarySearchMax(arr, target) {
let left = 0;
let right = arr.length - 1;
let max = -Infinity;
console.log(arr);
while (left <= right) {
const mid = Math.floor((left + right) / 2);
if (arr[mid] <= target) {
max = Math.max(max, arr[mid]);
left = mid + 1;
} else {
right = mid - 1;
}
}
return max;
},
//横轴改变
onSliderChange(value) {
console.log(value);
this.URLStartTime = this.binarySearchMax(Object.keys(this.urls),value+this.minTimeLong);
this.currentVideoUrl = this.urls[this.URLStartTime]
this.currentTime = value;
const video = this.$refs.videoPlayer;
video.currentTime = value +this.startTimeLong-this.URLStartTime ;
},
//视频时间改变
onVideoTimeUpdate() {
const video = this.$refs.videoPlayer;
console.log("视频时间"+(this.URLStartTime + video.currentTime));
this.currentTime =this.URLStartTime + video.currentTime-this.startTimeLong;
},
//向后
moveForward(duration) {
console.log("111");
const newTime = this.currentTime + duration;
if (newTime >= 0 ||newTime <= this.totalDuration) {
this.currentTime = newTime;
const video = this.$refs.videoPlayer;
video.currentTime = newTime;
}
},
playVideo() {
const video = this.$refs.videoPlayer;
this.isPlaying = true;
console.log( this.currentTime +this.startTimeLong - this.URLStartTime);
video.currentTime = this.currentTime +this.startTimeLong - this.URLStartTime
video.play();
},
pauseVideo() {
const video = this.$refs.videoPlayer;
this.isPlaying = false;
video.pause();
},
playNextVideo() {
let nextKey =this.URLStartTime;
const keys = Object.keys(this.urls);
// 找到当前键的索引
const currentIndex = keys.indexOf(this.URLStartTime.toString());
console.log(keys);
if (currentIndex !== -1 && currentIndex < keys.length - 1) {
nextKey = Number(keys[currentIndex + 1]);
const video = this.$refs.videoPlayer;
this.URLStartTime = nextKey;
this.currentVideoUrl = this.urls[nextKey] ;
this.currentTime =this.URLStartTime;
video.currentTime =0;
video.play();
}
},
handleCheck(selectedKeys, e){
if(e.selectedNodes[0].data.props.type == 1){
this.cameraId = e.selectedNodes[0].data.key;
console.log(e.selectedNodes[0].data);
this.cameraRecord()
}
console.log(e.selectedNodes[0].data.props);
},
cameraRecord(){
this.$api.httpApi.cameraRecord({
data: {
date: this.date._d.getFullYear() + '-' + (this.date._d.getMonth() + 1) + '-' + this.date._d.getDate(),
cameraId: this.cameraId,
}
}).then(res => {
console.log("update data")
if( (res.data.startTimeLong !== null && res.data.startTimeLong !== undefined && res.data.startTimeLong !== "")
||( res.data.endTimeLong !== null && res.data.endTimeLong!== undefined &&res.data.endTimeLong !== '')){
}
if(res.data.urls !== null && res.data.urls !== undefined && Object.keys(res.data.urls).length >0){
this.startTimeLong = res.data.startTimeLong
this.endTimeLong = res.data.endTimeLong
this.minTimeLong = res.data.startTimeLong
this.maxTimeLong = res.data.endTimeLong
this.currentTime = 0
this.totalDuration = res.data.endTimeLong - res.data.startTimeLong
this.currentVideoUrl = res.data.urls[0].url
const video = this.$refs.videoPlayer;
video.currentTime = 0 ;
const map = {};
for(let i = 0;i<res.data.urls.length;i++){
map[res.data.urls[i].startTimeLong] = res.data.urls[i].url
}
this.urls = map
this.marks = this.getTimeMap();
console.log(map);
}else{
if(this.cameraId !== null && this.cameraId !== undefined && this.cameraId !== ""){
message.info('此摄像头该日期未录像');
}
}
}).catch(err => {
console.log(err);
});
}
},
};
</script>
<style>
.progress-bar .ant-slider-rail {
background-color: lightgray;
}
.progress-bar .ant-slider-track {
background-color: dodgerblue;
}
.time-display {
margin-top: 10px;
display: flex;
justify-content: center;
align-items: center;
}
.zoom-buttons {
text-align: right;
margin-bottom: 16px;
}
</style>