Commit b4194460 by 李乾广

Merge branch 'qxh-master' of http://git.keliuyun.com:55676/jiaxiuc123/miniProject into qxh-master

2 parents af56ea2f 3ecf4e47
......@@ -13,6 +13,7 @@
"element-ui": "^2.15.14",
"less": "^4.2.0",
"less-loader": "^11.1.3",
"lodash": "^4.17.21",
"moment": "^2.29.4",
"vant": "^2.12.54",
"vue": "^2.6.14",
......
const operateBtns = {
fullscreen: true,
screenshot: false,
play: true,
audio: true,
ptz: true, // 云台
zoom: true,// 电子放大
performance: true, // 视频流信息展示
record: true, // 录制
scale: true, // 显示模式:拉伸、缩放、正常
quality: false, // 视频清晰度
};
const extendOperateBtns = [];
export function getPlayerConfig () {
return {
decoder: '/jessibuca-pro/decoder-pro.js',
text: '', // TODO: 功能暂不清楚
keepScreenOn: true, // 屏幕常亮
isResize: false,
isNotMute: false,
debug: false, // 是否开启控制台调试打印
// 播放相关
videoBuffer: 0.1, // 缓存时长
videoBufferDelay: 0.2, // 缓存延迟(延迟超过会触发丢帧)
// TODO: 是否通过浏览器API判断是否支持后,再赋值true或false
// useMSE: false,
// useWCS: checkSupportWCSHevc(),
// useWCS: false,
// useSIMD: checkSupportSIMD(),
// wcsUseVideoRender: checkSupportWCSHevc(),
useWebFullScreen: false, // ios可能不支持系统级别全屏,可能要使用此配置
timeout: 10, // 在连接成功之前(loading)和播放中途(heart),如果超过设定时长无数据返回,则回调timeout事件
// 按钮和界面
loadingText: '加载中...',
controlAutoHide: true,
supportDblclickFullscreen: false,
showBandwidth: true, // 显示网速
// angle fontSize fontFamily
fullscreenWatermarkConfig: {
opacity: 0.3,
text: '',
},
operateBtns,
extendOperateBtns: [],
showPerformance: false, // 显示性能
qualityConfig: ['标清', '高清'],
// 云台控制
ptzClickType: 'mouseDownAndUp', // click mouseDownAndUp
ptzZoomShow: true,
ptzMoreArrowShow: true,
// ptzApertureShow: true, // 光圈
ptzFocusShow: true,
}
}
export function getRotateConfig() {
return {
name: 'rotate',
index: 1,
icon: 'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHJlY3QgeD0iMi40ODQzOCIgeT0iNi40ODQzOCIgd2lkdGg9IjEyLjAzMTIiIGhlaWdodD0iOC4wMzEyNSIgcng9IjAuODA3MjkyIiBzdHJva2U9IndoaXRlIiBzdHJva2Utd2lkdGg9IjAuOTY4NzUiLz4KPHBhdGggZD0iTTcuMzQ4NDMgMi42OTcwN0w0LjgzNTM0IDQuMTE3NTNMNC44NjE3MyAxLjIzMDlMNy4zNDg0MyAyLjY5NzA3WiIgZmlsbD0id2hpdGUiLz4KPHBhdGggZD0iTTQuOTk2MjYgMi4xOTMzOEMzLjc5MTU2IDIuMjQwMDEgMi42NDQyNyAyLjcyMDM1IDEuNzY1NyAzLjU0NTkzQzAuODg3MTI2IDQuMzcxNTEgMC4zMzY0MzQgNS40ODY3NCAwLjIxNTA0OCA2LjY4NjIxTDEuNDA4OTUgNi44MDcwM0MxLjUwMTIgNS44OTU0MyAxLjkxOTczIDUuMDQ3ODYgMi41ODc0NCA0LjQyMDQyQzMuMjU1MTYgMy43OTI5OCA0LjEyNzEgMy40Mjc5MiA1LjA0MjY3IDMuMzkyNDhMNC45OTYyNiAyLjE5MzM4WiIgZmlsbD0id2hpdGUiLz4KPC9zdmc+Cg==',
iconTitle: '旋转',
click: this.rotate,
}
}
export function getMirrorRotate() {
return {
name: 'mirrorRotate',
index: 2,
icon: 'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZD0iTTAuNTIwOTcgMTQuNjY2N0w1LjY2NjY3IDMuNTE3NjZWMTQuNjY2N0gwLjUyMDk3WiIgc3Ryb2tlPSJ3aGl0ZSIgc3Ryb2tlLXdpZHRoPSIwLjY2NjY2NyIvPgo8cGF0aCBkPSJNMTUuNDc5IDE0LjY2NjdMMTAuMzMzMyAzLjUxNzY2VjE0LjY2NjdIMTUuNDc5WiIgc3Ryb2tlPSJ3aGl0ZSIgc3Ryb2tlLXdpZHRoPSIwLjY2NjY2NyIvPgo8cGF0aCBkPSJNOCAxVjE1IiBzdHJva2U9IndoaXRlIiBzdHJva2Utd2lkdGg9IjAuNTMzMzMzIi8+Cjwvc3ZnPgo=',
iconTitle: '镜像',
click: this.mirrorRotate,
}
}
export function getPlaybackConfig() {
return {
controlType: 'simple',
showRateBtn: true,
rateConfig: [
{ label: '0.5x', value: 0.5 },
{ label: '1x', value: 1 },
{ label: '2x', value: 2 },
{ label: '4x', value: 4 },
],
}
}
<template>
<div ref="container" :class="containerClassName" ></div>
<div ref="container"
:data-player-type="this.playerType"
:class="containerClassName"
@wheel="handleWheel"
>
</div>
</template>
<script>
import { merge } from 'lodash';
// checkSupportMSEHevc checkSupportSIMD, checkSupportWCSHevc
import { getWatermarkCanvasImg } from './utils';
import { getPlayerConfig, getRotateConfig, getMirrorRotate, getPlaybackConfig } from './config';
export default {
name: 'VionPlayer',
......@@ -25,6 +32,11 @@ export default {
type: Boolean,
default: true,
},
isPlayback: {
type: Boolean,
default: false,
},
// 是否是小程序
isXCXPage: {
type: Boolean,
default: false,
......@@ -35,6 +47,9 @@ export default {
// eslint-disable-next-line
_jessibuca: null,
playOriginUrl: '',
rotateNum: 0,
mirrorIndex: 0,
playerType: 'live', // 播放器类型:live playback
player: {
height: 0,
......@@ -44,7 +59,11 @@ export default {
},
computed: {
containerClassName() {
return this.hideControls ? ['vion-player', 'hide-controls'] : 'vion-player';
// 样式不支持响应式,因为会覆盖掉播放器自身添加的样式
const list = ['vion-player'];
if (this.hideControls) list.push('hide-controls');
// if (this.playerType === 'playback') list.push('playback-status');
return list;
},
},
mounted() {
......@@ -56,38 +75,13 @@ export default {
},
methods:{
init(url, params = {}) {
let options = Object.assign({
const options = merge(getPlayerConfig(), {
container: this.$refs.container,
decoder: '/jessibuca-pro/decoder-pro.js',
text: '', // TODO: 功能暂不清楚
keepScreenOn: true, // 屏幕常亮
isResize: false,
isNotMute: false,
debug: false, // 是否开启控制台调试打印
// 播放相关
videoBuffer: 0.1, // 缓存时长
videoBufferDelay: 0.2, // 缓存延迟(延迟超过会触发丢帧)
// TODO: 是否通过浏览器API判断是否支持后,再赋值true或false
// useMSE: false,
// useWCS: checkSupportWCSHevc(),
// useWCS: false,
// useSIMD: checkSupportSIMD(),
// wcsUseVideoRender: checkSupportWCSHevc(),
useWebFullScreen: this.isXCXPage, // ios可能不支持系统级别全屏,可能要使用此配置
timeout: 10, // 在连接成功之前(loading)和播放中途(heart),如果超过设定时长无数据返回,则回调timeout事件
// 按钮和界面
loadingText: '加载中...',
controlAutoHide: true,
supportDblclickFullscreen: false,
showBandwidth: true, // 显示网速
useWebFullScreen: this.isXCXPage,
fullscreenWatermarkConfig: {
text: this.watermarkText || '',
},
operateBtns: {
fullscreen: true,
screenshot: false,
play: !this.isXCXPage,
audio: !this.isXCXPage,
ptz: this.showPtz, // 云台
......@@ -95,23 +89,13 @@ export default {
performance: !this.isXCXPage, // 视频流信息展示
record: !this.isXCXPage, // 录制
scale: !this.isXCXPage, // 显示模式:拉伸、缩放、正常
quality: false, // 视频清晰度
},
extendOperateBtns: [],
showPerformance: false, // 显示性能
qualityConfig: ['标清', '高清'],
// 云台控制
ptzClickType: 'click', // click mouseDownAndUp
ptzZoomShow: true,
ptzMoreArrowShow: true,
// ptzApertureShow: true, // 光圈
ptzFocusShow: true,
extendOperateBtns: [getRotateConfig.call(this), getMirrorRotate.call(this)],
});
console.log('init-options', options);
this._jessibuca = new window.JessibucaPro(options);
console.log('_jessibuca', this._jessibuca);
this.registerEvent(this._jessibuca);
......@@ -146,27 +130,73 @@ export default {
// console.log('ptz', arrow);
this.$emit('ptz-control', arrow);
});
// 改变倍速事件
playerIns.on('playbackPreRateChange', (rate) => {
// console.log('playbackPreRateChange', rate);
this.$emit('rate-change', rate, this.setForward);
});
// 点击时间轴跳转事件
playerIns.on('playbackSeek', (data) => {
console.log('playbackSeek', data);
// jessibuca.setPlaybackStartTime(data.ts);
});
// 电子放大
},
setForward(rate) {
this._jessibuca.forward(rate);
},
getWatermarkBase64() {
const data = getWatermarkCanvasImg(150, 48, '文安智能');
console.log('getWatermarkBase64', data);
},
delayPlay(url) {
delayPlay(url, isPlayback = false) {
setTimeout(() => {
this._jessibuca.play(url);
if (isPlayback) {
this._jessibuca.playback(url, getPlaybackConfig());
this.playerType = 'playback';
} else {
this._jessibuca.play(url);
this.playerType = 'live';
}
this.playOriginUrl = url;
}, 150);
},
// 获取是否是回放状态
getPlaybackStatus(status) {
// 传入参数 优先级 大于属性
return status || this.isPlayback;
},
// true 放大,false 缩小
zoom(direction = true) {
// temp1.player.zoom.expandPrecision()
const targetPlayer = this._jessibuca.player;
// zooming 表示处于电子放大状态
if (targetPlayer && targetPlayer.zooming && targetPlayer.zoom) {
if (direction) targetPlayer.zoom.expandPrecision();
else targetPlayer.zoom.narrowPrecision();
}
},
handleWheel(event) {
console.log('handleWheel', event);
// TODO: 增加防抖动
event.stopPropagation();
const direction = event.deltaY < 0;
this.zoom(direction);
},
// 暴露方法
play(url) {
play(url, isPlayback = false) {
if (url) {
const playbackStatus = this.getPlaybackStatus(isPlayback);
// 播放地址不同,则先停止再播放。地址相同,相当于暂停后,继续播放
if (this.playOriginUrl && this.playOriginUrl !== url) {
// 若是回放,则直接播放
if (!playbackStatus && this.playOriginUrl && this.playOriginUrl !== url) {
// 切换视频流地址,先销毁当前实例,再创建新实例,避免内存溢出
this.replay(url);
} else {
this.delayPlay(url);
this.delayPlay(url, playbackStatus);
}
} else {
console.error('The url is not valid');
......@@ -194,6 +224,23 @@ export default {
return Promise.resolve(true);
}
},
rotate(num) {
let targetRotate = 0;
if (Number.isInteger(num)) {
targetRotate = num;
} else {
this.rotateNum++;
targetRotate = (this.rotateNum % 4) * 90;
}
this._jessibuca.setRotate(targetRotate);
},
mirrorRotate() {
// , 'vertical'
const typeList = ['', 'level'];
this.mirrorIndex++;
const targetType = typeList[this.mirrorIndex % 2];
this._jessibuca.setMirrorRotate(targetType);
},
screenshot(filename = '', format = 'jpeg', quality = 0.2, type = 'base64') {
return new Promise((resolve, reject) => {
// 如果是播放状态
......@@ -238,6 +285,20 @@ export default {
height: 100%;
widows: 100%;
background-color: rgba(13, 14, 27, 0.7);
// 时间轴
::v-deep(.jessibuca-control-progress-simple) {
display: none;
}
// 电子放大
::v-deep(.jessibuca-zoom-controls) {
display: none !important;
}
// 云台控制
&[data-player-type="playback"] {
::v-deep(.jessibuca-ptz) {
display: none !important;
}
}
}
.hide-controls {
::v-deep(.jessibuca-controls) {
......
......@@ -7,6 +7,7 @@
:datetime-range="datetimeRange"
watermarkText="文安智能678"
@ptz-control="handlePtz"
@rate-change="handleRateChange"
/>
</div>
<div class="footer">
......@@ -19,8 +20,11 @@
<button @click="handlePause">暂停</button>
<button @click="handleStop">停止</button>
<button @click="handleDestroy">销毁</button>
<button @click="handleRotate">旋转</button>
<button @click="handleScreenshot">抓拍</button>
<button @click="handleScreenshot2">抓拍(原)</button>
<button @click="handleZoom(true)">放大</button>
<button @click="handleZoom(false)">缩小</button>
<div class="record">
<input type="text" v-model="recordUrl">
<button @click="handleRecord">录像</button>
......@@ -50,9 +54,10 @@ export default {
base64Url: '',
// 播放器相关
// playUrl: 'https://rtmp01open.ys7.com:9188/v3/openlive/F16423875_4_1.flv?expire=1695696850&id=626370860302729216&t=8c5be77f3d74149d2cdb93f913baf0c171bc33f8d6b6507510e8869b3392a4da&ev=100&supportH265=1',
playUrl: '',
recordUrl: '',
playUrl: 'https://rtmp01open.ys7.com:9188/v3/openlive/F16423875_4_1.flv?expire=1695801507&id=626809821921091584&t=012b62efc1b531ada1d08aae3d374c4cb9cf999a87f38b298b52a14bbcc51883&ev=100&supportH265=1',
// playUrl: 'http://flv.bdplay.nodemedia.cn/live/bbb_264.flv',
// playUrl: '',
recordUrl: 'https://rtmp01open.ys7.com:9188/v3/openpb/F16423875_1_1.flv?begin=20230925113136&end=20230925182952&expire=1695724192&id=626485541843505152&rec=local&t=1a3147ede9f0c48ed31df986f8e1a24b39ebcebf0325c134bdae5d8bbda078f5&ev=100&supportH265=1',
}
},
methods: {
......@@ -68,7 +73,7 @@ export default {
this.playerVisible = true;
},
handleRecord() {
this.$refs.vionPlayer.play(this.recordUrl);
this.$refs.vionPlayer.play(this.recordUrl, true);
},
handleScreenshot() {
this.$refs.vionPlayer.screenshot().then(data => {
......@@ -92,10 +97,22 @@ export default {
handleDestroy() {
this.$refs.vionPlayer.destroy();
},
handleRotate() {
console.log('handleRotate');
this.$refs.vionPlayer.rotate();
},
handleZoom(direction) {
this.$refs.vionPlayer.zoom(direction);
},
handlePtz(arrow) {
console.log('handlePtz', arrow);
},
handleRateChange(rate, done) {
console.log('handleRateChange', rate, done);
// 请求接口,获取流地址
done(rate);
},
},
}
</script>
......@@ -132,6 +149,7 @@ export default {
> button {
margin-left: 2px;
}
}
}
::v-deep(.el-dialog__body) {
......
......@@ -4565,11 +4565,16 @@ lodash.uniqby@^4.7.0:
resolved "https://registry.npmmirror.com/lodash.uniqby/-/lodash.uniqby-4.7.0.tgz#d99c07a669e9e6d24e1362dfe266c67616af1302"
integrity sha512-e/zcLx6CSbmaEgFHCA7BnoQKyCtKMxnuWrJygbwPs/AIn+IMKl66L8/s+wBUn5LRw2pZx3bUHibiV1b6aTWIww==
lodash@^4.17.14, lodash@^4.17.20, lodash@^4.17.21:
lodash@^4.17.14, lodash@^4.17.20:
version "4.17.21"
resolved "https://registry.npmmirror.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==
lodash@^4.17.21:
version "4.17.21"
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==
log-symbols@^4.1.0:
version "4.1.0"
resolved "https://registry.npmmirror.com/log-symbols/-/log-symbols-4.1.0.tgz#3fbdbb95b4683ac9fc785111e792e558d4abd503"
......
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!