写文思路:
实现了视频播放,包括实时播放和视频回放。
首先展示效果图,介绍国标视频平台、国标视频平台的接口文档,介绍后端如何工作,前端如何工作,封装的核心代码以及完整代码。
效果展示:



实现思路:
左侧是树状图,包含摄像头列表,点击某一个摄像头,调取视频播放的接口,根据接口返回的数据,数据包括但不限于直播推流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)【开源平台】
华为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标签渲染
},
});
四、实际效果展示
效果展示:



