当前位置: 首页 > news >正文

使用ezuikit-js封装一个对接摄像头的组件

ezuikit-js 是一个基于 JavaScript 的视频播放库,主要用于在网页中嵌入实时视频流播放功能。它通常用于与支持 RTSP、RTMP、HLS 等协议的摄像头或视频流服务器进行交互,提供流畅的视频播放体验。

主要功能
多协议支持:支持 RTSP、RTMP、HLS 等主流视频流协议。

实时播放:低延迟播放实时视频流。

多平台兼容:支持 PC 端和移动端浏览器。

丰富的 API:提供 JavaScript API,方便开发者自定义控制和集成。

轻量级:库文件体积小,加载速度快。

使用场景
安防监控:实时查看摄像头视频流。

直播应用:嵌入直播视频流到网页中。

视频会议:播放远程会议视频流。

PlayVideomonitor.vue组件

<template>
  <el-dialog
    v-model="dialogVisible"
    :width="isLargeScreen ? 1680 : 840"
    :close-on-click-modal="false"
    :close-on-press-escape="false"
  >
    <template #title>
      <div style="display: flex; align-items: center">
        监控摄像头 ({{ playName }}) &nbsp; &nbsp;
        <el-button
          type="text"
          size="mini"
          class="refresh-btn"
          @click="refreshFun"
          title="点击刷新"
        >
          <template #icon>
            <span class="ti-shuaxin"></span>
          </template>
        </el-button>
        &nbsp; &nbsp;&nbsp; &nbsp;
      </div>
    </template>
    <el-tabs v-model="playType" class="demo-tabs" @tab-click="tabeChange">
      <el-tab-pane label="实时视频" name="pcLive">
        <div :id="playConfig" class="videoMonitor-content"></div>
      </el-tab-pane>
      <el-tab-pane label="历史回放" name="pcRec">
        <div :id="playRecConfig" class="videoMonitor-content"></div>
      </el-tab-pane>
    </el-tabs>
  </el-dialog>
</template>

<script lang="ts" setup>
import EZUIKit from "ezuikit-js";
import { uuid } from "vue-uuid";
import { ElMessage } from "element-plus";
import {
  computed,
  getCurrentInstance,
  onMounted,
  ref,
  defineProps,
  defineEmits,
} from "vue";
import userInfoStorage from "@/userInfoStorage";
import { useMediaQuery } from "@vueuse/core";
const { proxy }: any = getCurrentInstance();
const props = defineProps<{
  modelValue: Boolean;
  playId: string | null;
  projectId: string;
  playName: string;
}>();

const emits = defineEmits<{
  (e: "update:modelValue", value: Boolean): void;
}>();

const isLargeScreen = useMediaQuery("(min-height:2000px)");
//公司id
const companyId = computed(() => {
  return userInfoStorage.getCompanyId();
});
let player: any = null;
let playerRec: any = null;
const dialogVisible = computed({
  get() {
    return props.modelValue;
  },
  set(v: Boolean) {
    emits("update:modelValue", v);
  },
});
const playConfig = ref(uuid.v4());
const playRecConfig = ref(uuid.v4());
const playType = ref("pcLive");
const getAccessToken = () => {
  if (playType.value !== "") {
    proxy.axios
      .get(
        `/cloud/camera/company/${companyId.value}/project/${props.projectId}/play-video/${props.playId}?linkType=0  `
      )
      .then(({ data }: { data: any }) => {
        if (data.errorcode == 0) {
          if (playType.value == "pcLive") {
            init(data.data.accessToken, data.data.url, "pcLive");
          } else if (playType.value == "pcRec") {
            initRec(data.data.accessToken, data.data.url, "pcRec");
          }
        } else {
          ElMessage.warning(data.message);
        }
      })
      .catch((err: any) => {
        console.error(err);
      });
  }
};
const tabeChange = (val: any) => {
  if (playType.value == "pcLive") {
    if (player) {
      destroy();
    }
  } else {
    if (playerRec) {
      destroyRec();
    }
  }
  getAccessToken();
};
function init(token: any, url: any, playType: any) {
  if (player) {
    destroy();
  }
  player = new EZUIKit.EZUIKitPlayer({
    id: playConfig.value, // 视频容器ID
    accessToken: token,
    url: url,
    width: isLargeScreen.value ? 1600 : 800,
    height: isLargeScreen.value ? 900 : 450,
    template: playType,
  });
  setTimeout(() => {
    player.play();
  }, 500);
}
function initRec(token: any, url: any, playType: any) {
  if (playerRec) {
    destroyRec();
  }
  player = new EZUIKit.EZUIKitPlayer({
    id: playRecConfig.value, // 视频容器ID
    accessToken: token,
    url: url,
    width: isLargeScreen.value ? 1600 : 800,
    height: isLargeScreen.value ? 900 : 450,
    template: playType,
  });

  playerRec.play();
}

