vue/react使用h5player对接海康ws视频流实时播放,监控回放

前端对接海康ws实时视频流,回放基础使用

1.首先在海康开放平台下载这个官方demo

这里我用的是h5player开发

2.将插件引入项目

将下载的demo 文件放到项目的静态资源中,

找到官网下载好的demo点进去,将里边的文件复制到项目的public下,这里使用的是vue,如果是react也和项目位置是一样的

我这里是在public新建了一个lib文件夹放进去

3.然后在index.html进行插件的导入

4.封装海康组件方便使用

封装hkPlayer.js,注意szBasePath的路径,如果跟我一样可以直接cv

javascript 复制代码
const IS_MOVE_DEVICE = document.body.clientWidth < 992;
const MSE_IS_SUPPORT = !!window.MediaSource; // 是否支持mse

/**
 * 海康播放器
 * @param {*} domid 容器id
 */
export default class HkPlayer {
  constructor(domid) {
    this.createPlayer(domid);
  }
  createPlayer(domid) {
    console.log('IS_MOVE_DEVICE', domid);
    const player = new window.JSPlugin({
      szId: domid,
      szBasePath: '/lib',
      iMaxSplit: 1,
      iCurrentSplit: IS_MOVE_DEVICE ? 1 : 2,
      openDebug: true,
      muted: true,
      // iWidth: 425,
      // iHeight: 350,
      mseWorkerEnable: false, //是否开启多线程解码,分辨率大于1080P建议开启,否则可能卡顿
      mseSupport: MSE_IS_SUPPORT,
      tabActive: MSE_IS_SUPPORT ? 'mse' : 'decoder',
      oStyle: {
        borderSelect: IS_MOVE_DEVICE ? '#000' : '#FFCC00'
      }
    });

    // 事件回调绑定
    player.JS_SetWindowControlCallback({
      windowEventSelect: function (iWndIndex) {
        //插件选中窗口回调
        console.log('windowSelect callback: ', iWndIndex);
      },
      pluginErrorHandler: function (iWndIndex, iErrorCode, oError) {
        //插件错误回调
        console.log('pluginError callback: ', iWndIndex, iErrorCode, oError);
      },
      windowEventOver: function (iWndIndex) {
        //鼠标移过回调
        //console.log(iWndIndex);
      },
      windowEventOut: function (iWndIndex) {
        //鼠标移出回调
        //console.log(iWndIndex);
      },
      windowEventUp: function (iWndIndex) {
        //鼠标mouseup事件回调
        //console.log(iWndIndex);
      },
      windowFullCcreenChange: function (bFull) {
        //全屏切换回调
        console.log('fullScreen callback: ', bFull);
      },
      firstFrameDisplay: function (iWndIndex, iWidth, iHeight) {
        //首帧显示回调
        console.log('firstFrame loaded callback: ', iWndIndex, iWidth, iHeight);
      },
      performanceLack: function (iWndIndex) {
        //性能不足回调
        console.log('performanceLack callback: ', iWndIndex);
      },
      StreamEnd: function (iWndIndex) {
        //性能不足回调
        console.log('recv StreamEnd: ', iWndIndex);
      },
      StreamHeadChanged: function (iWndIndex) {
        console.log('recv StreamHeadChanged: ', iWndIndex);
      },
      ThumbnailsEvent: (iWndIndex, eventType, eventCode) => {
        console.log('recv ThumbnailsEvent: ' + iWndIndex + ', eventType:' + eventType + ', eventCode:' + eventCode);
      },
      InterruptStream: (iWndIndex, iTime) => {
        console.log('recv InterruptStream: ' + iWndIndex + ', iTime:' + iTime);
      },
      ElementChanged: (iWndIndex, szElementType) => {
        //回调采用的是video还是canvas
        console.log('recv ElementChanged: ' + iWndIndex + ', szElementType:' + szElementType);
      }
    });

    this.player = player;
  }
  // 实时播放
  startplay(url) {
    const playURL = url;
    const index = 1;
    this.player.JS_Play(playURL, { playURL, mode: 1 }, index).then(
      (res) => {
        console.log('播放成功', res);
      },
      (e) => {
        console.error('播放失败', e);
      }
    );
  }

