国标28181 国标视频平台

写文思路:

实现了视频播放,包括实时播放和视频回放。

首先展示效果图,介绍国标视频平台、国标视频平台的接口文档,介绍后端如何工作,前端如何工作,封装的核心代码以及完整代码。

效果展示:

实现思路:

左侧是树状图,包含摄像头列表,点击某一个摄像头,调取视频播放的接口,根据接口返回的数据,数据包括但不限于直播推流url等。根据这个url前端使用Jessibuca直播流播放器进行视频的播放。

一、国际28181

理论知识:

理论知识:

1.协议类型:GB28181,国标28181规范是什么?

国标28181平台【简写GB28181】的"视频监控设备接入系统",是一个系统,一个能够

远程、跨区域、跨级别的访问网络中的监控设备(包括IPC、NVR等)。GB28181规定了视频监控系统中各种设备、系统、角色之间的互通互联的关系和连接规范。


2.国标平台的组成部分?

一个完整的GB28181平台,通常由管理平台、信令服务器、流媒体服务器、监控设备(IPC、NVR)、管理终端等几部分组成。


3.三种主流的国标28181平台,如下:

1.NTV GBS

2.华为IVS平台

3.WVP(WEB VIDEO PLATFORM)【开源平台】

NTV官网链接

华为IVS官网链接

开源平台WVP官网链接


参考博客:点击跳转

备注:视频监控工程,会通过标准协议接口纳入各地的监控资源,以实现平安和谐社会的建设。总体上是由各个单位建设平台,通过公网或专网将各地监控资源接入,这种监控设备对接到平台的协议,我们一般指的就是国标GB/T28181。

二、国标视频平台

公司后端可以拉取gitHub上的源码,进行本地部署。

平台信息:

国标视频平台的首页概览:

国标设备:

备注:

这是一个什么平台?用来做什么?

答:这是国标视频平台,通过登录一个可视化界面可以操作或者查看一些设备的状态,通过接口文档,后端写接口。写的接口要符合规范,进而前端调取接口【接口解决跨域】,实现具体的界面上的功能,包括:视频监控【实时监控】、视频回放【历史回放】。

三、国标视频接口文档

前端人员对接国标视频平台上的数据,需要按照此平台的接口文档进行传参、对接数据。

前端怎么使用?

答:如果后端接口写得详细,其实前端不用看。前端调取接口,传参,操作平台,进而控制摄像头的向上、向下、向左、向右、播放、停止、放大、缩小等功能。

三、jessibuca视频插件

目录:

  • jessibuca简介
  • 下载依赖文档
  • 组件封装

(一)、jessibuca简介

官网链接:点击跳转

Jessibuca是一款开源的纯H5直播流播放器,通过Emscripten将音视频解码库编译成Js(ams.js/wasm)运行于浏览器之中。兼容几乎所有浏览器,可以运行在PC、手机、微信中,无需额外安装插件。

(二)、下载依赖:

去jessibuca官网下载,官网下载:点击跳转

从官网下载相关压缩包将文件引入项目中,放入Public文件夹下。

(三)、jessibuca插件使用:

vue2封装:
html 复制代码
<template>
	<div class="container" ref="container" style="width:100%;height:200px;"> </div>
</template>