function destroy() {
  if (player) {
    player.destroy();
  }
  player = null;
}
function destroyRec() {
  if (playerRec) {
    playerRec.destroy();
  }
  playerRec = null;
}

const refreshFun = () => {
  getAccessToken();
};
onMounted(() => {
  getAccessToken();
});
</script>
<style scoped>
.videoMonitor-content {
  height: 400px;
}

.el-dialog:deep(.el-dialog__body) {
  padding: 0 var(--el-dialog-padding-primary);
}
@media (min-height: 2000px) {
  .videoMonitor-content {
    height: 800px;
  }
}
</style>

父组件使用

<!-- 遍历video信息  把每一个信息传给monitorClick事件 -->
<template v-if="videoData && videoData.length > 0">
        <div v-for="(item, index) in videoData" :key="item.cameraId">
          <span
            :title="item.alias"
            class="imgconetnt"
            @click="monitorClick(item)"
          >
            <img src="@/assets/img/monitor1.png" class="monitor-img" />
          </span>
        </div>
      </template>
<PlayVideomonitor
    v-model="monitorVis"
    v-if="monitorVis"
    :playId="playId"
    :playName="playName"
    :projectId="projectId"
  />
//projectId是自定义属性,业务工程id
const monitorVis = ref<boolean>(false);
const playId = ref("");
const playName = ref("");
//获取video信息
const videoData = ref<any[]>([]);
const getVideoData = () => {
  appAxios
    .get(
      `/cloud/camera/company/${companyId.value}/project/${props.projectId}/cameras?linkType=0`
    )
    .then(({ data }: { data: any }) => {
      if (data.errorcode == 0) {
        let res = data.data;
        videoData.value = res;
      } else {
        ElMessage.error(data.message);
      }
    })
    .catch((err) => {
      console.error(err);
    });
};
//点击每一个摄像头拿到每一个信息
const monitorClick = (row: any) => {
  if (row.status == 2) {
    return notificationMessage("摄像头状态异常,无法播放", "提示", "warning");
  }
  if (row.status == 0) {
    return notificationMessage("摄像头已被禁用,无法播放", "提示", "error");
  }
  monitorVis.value = true;
  playId.value = row.cameraId;
  playType.value = row.videoQuality;
  playName.value = row.alias;
};

相关文章:

  • node和vue的主流版本组合版本介绍
  • DeepSeek与AI幻觉
  • [寻找密码]
  • 游戏引擎学习第116天
  • Linux--进程(进程虚拟地址空间、页表、进程控制、实现简易shell)
  • python字符串列表
  • ROS2学习
  • 25工程管理研究生复试面试问题汇总 工程管理专业知识问题很全! 工程管理复试全流程攻略 工程管理考研复试真题汇总
  • 深度学习图像预处理可视化:拆解Compose操作的全过程
  • Java并发编程面试题:ThreadLocal(8题)
  • VIM FZF 安裝和使用
  • ClickHouse系列之ClickHouse安装
  • 8. MySQL 索引的创建与涉及原则(详解说明)
  • JavaScript函数-函数的使用
  • Ubuntu服务器 /data 盘需要手动挂载的解决方案
  • WPS PPT插入各种线型形状(如画直线)的时候总是有箭头,如何还原成只画直线
  • CSS垂直居中终极方案:告别复杂计算,拥抱现代布局
  • RocksDB Bloom Filter 如何避免假阳性问题探索
  • Ubuntu 22.04安装K8S集群
  • MySQL的Union和OR查询
  • 中非民间对话在赞比亚举行
  • 临港新片区:发布再保险、国际航运、生物医药3个领域数据出境操作指引
  • 【社论】职业上新,勇于“尝新”
  • 江西暴雨强对流明显,专家:落雨区高度重叠,地质灾害风险高
  • 中日有关部门就日本水产品输华问进行第三次谈判,外交部回应
  • 人民日报整版聚焦:铭记二战历史,传承深厚友谊