  stopPlay() {
    this.player.JS_Stop().then(
      () => {
        console.log('stop realplay success');
      },
      (e) => {
        console.error(e);
      }
    );
  }

  // 回放
  startBackPlay(url, startTime, endTime) {
    const index = 1;
    this.player
      .JS_Play(
        url,
        {
          playURL: url, // 流媒体播放时必传
          mode: 0, // 解码类型:0=普通模式; 1=高级模式 默认为0
          PlayBackMode: 1, //1:绝对时间正放; 3 绝对时间倒放 默认为1
          keepDecoder: 0 // 0:回收解码资源; 1:不回收解码资源。为1时相同的编码格式,通过直接调用js_play接口切换点位不黑屏。默认0
          // ...
        },
        index, //当前窗口下标

        // 回放参数
        startTime,
        endTime
      )
      .then(
        () => {
          console.info('JS_Play success', startTime, endTime);
          // do you want...
        },
        (err) => {
          console.info('JS_Play failed:', err);
          // do you want...
        }
      );
  }
}

5.对接实时视频和回放

这里使用的流为ws,不同的流传参不一样,具体的可以登录海康官网查看

注意:回放的传参跟实时的有点区别,还有时间格式为iso的,需要toISOString转一下

javascript 复制代码
<template>
  <div class="centeredVideo" :id="'videoElement'+ playitem.cameraCode" style="width: 100%;height: 100%;"></div>
</template>

<script>

import { string } from 'vue-types';
import HkPlayer from '../utils/hkPlayer';
import { videoList, videoByCameraId, videoBack } from '@/api/tjh/video';
import moment from 'moment';

export default {
  name: 'PlayVideoCom',
  props: {
    playitem: {
      type: Object,
      required: true
    },
    videoType: {
      type: String,
      default: () => 'real' // real: 实时视频,back: 回放视频
    },
    startTimeStamp: {
      type: Date,
      default: () => ''
    },
    endTimeStamp: {
      type: Date,
      default: () => ''
    }
  },
  data() {
    return {
      VideoEltype: [0, 6],
      HkPlayerObj: null
    }
  },
  watch: {
    playitem: {
      immediate: true,
      handler(newVal) {
        if (newVal) {
          console.log(newVal,this, 'newVal');
          this.$nextTick(() => {
            this.HKplayVideo();
          })
        }
      }
    }
  },
  beforeUnmount() {
    this.HKclosePlaying();
  },
  methods: {
    // 海康
    async HKplayVideo() {
      try {
        this.HkPlayerObj = new HkPlayer('videoElement'+this.playitem.cameraCode);
        if(this.videoType === 'real'){
          const res = await videoByCameraId(this.playitem.cameraCode);
        if (res.msg) {
          this.HkPlayerObj.startplay(res.msg);
        }
        }else {
          let data = {
            cameraId: this.playitem.cameraCode,
            beginTime: moment(this.startTimeStamp).format('YYYY-MM-DD HH:mm:ss'),
            endTime: moment(this.endTimeStamp).format('YYYY-MM-DD HH:mm:ss'),
            "recordLocation": "1",
            "protocol": "ws"
          }
          const res = await videoBack(data);
        if (res.msg) {
          this.HkPlayerObj = new HkPlayer('videoElement' + this.playitem.cameraCode);
        }
        // let str = 'ws://169.16.10.7:559/openUrl/RRxMHQc?beginTime=20250817T000000&endTime=20250818T000000'
          this.HkPlayerObj.startBackPlay(res.msg, this.startTimeStamp.toISOString(), this.endTimeStamp.toISOString());
        }
      } catch (error) {
        console.error('Failed to play video:', error);
      }
    },
    HKclosePlaying() {
      if (this.HkPlayerObj) {
        console.log('关闭播放');
        this.HkPlayerObj.stopPlay(() => {});
      }
    }
  }
};
</script>