<script>
export default {
  data() {
    return {
      jessibuca: '',
      videoUrl:'***********' // 后台推送过来的直播地址
    };
  },
  mounted() {
    this.play()
  },
  methods: {
    init() {
      const options = {};
      this.jessibuca = new window.Jessibuca(Object.assign({
    container: this.$refs.container, // 播放器容器,若为 string ,则底层调用的是 document.getElementById('id')
    videoBuffer: 0.2, // 设置最大缓冲时长,单位毫秒,播放器会自动消除延迟。
    forceNoOffscreen: true, // 是否不使用离屏模式(提升渲染能力)
    hasAudio: false, // 是否有音频
    rotate: 0, // 设置旋转角度,只支持,0(默认) ,180,270 三个值
    isResize: false, // 1.当为true的时候:视频画面做等比缩放后,高或宽对齐canvas区域,画面不被拉伸,但有黑边;2.当为false的时候:视频画面完全填充canvas区域,画面会被拉伸
    isFullSize: true, // 当为true的时候:视频画面做等比缩放后,完全填充canvas区域,画面不被拉伸,没有黑边,但画面显示不全
    debug: false, // 是否开启控制台调试打印
    timeout: 30, // 设置超时时长, 单位秒,在连接成功之前和播放中途,如果超过设定时长无数据返回,则回调timeout事件
    supportDblclickFullscreen: true, // 是否支持屏幕的双击事件,触发全屏,取消全屏事件。
    showBandwidth: false, // 是否显示网速
    operateBtns: {
      fullscreen: true,// 是否显示全屏按钮
      screenshot: true,// 是否显示截图按钮
      play: true,// 是否显示播放暂停按钮
      audio: true,// 是否显示声音按钮
      recorder: false
    },
    keepScreenOn: false, // 开启屏幕常亮,在手机浏览器上, canvas标签渲染视频并不会像video标签那样保持屏幕常亮。
    isNotMute: false, // 是否开启声音,默认是关闭声音播放的。
    loadingText: "加载中...", // 加载过程中文案。
    background: "", // 背景图片。
    decoder: '/public/jessibuca/decoder.js',
    // useMSE: false,
    isFlv: true,
        },
        options
      ));
    },
    play() {
      const url = this.videoUrl;
      this.init();
      this.jessibuca.play(url);
    },
    destroy() {
      if (this.jessibuca) {
        this.jessibuca.destroy();
      }
    }
  }
};
</script>

<style scoped lang="scss"></style>
vue3封装:
html 复制代码
<template>
  <div ref="playerRef" class="player"></div>
</template>

<script setup lang="ts">
import { computed, nextTick, onBeforeUnmount, onMounted, ref, watch } from "vue";

const playerRef = ref();
const jessibucaPlayer = ref(null);

const props = defineProps({
  wsFlv: String,
  config: {
    type: Object,
    default: {
      isFlv: true, // 是否使用flv格式
      showBandwidth: true, // 是否显示带宽使用情况
      operateBtns: {
        // 配置按钮对象
        screenshot: true, // 是否启用截图功能
        fullscreen: true, // 是否启用全屏功能
        play: true, // 是否启用播放功能
        audio: true, // 是否启用音频功能
        record: true, // 是否启用录制功能
      },
      loadingText: "加载中...", // 设置播放器加载时显示的文本
      isResize: false,
      controlAutoHide: true, //底部控制台是否自动隐藏
      decoder: "decoder.js",
      hotKey: true, //是否开启键盘快捷键,目前支持的键盘快捷键有:esc -> 退出全屏;arrowUp -> 声音增加;arrowDown -> 声音减少;
      keepScreenOn: true, //开启屏幕常亮,在手机浏览器上, canvas标签渲染视频并不会像video标签那样保持屏幕常亮。
      videoBuffer: 0,
    },
  },
});
const url = computed(() => {
  return props.wsFlv
})

watch(url, (newVal, oldVal) => {
  nextTick(() => {
    createJessibucaPlayer()
  })
}, { immediate: true })
// 创建播放器
const createJessibucaPlayer = () => {
  if (jessibucaPlayer.value) jessibucaPlayer.value.destroy();
  jessibucaPlayer.value = new Jessibuca({
    container: playerRef.value,
    ...props.config,
  });
  jessibucaPlayer.value.on('load', () => {
    jessibucaPlayer.value.play(props.wsFlv);
  })
};
// 组件销毁前销毁播放器并停止视频流
onBeforeUnmount(() => {
  if (jessibucaPlayer.value) {
    jessibucaPlayer.value.destroy();
    jessibucaPlayer.value = null;
  }
});

const updatePlayerDomSize = () => {
  const dom = playerRef.value;
  let width = dom.parentNode.clientWidth;
  let height = (9 / 16) * width;
  if (height > dom.clientHeight) {
    height = dom.clientHeight;
    width = (16 / 9) * height;
  }
  if (width > 0 && height > 0) {
    dom.style.width = width + "px";
    dom.style.height = height + "px";
  }
};
defineExpose({
  updatePlayerDomSize,
});
</script>

