董国庆
2025-04-18 d70de98b263f657a7714301a73ac210e9cd2828e
首页监控
2个文件已修改
126 ■■■■■ 已修改文件
src/view/home/index.vue 116 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/view/home/service.js 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/view/home/index.vue
@@ -208,11 +208,14 @@
  getWarnGroupCount,
  getWarnGroupCountTop10,
  getRealVideo,
  playDetection,
  closeRealVideo,
} from "./service";
export default {
  data() {
    return {
      flvPlayer: null,
      videoTimer: null,
      activeIndex: "1",
      activeIndex2: "1",
      timer: null,
@@ -235,6 +238,10 @@
      carCountData: [], //车辆统计数据
      carStatusData: {}, //车辆状态数据
      warnList: [], //预警列表数据
      serverIp: "",//监控ip
      serverPort: "",//监控端口
      carId: "",//监控车辆
    };
  },
  watch: {
@@ -253,9 +260,7 @@
      }
    },
  },
  filters: {
  },
  filters: {},
  created() {
    window.toCarDetail = (record) => {
@@ -292,6 +297,7 @@
    if (this.timer) {
      clearInterval(this.timer);
    }
    this.destroyPlayer();
    if (this.markers && this.markers.length > 0) {
      this.markers.forEach((marker) => {
        marker.setMap(null);
@@ -472,6 +478,11 @@
            autoMove: true,
            anchor: "top-center",
          });
          // 添加信息弹窗关闭事件监听
          this.infoWindow.on('close', () => {
            console.log('关闭信息弹窗1111111111111111111')
            this.destroyPlayer();
          });
          this.getMapCarData();
        })
        .catch((e) => {
@@ -567,7 +578,6 @@
                new Promise((resolve) => {
                  geocoder.getAddress(location, (status, result) => {
                    if (status === "complete" && result.regeocode) {
                      console.log("result", result,'status',status);
                      resolve(result.regeocode.formattedAddress);
                    } else {
                      resolve("未知地址");
@@ -581,13 +591,12 @@
              this.infoWindow.setContent(
                this.listRender({
                  ...item,
                  drivingTime:this.formatterTime(item.drivingTime || 0) ,
                  drivingTime: this.formatterTime(item.drivingTime || 0),
                  location: addressResult,
                  videoUrl: videoRes.url,
                })
              );
              this.initVideoPlayer(videoRes.url);
              this.initVideoPlayer();
            } catch (error) {
              this.infoWindow.setContent(
                '<div style="padding: 20px;text-align: center;color: red;">获取车辆信息失败</div>'
@@ -605,27 +614,13 @@
      try {
        const res = await getRealVideo({ id: carId });
        // 将RTSP流转换为FLV流
        const flvUrl = this.convertRtspToFlv(res.url);
        return {
          url: flvUrl
        };
        this.serverIp = res.serverIp;
        this.serverPort = res.serverPort;
        this.carId = carId;
      } catch (error) {
        console.error("获取视频地址失败", error);
        return {
          url: ""
        };
        return {};
      }
    },
    // RTSP转FLV
    convertRtspToFlv(rtspUrl) {
      // 这里需要根据实际的流媒体服务器地址进行修改
      // 假设流媒体服务器地址为 http://your-media-server:8080
      const mediaServer = "http://101.206.211.65:18042";
      // 从RTSP URL中提取流标识
      const streamId = rtspUrl.split("/").pop();
      // 返回FLV流地址
      return `${mediaServer}/live/${streamId}.flv`;
    },
    // 初始化视频播放器
@@ -646,22 +641,40 @@
      // 检查flv.js是否支持
      if (flvjs.isSupported()) {
        try {
          this.flvPlayer = flvjs.createPlayer({
            type: "flv",
            isLive: true,
            cors: true,
            hasAudio: true,
            hasVideo: true,
            url: videoUrl,
            enableWorker: true,
            enableStashBuffer: false,
            seekType: "range",
          });
          this.flvPlayer.attachMediaElement(video);
          this.flvPlayer.load();
          this.flvPlayer.play().catch(error => {
            console.error("视频播放失败:", error);
          playDetection(this.carId).then((res) => {
            this.flvPlayer = flvjs.createPlayer({
              type: "flv", //视频类型
              isLive: true, //是否为直播
              cors: true, //是否开启跨域
              hasAudio: false, //是否开启音频
              hasVideo: true, //是否开启视频
              url: `http://${this.serverIp}:${this.serverPort}/live?port=1935&app=flv&stream=${this.carId}`, // 后端拿到的视频路径
              enableWorker: true, //启用 Web Worker 进程来加速视频的解码和处理过程
              enableStashBuffer: false, // 启用数据缓存机制,提高视频的流畅度和稳定性。
              stashInitialSize: 1024, // 初始缓存大小。单位:字节。建议针对直播:调整为1024kb
              stashInitialTime: 0.2, // 缓存初始时间。单位:秒。建议针对直播:调整为200毫秒
              seekType: "range", // 建议将其设置为“range”模式,以便更快地加载视频数据,提高视频的实时性。
              lazyLoad: false, //关闭懒加载模式,从而提高视频的实时性。建议针对直播:调整为false
              lazyLoadMaxDuration: 0.2, // 懒加载的最大时长。单位:秒。建议针对直播:调整为200毫秒
              deferLoadAfterSourceOpen: false, // 不预先加载视频数据,在 MSE(Media Source Extensions)打开后立即加载数据,提高视频的实时性。建议针对直播:调整为false
            });
            let video = document.getElementById("monitoringCard");
            this.flvPlayer.attachMediaElement(video); // video容器
            this.flvPlayer.load();
            this.flvPlayer
              .play()
              .then((res) => {
                this.videoTimer = setInterval(() => {
                  playDetection(this.carId);
                }, 5000);
              })
              .catch((err) => {
                this.destroyPlayer();
              });
            // 错误监听
            this.flvPlayer.on("error", (err) => {
              this.destroyPlayer();
            });
          });
        } catch (error) {
          console.error("创建播放器失败:", error);
@@ -670,6 +683,20 @@
        console.error("当前浏览器不支持flv.js");
      }
    },
    destroyPlayer() {
            // 销毁播放器释放资源
            if (this.flvPlayer) {
                if (this.videoTimer) clearInterval(this.videoTimer)
                closeRealVideo(this.carId).then(res => {
                    this.flvPlayer.pause();
                    this.flvPlayer.unload();
                    this.flvPlayer.detachMediaElement();
                    this.flvPlayer.destroy();
                    this.flvPlayer = null;
                })
            }
        },
    // 处理视频错误
    handleVideoError(event) {
@@ -687,11 +714,8 @@
      return `<div style="background: #ffffff; padding: 24px 20px;z-index: 999">
        <div style="position: relative; width: 460px; height: 330px">
          <video
            crossorigin="anonymous"
            style="width: 460px; height: 330px; border-radius: 9px" 
            id="monitoringCard"
            autoplay
            playsinline
            preload="auto"
            @error="handleVideoError"
            width="620">
@@ -718,9 +742,9 @@
          }</div>
        </div>
        <div style="display: flex; justify-content: space-between">
          <div style="font-weight: 500; font-size: 14px; color: rgba(0, 0, 0, 0.65);line-height: 26px;width: 200px;overflow: hidden;text-overflow: ellipsis;white-space: nowrap;" title="${record.location}">位置:${
          <div style="font-weight: 500; font-size: 14px; color: rgba(0, 0, 0, 0.65);line-height: 26px;width: 200px;overflow: hidden;text-overflow: ellipsis;white-space: nowrap;" title="${
            record.location
          }</div>
          }">位置:${record.location}</div>
          <div style="font-weight: 500;font-size: 14px; color: rgba(0, 0, 0, 0.65);line-height: 26px;">经纬度:${
            record.longitude + "," + record.latitude
          }</div>
src/view/home/service.js
@@ -30,4 +30,14 @@
// 获取监控
export const getRealVideo = (data) => {
    return axios.get(`/system/car/getRealVideo/${data.id}`, data)
}
// 通知后端开始获取视频流
export const playDetection = (id) => {
    return axios.get(`/system/car/playDetection/${id}`)
}
// 通知后端开始关闭视频流
export const closeRealVideo = (id) => {
    return axios.get(`/system/car/closeRealVideo/${id}`)
}