数据可视化大屏项目开发中,需要播放监控,这里我们通过hls.js来播放我们的监控视频。
测试在线
我们在写代码前,先使用在线工具测试一下,看看我们收到的视频流地址是否可以播放,之前客户提供的视频一直不能播放,使用IINA可以播放,但是使用网页无法播放,通过在线播放器测试也不能播放,这才确定代码没问题,可能是其他方面的问题。
海康流视频地址
下面是一个海康视频接口返回的视频格式示例地址
{
"url": "https://192.168.1.1:6014/openUrl/eLkjsGs/live.m3u8"
}
安装依赖
npm install hls.js
实例代码
<template>
<div ref="videoContainer" class="video-container">
<!-- <div class="fullscreen-button" @click="toggleFullscreen">-->
<!-- <img src="./assets/icon_full.png" alt="Fullscreen" class="fullscreen-icon" />-->
<!-- </div>-->
<video
ref="videoPlayer"
class="video-player"
controls
preload="auto"
muted
autoplay
></video>
</div>
</template>
<script setup>
import {onMounted, onBeforeUnmount, ref, watch} from "vue";
import Hls from "hls.js";
const props = defineProps({
src: {
type: String,
required: true,
},
});
const videoPlayer = ref(null);
const videoContainer = ref(null);
let hls = null;
const initializePlayer = () => {
if (Hls.isSupported()) {
hls = new Hls();
hls.loadSource(props.src);
hls.attachMedia(videoPlayer.value);
hls.on(Hls.Events.MANIFEST_PARSED, () => {
videoPlayer.value.play().catch(error => {
console.error("自动播放失败:", error);
});
});
} else if (videoPlayer.value.canPlayType("application/vnd.apple.mpegurl")) {
// 对于不支持 HLS.js 但原生支持 HLS 的浏览器(如 Safari)
videoPlayer.value.src = props.src;
videoPlayer.value.addEventListener("loadedmetadata", () => {
videoPlayer.value.play().catch(error => {
console.error("自动播放失败:", error);
});
});
}
// 确保播放器大小与容器同步
const resizeObserver = new ResizeObserver(() => {
if (videoPlayer.value) {
videoPlayer.value.style.width = `${videoContainer.value.clientWidth}px`;
videoPlayer.value.style.height = `${videoContainer.value.clientHeight}px`;
}
});
resizeObserver.observe(videoContainer.value);
};
onMounted(() => {
initializePlayer();
});
onBeforeUnmount(() => {
if (hls) {
hls.destroy();
}
});
watch(() => props.src, (newSrc) => {
if (hls) {
hls.loadSource(newSrc);
} else if (videoPlayer.value.canPlayType("application/vnd.apple.mpegurl")) {
videoPlayer.value.src = newSrc;
videoPlayer.value.play().catch(error => {
console.error("自动播放失败:", error);
});
}
});
const toggleFullscreen = () => {
if (!document.fullscreenElement) {
if (videoContainer.value.requestFullscreen) {
videoContainer.value.requestFullscreen();
} else if (videoContainer.value.mozRequestFullScreen) { // Firefox
videoContainer.value.mozRequestFullScreen();
} else if (videoContainer.value.webkitRequestFullscreen) { // Chrome, Safari and Opera
videoContainer.value.webkitRequestFullscreen();
} else if (videoContainer.value.msRequestFullscreen) { // IE/Edge
videoContainer.value.msRequestFullscreen();
}
} else {
if (document.exitFullscreen) {
document.exitFullscreen();
} else if (document.mozCancelFullScreen) { // Firefox
document.mozCancelFullScreen();
} else if (document.webkitExitFullscreen) { // Chrome, Safari and Opera
document.webkitExitFullscreen();
} else if (document.msExitFullscreen) { // IE/Edge
document.msExitFullscreen();
}
}
};
</script>
<style scoped>
.video-container {
width: 100%;
height: 100%;
position: relative;
overflow: hidden;
}
.fullscreen-button {
position: absolute;
top: 10px;
right: 10px;
z-index: 1000;
width: 28px;
height: 28px;
background: rgba(0, 0, 0, 0.6);
border-radius: 4px;
border: 1px solid #305295;
backdrop-filter: blur(5px);
display: flex;
justify-content: center;
align-items: center;
cursor: pointer;
}
.fullscreen-icon {
width: 16px;
height: 17px;
}
.video-player {
width: 100%;
height: 100%;
object-fit: cover;
}
</style>