<style lang="scss" scoped></style>
调用封装的组件,组件使用传参:

//html部分

<JessibucaPlayer :config="stateVideo.jessibucaPlayerConfig" :wsFlv="stateVideo.flvUrl" style="width: 100%; height: 100%" />

//js部分

const stateVideo = reactive({

flvUrl: "",

jessibucaPlayerConfig: {

autoWasm: true, // 在使用MSE或者Webcodecs 播放H265的时候,是否自动降级到wasm模式。

background: "", //背景图片

controlAutoHide: false, //底部控制台是否自动隐藏

debug: false, //是否开启控制台调试打印

decoder: "/jessibuca/decoder.js",

hasAudio: false, // 是否有音频,如果设置false,则不对音频数据解码,提升性能。

hasVideo: true, // 是否开启控制台调试打印

heartTimeout: 5, //设置超时时长, 单位秒播放中途,如果超过设定时长无数据返回,则回调 timeout事件

heartTimeoutReplay: true, //是否开启心跳超时之后自动再播放

heartTimeoutReplayTimes: 3, //重试次数 heartTimeoutReplay 重试失败之后,不再重新播放视频地址。如果想无限次重试,可以设置为-1

hiddenAutoPause: false, //是否开启当页面的'visibilityState'变为'hidden'的时候,自动暂停播放。

hotKey: false, //是否开启键盘快捷键 esc -> 退出全屏;arrowUp -> 声音增加;arrowDown -> 声音减少;

isFlv: false, //当为true的时候:ws协议不检验是否以.flv为依据,进行协议解析。

isFullResize: false, //当为true的时候:视频画面做等比缩放后,完全填充canvas区域,画面不被拉伸,没有黑边,但画面显示不全

isNotMute: false, // 是否开启声音,默认是false关闭声音播放的。

isResize: false, //当为true的时候:视频画面做等比缩放后,高或宽对齐canvas区域,画面不被拉伸,但有黑边。 当为false的时候:视频画面完全填充canvas区域,画面会被拉伸。

keepScreenOn: false, //开启屏幕常亮,在手机浏览器上, canvas标签渲染视频并不会像video标签那样保持屏幕常亮。PC端不会生效,仅手机端生效

loadingText: "请稍等, 视频加载中......", // 视频加载转圈时的提示文字

loadingTimeout: 10, //当play()的时候,如果没有数据返回,则回调

loadingTimeoutReplay: true, ///是否开启loading超时之后自动再播放

loadingTimeoutReplayTimes: 3, //loadingTimeoutReplay 重试失败之后,不再重新播放视频地址。

operateBtns: {

// 配置操作按钮 其中

fullscreen: false, //全屏按钮

screenshot: false, //截图按钮

play: false, //播放暂停按钮

audio: false, //声音按钮

record: false, //录制按钮

},

recordType: "webm", //默认录制的视频格式

rotate: 0, //设置旋转角度

showBandwidth: false, // 显示网速

supportDblclickFullscreen: false, // 是否支持屏幕的双击事件,触发全屏,取消全屏事件。

timeout: 10, //设置超时时长, 单位秒在连接成功之前(loading)和播放中途(heart),如果超过设定时长无数据返回,则回调timeout事件

useMSE: location.hostname !== "localhost" && location.protocol !== "https:", //是否开启MediaSource硬解码

useWCS: location.hostname === "localhost" || location.protocol === "https", //是否开启Webcodecs硬解码

useWebFullScreen: false, //是否使用web全屏(旋转90度)(只会在移动端生效)。

videoBuffer: 0, // 设置最大缓冲时长,单位秒,播放器会自动消除延迟。

wasmDecodeErrorReplay: true, // 是否开启解码失败重新播放

wcsUseVideoRender: true, //webcodecs硬解码是否通过video标签渲染

},

});

四、实际效果展示

效果展示: