video_ca/src/views/VideoStream.vue

105 lines
3.3 KiB
Vue
Raw Normal View History

2024-12-26 15:35:40 +08:00
<template>
<div>
<video ref="videoPlayer" autoplay playsinline></video>
</div>
</template>
<script>
import axios from "axios";
export default {
data() {
return {
videoPlayer: null,
source: null, // 用于存储axios的CancelToken.source对象以便后续取消请求
};
},
mounted() {
this.videoPlayer = this.$refs.videoPlayer;
this.startVideoStream();
},
methods: {
startVideoStream() {
//let url = "https://gep.ljsea.top/device/video_feed?" +"&device_id=" +localStorage.getItem("realvp_device_id") +"&token=" +localStorage.getItem("token"); //视频地址
const deviceId = localStorage.getItem("realvp_device_id"); // 替换为实际存储设备id的方式和键名
const token = localStorage.getItem("token"); // 替换为实际存储token的方式和键名
const url = `https://gep.ljsea.top/device/video_feed?device_id=${deviceId}&token=${token}`;
this.source = axios.CancelToken.source();
axios
.get(url, {
responseType: "arraybuffer",
cancelToken: this.source.token,
})
.then((response) => {
console.log("获取视频流成功");
const reader = response.data
.pipeThrough(new window.TextDecoderStream())
.getReader();
const processData = () => {
reader.read().then(({ done, value }) => {
if (done) {
return;
}
const dataString = new window.TextDecoder().decode(value);
const parts = dataString.split("\r\n");
// 检查是否包含关键的视频流格式标识
const hasFrameMarker = parts.some((part) =>
part.startsWith("--frame")
);
const hasContentTypeMarker = parts.some(
(part) => part === "Content-Type: image/jpeg"
);
if (!hasFrameMarker || !hasContentTypeMarker) {
console.error("视频流数据格式不符合预期,无法解析");
return;
}
parts.forEach((part) => {
if (part.startsWith("--frame")) {
const imageData = [];
let isImageData = false;
parts.forEach((subPart) => {
if (isImageData) {
imageData.push(subPart);
}
if (subPart === "Content-Type: image/jpeg") {
isImageData = true;
}
});
const imageBlob = new Blob(imageData, { type: "image/jpeg" });
const objectURL = URL.createObjectURL(imageBlob);
this.videoPlayer.src = objectURL;
}
});
processData();
});
};
processData();
})
.catch((error) => {
if (axios.isCancel(error)) {
console.log("请求已取消");
} else {
console.error("获取视频流出错:", error);
}
});
},
},
beforeUnmount() {
if (this.source) {
this.source.cancel("组件即将销毁,取消视频流请求");
}
},
};
</script>
<style scoped>
video {
width: 100%;
max-width: 800px;
margin: 0 auto;
}
</style>