hls流视频播放海康视频

vue yekong

数据可视化大屏项目开发中,需要播放监控,这里我们通过hls.js来播放我们的监控视频。

hls流视频播放海康视频

测试在线

我们在写代码前,先使用在线工具测试一下,看看我们收到的视频流地址是否可以播放,之前客户提供的视频一直不能播放,使用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>

喜欢