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

550 lines
20 KiB
Vue

2 years ago
<template>
2 years ago
<a-row
type="flex"
:gutter="30"
>
2 years ago
2 years ago
<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="60%"
>
<source
:src="'http://192.168.1.110:8007'+currentVideoUrl"
type="video/mp4"
/>
</video>
</div>
<!-- 滑动轴 'http://192.168.1.110:8007'+currentVideoUrl -->
<div
class="zoom-buttons"
width="100%"
>
<!-- <a-button-group>
2 years ago
<a-button icon="arrows-alt" :disabled="zoom" @click="handleZoomIn"></a-button>
<a-button icon="shrink" :disabled="shrink" @click="handleZoomOut"></a-button>
</a-button-group> -->
2 years ago
</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>
2 years ago
</template>
<script>
2 years ago
import { Slider, Button, ButtonGroup } from "ant-design-vue";
2 years ago
2 years ago
import moment from "moment";
2 years ago
2 years ago
import { message } from "ant-design-vue";
2 years ago
export default {
components: {
ASlider: Slider,
AButton: Button,
AButtonGroup: ButtonGroup,
},
data() {
return {
2 years ago
totalDuration: 24 * 60 * 60, // 假设视频总时长为60s
2 years ago
//数据轴上的数值
currentTime: 0,
//数据轴上的开始时间
startTimeLong: 0,
//数据轴上的结束时间
2 years ago
endTimeLong: 24 * 60 * 60,
2 years ago
//当天记录的结束的时间绝对值
2 years ago
maxTimeLong: 24 * 60 * 60,
2 years ago
//当天记录的开始的时间绝对值
2 years ago
minTimeLong: 0 * 60 * 60,
date: this.getYesterday(),
currentVideoUrl: "", // 当前视频的 URL
value1: "2023-10-11",
urls: {},
mapByTime: {},
2 years ago
URLStartTime: 0,
isPlaying: false, // 视频是否正在播放
2 years ago
marks: {},
zoom: false,
shrink: true,
2 years ago
treeData: [],
2 years ago
cameraId: "",
playObject: {},
getSuccessUrl: [],
2 years ago
};
},
mounted() {
const video = this.$refs.videoPlayer;
2 years ago
video.addEventListener("timeupdate", this.onVideoTimeUpdate);
video.addEventListener("ended", this.playNextVideo);
2 years ago
console.log(this.getTimeMap());
2 years ago
this.totalDuration = this.endTimeLong - this.startTimeLong;
2 years ago
this.marks = this.getTimeMap();
console.log(this.date);
2 years ago
this.getTree();
this.cameraRecord();
2 years ago
},
beforeDestroy() {
const video = this.$refs.videoPlayer;
2 years ago
video.removeEventListener("timeupdate", this.onVideoTimeUpdate);
video.removeEventListener("ended", this.playNextVideo);
2 years ago
},
2 years ago
methods: {
videoControl(seconds) {
//获取playObject参数
this.binarySearchMax(seconds);
//后台获取资源
if (!this.getSuccessUrl.includes(this.currentVideoUrl)) {
//加载视频
this.$api.httpApi
.cameraRecordConvetor({
data: {
url: this.currentVideoUrl,
},
})
.then((res) => {
this.getSuccessUrl.push(this.currentVideoUrl);
});
}
//读取MP4文件
const video = this.$refs.videoPlayer;
this.isPlaying = true;
video.load(); // 重新加载视频资源
//计算时间
video.currentTime =
this.currentTime - this.playObject.startTimeLong;
//播放或停止
if (this.isPlaying) {
video.play();
} else {
video.pause();
}
},
//获取前一天
getYesterday() {
2 years ago
const now = moment();
2 years ago
return now.subtract(1, "days");
2 years ago
},
2 years ago
//放大缩小轴所用
2 years ago
scaleTime(rate) {
2 years ago
const middle = this.startTimeLong + this.currentTime;
2 years ago
// 计算开始时间到中间时间的毫秒数
const startToMiddleMs = middle - this.startTimeLong;
// 计算结束时间到中间时间的毫秒数
const endToMiddleMs = this.endTimeLong - middle;
// 缩小或放大开始时间
2 years ago
const scaledStart = middle - Math.floor(startToMiddleMs * rate);
console.log("开始缩小时间" + scaledStart);
2 years ago
// 缩小或放大结束时间
2 years ago
const scaledEnd = middle + Math.floor(endToMiddleMs * rate);
console.log("结束缩小时间" + scaledEnd);
2 years ago
// 检查是否超出当天时间的范围并赋值
2 years ago
this.startTimeLong =
this.minTimeLong > scaledStart ? this.minTimeLong : scaledStart;
this.endTimeLong =
this.maxTimeLong < scaledEnd ? this.maxTimeLong : scaledEnd;
2 years ago
//时间修改
2 years ago
if (
this.minTimeLong < scaledStart ||
this.maxTimeLong > scaledEnd
) {
this.shrink = false;
} else {
this.shrink = true;
2 years ago
}
2 years ago
console.log("zhou" + middle);
this.updateslider(middle);
2 years ago
},
2 years ago
//获取当前时间
2 years ago
formatTime(seconds) {
2 years ago
seconds = seconds % (60 * 60 * 24);
2 years ago
const hour = Math.floor(seconds / 3600);
const minute = Math.floor((seconds % 3600) / 60);
const second = seconds % 60;
2 years ago
return `${hour.toString().padStart(2, "0")}:${minute
.toString()
.padStart(2, "0")}:${second.toString().padStart(2, "0")}`;
2 years ago
},
// 点击放大按钮触发的方法
handleZoomIn() {
2 years ago
this.scaleTime(0.5);
2 years ago
},
// 点击缩小按钮触发的方法
handleZoomOut() {
2 years ago
this.scaleTime(2);
2 years ago
},
//根据开始时间修改时间轴(轴位置不变,请在外部修改)
2 years ago
updateslider(middle) {
2 years ago
this.totalDuration = this.endTimeLong - this.startTimeLong;
2 years ago
console.log("轴上数值为:" + (middle - this.startTimeLong));
this.currentTime = middle - this.startTimeLong;
2 years ago
this.marks = this.getTimeMap();
},
2 years ago
//巷道列表
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);
2 years ago
}
2 years ago
console.log(this.treeData);
})
.catch((err) => {});
2 years ago
},
2 years ago
//根据时间间隔调整横轴时间片段
2 years ago
getTimeMap() {
2 years ago
const diff = this.endTimeLong - this.startTimeLong; // 计算时间差,单位为秒
2 years ago
console.log(diff + " qqq");
const map = {};
if (diff >= 60 * 60 * 3) {
2 years ago
this.TimeMapErgodic(60 * 60, map);
} else if (diff >= 60 * 60) {
// 如果大于等于1小时小于3小时每15分钟一个标识
this.TimeMapErgodic(15 * 60, map);
} else if (diff >= 60 * 20) {
2 years ago
this.zoom = false;
2 years ago
// 如果大于等于20分钟小于1小时每5分钟一个标识
this.TimeMapErgodic(5 * 60, map);
} else if (diff >= 5 * 60) {
2 years ago
this.zoom = false;
2 years ago
// 如果大于等于5分钟小于20分钟每分钟一个标识
this.TimeMapErgodic(60, map);
} else if (diff >= 30) {
2 years ago
this.zoom = false;
2 years ago
// 如果小于5分钟大于1m每30s一个标识
2 years ago
console.log("如果小于5分钟大于1m每30s一个标识");
2 years ago
console.log(startTime + " " + endTime);
this.TimeMapErgodic(30, map);
} else if (diff >= 10) {
2 years ago
this.zoom = true;
2 years ago
// 如果小于1m大于10s 5s标识
this.TimeMapErgodic(5, map);
} else {
2 years ago
this.zoom = true;
2 years ago
// 如果小于10s 1s标识
this.TimeMapErgodic(1, map);
}
2 years ago
return map;
},
//遍历获取time映射
2 years ago
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")}`;
}
2 years ago
return map;
},
//将秒数转为 时分秒
2 years ago
formatter(value) {
const i = this.startTimeLong + value;
2 years ago
// 格式化输出新的时间
2 years ago
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");
2 years ago
return `${hours}:${minutes}:${seconds}`;
},
2 years ago
//当改变横轴时获取视频开始时间和url
binarySearchMax(target) {
var maxSmaller = null;
let nums = Object.keys(this.mapByTime);
//console.log(nums);
let num = 0;
for (let numString of nums) {
num = parseInt(this.mapByTime[numString].endTimeLong);
if (target < num) {
this.playObject = this.mapByTime[numString];
if (
!(
target >
parseInt(this.mapByTime[numString].startTimeLong)
)
) {
this.currentTime = parseInt(
this.mapByTime[numString].startTimeLong
);
} else {
this.currentTime = target;
}
this.currentVideoUrl = this.playObject.url;
2 years ago
2 years ago
console.log(this.currentVideoUrl);
break;
2 years ago
}
}
2 years ago
return maxSmaller;
2 years ago
},
//横轴改变
onSliderChange(value) {
2 years ago
this.videoControl(value);
2 years ago
},
//视频时间改变
onVideoTimeUpdate() {
const video = this.$refs.videoPlayer;
2 years ago
console.log(
"视频时间" + (this.playObject.startTimeLong + video.currentTime)
);
this.currentTime =
this.playObject.startTimeLong +
video.currentTime -
this.startTimeLong;
2 years ago
},
2 years ago
//左右调整
2 years ago
moveForward(duration) {
console.log("111");
2 years ago
this.videoControl(this.currentTime + duration)
2 years ago
},
playVideo() {
2 years ago
console.log(this.currentVideoUrl);
if (this.currentVideoUrl == null || this.currentVideoUrl == "") {
this.binarySearchMax(0);
}
//加载视频
console.log(this.getSuccessUrl.includes(this.currentVideoUrl));
if (!this.getSuccessUrl.includes(this.currentVideoUrl)) {
//加载视频
this.$api.httpApi
.cameraRecordConvetor({
data: {
url: this.currentVideoUrl,
},
})
.then((res) => {
this.getSuccessUrl.push(this.currentVideoUrl);
});
}
2 years ago
const video = this.$refs.videoPlayer;
this.isPlaying = true;
2 years ago
video.load(); // 重新加载视频资源
video.currentTime =
this.currentTime - this.playObject.startTimeLong;
2 years ago
video.play();
},
pauseVideo() {
const video = this.$refs.videoPlayer;
this.isPlaying = false;
video.pause();
},
2 years ago
playNextVideo() {
let nextKey = this.URLStartTime;
2 years ago
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;
2 years ago
this.currentVideoUrl = this.urls[nextKey];
video.load(); // 重新加载视频资源
this.currentTime = this.URLStartTime;
video.currentTime = 0;
2 years ago
video.play();
}
},
2 years ago
handleCheck(selectedKeys, e) {
if (e.selectedNodes[0].data.props.type == 1) {
2 years ago
this.cameraId = e.selectedNodes[0].data.key;
console.log(e.selectedNodes[0].data);
2 years ago
this.cameraRecord();
2 years ago
}
console.log(e.selectedNodes[0].data.props);
},
2 years ago
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 !== "")
) {
2 years ago
}
2 years ago
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;
const map = {};
const mapByTime = {};
for (let i = 0; i < res.data.urls.length; i++) {
map[res.data.urls[i].startTimeLong] =
res.data.urls[i].url;
}
for (let i = 0; i < res.data.urls.length; i++) {
mapByTime[res.data.urls[i].startTimeLong] =
res.data.urls[i];
}
this.urls = map;
this.mapByTime = mapByTime;
2 years ago
2 years ago
this.marks = this.getTimeMap();
console.log(map);
} else {
if (
this.cameraId !== null &&
this.cameraId !== undefined &&
this.cameraId !== ""
) {
message.info("此摄像头该日期未录像");
}
}
})
.catch((err) => {
console.log(err);
});
},
2 years ago
},
};
</script>
<style>
2 years ago
.progress-bar .ant-slider-rail {
2 years ago
background-color: lightgray;
2 years ago
}
2 years ago
2 years ago
.progress-bar .ant-slider-track {
2 years ago
background-color: dodgerblue;
2 years ago
}
2 years ago
2 years ago
.time-display {
2 years ago
margin-top: 10px;
display: flex;
justify-content: center;
align-items: center;
2 years ago
}
.zoom-buttons {
text-align: right;
margin-bottom: 16px;
2 years ago
}
</style>