2023年4月24日 更改为rtmp直播方式,
This commit is contained in:
parent
5c7dd98370
commit
8de8b89348
|
@ -81,5 +81,6 @@ module.exports = defineConfig({
|
|||
'vue/no-deprecated-v-on-native-modifier': 'off',
|
||||
'vue/no-v-html': 'off',
|
||||
'prefer-const': 'off',
|
||||
'no-irregular-whitespace': 'off',
|
||||
},
|
||||
});
|
||||
|
|
|
@ -28,6 +28,8 @@
|
|||
theme = htmlRoot = null;
|
||||
}
|
||||
})();
|
||||
|
||||
window.HELP_IMPROVE_VIDEOJS = false;
|
||||
</script>
|
||||
<div id="app">
|
||||
<style>
|
||||
|
@ -172,5 +174,7 @@
|
|||
<script type="text/javascript" src="/resource/js/webrtc/webrtcstreamer.js"></script>
|
||||
<!-- <script type="module" src="/resource/js/webrtc/adapter.min.js"></script>
|
||||
<script type="module" src="/resource/js/webrtc/webrtcstreamer.js"></script> -->
|
||||
<!-- <link href="https://vjs.zencdn.net/7.4.1/video-js.css" rel="stylesheet">
|
||||
<script src='https://vjs.zencdn.net/7.4.1/video.js'></script> -->
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -59,6 +59,7 @@
|
|||
"echarts": "^5.3.2",
|
||||
"emoji-mart-vue-fast": "^11.1.1",
|
||||
"enquire.js": "^2.1.6",
|
||||
"flv.js": "^1.6.2",
|
||||
"intro.js": "^5.1.0",
|
||||
"lodash-es": "^4.17.21",
|
||||
"lodash.get": "^4.4.2",
|
||||
|
@ -77,6 +78,7 @@
|
|||
"sortablejs": "^1.15.0",
|
||||
"tinymce": "^5.10.3",
|
||||
"vditor": "^3.8.13",
|
||||
"video.js": "^8.0.4",
|
||||
"vue": "^3.2.33",
|
||||
"vue-cropper": "^0.5.6",
|
||||
"vue-cropperjs": "^5.0.0",
|
||||
|
|
|
@ -48,6 +48,8 @@ async function bootstrap() {
|
|||
// 注册全局组件
|
||||
registerGlobComp(app);
|
||||
|
||||
app.use(vue3videoPlay);
|
||||
|
||||
//CAS单点登录
|
||||
await useSso().ssoLogin();
|
||||
|
||||
|
|
|
@ -82,9 +82,25 @@ const site: AppRouteModule = {
|
|||
name: 'LiveBroadcastRoom',
|
||||
component: () => import('/@/views/site/common/webRTC/index.vue'),
|
||||
meta: {
|
||||
title: '直播',
|
||||
title: '直播rtsp',
|
||||
}
|
||||
},
|
||||
{
|
||||
path: 'liveFlvView',
|
||||
name: 'LiveFlvBroadcastRoom',
|
||||
component: () => import('/@/views/site/common/video/flvjs/index.vue'),
|
||||
meta: {
|
||||
title: '直播flv.js',
|
||||
}
|
||||
},
|
||||
{
|
||||
path: 'livem3u8View',
|
||||
name: 'Live3u8BroadcastRoom',
|
||||
component: () => import('/@/views/site/common/video/videojs/index.vue'),
|
||||
meta: {
|
||||
title: '直播video.js',
|
||||
}
|
||||
},
|
||||
|
||||
],
|
||||
};
|
||||
|
|
|
@ -13,82 +13,35 @@
|
|||
{{ item.jsmc }}-{{ item.xm }}
|
||||
</a-menu-item>
|
||||
</a-menu>
|
||||
<!-- document.querySelector('.ant-layout .jeecg-default-layout-main > div').style.height -->
|
||||
</a-col>
|
||||
<a-col :span="20">
|
||||
<!-- <a-row> -->
|
||||
<!-- <a-col :span="12" v-if="currentItem?.child?.录播主机">
|
||||
<div>{{ currentItem?.child?.录播主机?.xm }}</div>
|
||||
<bVideo :ref="el=> bVideoRefs['main']=el" :videoOption="{ autoPlay: true }" :videoKey="'main'"/>
|
||||
</a-col> -->
|
||||
<!-- <a-col :span="12">
|
||||
<a-row>
|
||||
<a-col v-for="(item,index) of calcOtherVideo()" :span="12">
|
||||
<div>{{ index }}</div>
|
||||
<bVideo :ref="el=> bVideoRefs[index]=el" :videoOption="{ autoPlay: true }" :videoKey="'other-'+item.id"/>
|
||||
</a-col>
|
||||
</a-row>
|
||||
</a-col> -->
|
||||
<!-- <a-col v-for="(item,index) of calcOtherVideo()" :span="4">
|
||||
</a-col> -->
|
||||
<!-- <a-col :span="4"> -->
|
||||
<!-- <bVideo ref="bVideoLeftRef" :videoOption="{ autoPlay: true }" :videoKey="'left-'+currentItem?.child?.学生定位?.id"/> -->
|
||||
<!-- </a-col> -->
|
||||
<!-- </a-row> -->
|
||||
<div>
|
||||
<a-card :title="mainVideoCardBoxTitle" class="videoCardMain">
|
||||
<video id="mainVideo" v-bind="videoOption" style="width:100%" @click.prevent.stop></video>
|
||||
<a-card :title="mainVideoCardBoxTitle" class="videoCardMain" style="width:100%">
|
||||
<bVideo ref="mainVideo" videoId="mainVideo"></bVideo>
|
||||
</a-card>
|
||||
</div>
|
||||
<div style="display: flex;flex-direction: row;flex-wrap: nowrap;overflow-x: scroll;">
|
||||
<div v-for="(item,index) of calcOtherVideo()" class="videoMax">
|
||||
<a-card :title="item?.xm" style="width: 300px" class="videoCardMain">
|
||||
<bVideo :ref="el=> bVideoRefs[index]=el" :videoOption="{ autoPlay: true, onClick: bVideoClick }" :videoKey="'other-'+item.id"/>
|
||||
<!-- <bVideo :ref="el=> bVideoRefs[index]=el" :src="'http://127.0.0.1/live_hls/soures.m3u8'" type="application/x-mpegURL" :videoId="'other-'+item.id"/> -->
|
||||
<!-- <bVideo :ref="el=> bVideoRefs[index]=el" :videoOption="{ autoPlay: true, userActions: { click: bVideoClick } }" :src="'http://127.0.0.1/live_hls/soures.m3u8'" type="application/x-mpegURL" :videoId="'other-'+item.id"/> -->
|
||||
<bVideo :ref="el=> bVideoRefs[index]=el" :videoOption="{ autoPlay: true, userActions: { click: bVideoClick } }" :src="item.pullUrl" type="application/x-mpegURL" :videoId="'other-'+item.id"/>
|
||||
<!-- <bVideo :ref="el=> bVideoRefs[index]=el" :src="'http://bylwcs.nenu.edu.cn:8089/live_hls/123.m3u8'" type="application/x-mpegURL" :videoId="'other-'+item.id"/> -->
|
||||
</a-card>
|
||||
</div>
|
||||
</div>
|
||||
</a-col>
|
||||
</a-row>
|
||||
</div>
|
||||
<!-- <a-layout>
|
||||
<a-layout-sider width="200" style="background: #fff">
|
||||
<a-menu
|
||||
v-model:openKeys="openKeys"
|
||||
v-model:selectedKeys="selectedKeys"
|
||||
:style="{ height: '100%', borderRight: 0 }"
|
||||
mode="inline"
|
||||
>
|
||||
<a-menu-item v-for="(item, index) of leftList" :key="index" @click="(e) => titleClick(e,item)" :title="`${item.xq}-${item.jsmc}-${item.xm}`">
|
||||
{{ item.xq }}-{{ item.jsmc }}-{{ item.xm }}
|
||||
</a-menu-item>
|
||||
</a-menu>
|
||||
|
||||
</a-layout-sider>
|
||||
<a-layout>
|
||||
<a-layout-content> -->
|
||||
<!-- {{ currentItem }} -->
|
||||
<!-- <bVideo ref="bVideoMainRef" :videoOption="{ autoPlay: true }" :videoKey="'main'+currentItem.id"/> -->
|
||||
<!-- <a-row>
|
||||
<a-col :span="12">
|
||||
<bVideo ref="bVideoMainRef" :videoOption="{ autoPlay: true }" :videoKey="'main'+currentItem.id"/>
|
||||
</a-col>
|
||||
<a-col :span="12">
|
||||
<bVideo ref="bVideoLeftRef" :videoOption="{ autoPlay: true }" :videoKey="'main2'+currentItem.id"/>
|
||||
</a-col>
|
||||
</a-row> -->
|
||||
<!-- </a-layout-content>
|
||||
</a-layout> -->
|
||||
<!-- </a-layout> -->
|
||||
</template>
|
||||
<script lang="ts" setup name="zhihuijiaoshiIndexPage">
|
||||
import type { MenuProps } from 'ant-design-vue';
|
||||
import { defHttp } from '/@/utils/http/axios';
|
||||
import { useMessage } from "/@/hooks/web/useMessage";
|
||||
import { ref, onMounted, onBeforeUnmount, reactive, computed, VideoHTMLAttributes } from 'vue';
|
||||
import bVideo from '/@/views/site/common/webRTC/video.vue';
|
||||
import { ref, onMounted } from 'vue';
|
||||
import bVideo from '/@/views/site/common/video/videojs/video.vue';
|
||||
import { nextTick } from 'vue';
|
||||
|
||||
const bVideoRefs = <any>ref([]);
|
||||
const mainVideo = <any>ref();
|
||||
const _document = window.document;
|
||||
// const bVideoLeftRef = ref();
|
||||
|
||||
|
@ -97,25 +50,6 @@ const currentItem = <any>ref({});
|
|||
const topWidth = <any>ref('0');
|
||||
const mainVideoCardBoxTitle = <any>ref('');
|
||||
|
||||
const videoOption = reactive({
|
||||
// width: '800', //播放器高度
|
||||
// height: '450', //播放器高度
|
||||
color: "#409eff", //主题色
|
||||
title: '', //视频名称
|
||||
//src: "https://go.dreamwq.com/videos/IronMan.mp4", //视频源
|
||||
muted: true, //静音
|
||||
playsinline: true,
|
||||
webFullScreen: false,
|
||||
// speedRate: ["0.75", "1.0", "1.25", "1.5", "2.0"], //播放倍速
|
||||
autoPlay: false, //自动播放
|
||||
loop: false, //循环播放
|
||||
mirror: false, //镜像画面
|
||||
ligthOff: false, //关灯模式
|
||||
volume: 0.3, //默认音量大小
|
||||
controls: true, //是否显示控制器
|
||||
});
|
||||
|
||||
|
||||
onMounted(() => {
|
||||
list({ pageSize: -1, sfyx: '0' }).then(res => {
|
||||
let list = (res?.records) ?? [];
|
||||
|
@ -136,16 +70,12 @@ onMounted(() => {
|
|||
});
|
||||
|
||||
leftList.value = Object.values(map);
|
||||
topWidth.value = _document?.querySelector('.ant-layout .jeecg-default-layout-main > div')?.style?.height?? '0';
|
||||
// console.log(_document?.querySelector('.ant-layout .jeecg-default-layout-main > div')?.style?.height?? '0')
|
||||
//计算左侧菜单高度
|
||||
let mainDiv = <any>_document?.querySelector('.ant-layout .jeecg-default-layout-main > div');
|
||||
topWidth.value =mainDiv?.style?.height?? '0';
|
||||
});
|
||||
});
|
||||
|
||||
// const topWidthCalc = computed(() => {
|
||||
// return _document?.querySelector('.ant-layout .jeecg-default-layout-main > div')?.style?.height?? '0';
|
||||
// });
|
||||
// xxx = document.querySelector('.ant-layout .jeecg-default-layout-main > div').style.height
|
||||
//
|
||||
enum Api {
|
||||
list = '/jiaoshi/kcZhihuijiaoshi/list',
|
||||
}
|
||||
|
@ -158,62 +88,30 @@ const list = (params) => defHttp.get({ url: Api.list, params });
|
|||
|
||||
const selectedKeys = ref<string[]>(['1']);
|
||||
const openKeys = ref<string[]>(['sub1']);
|
||||
|
||||
/**
|
||||
* 点击左侧菜单回调
|
||||
* @param e
|
||||
* @param item
|
||||
*/
|
||||
const titleClick = (e: Event, item: any) => {
|
||||
console.log('titleClick ->', e, item);
|
||||
currentItem.value = {};
|
||||
|
||||
nextTick(() => {
|
||||
currentItem.value = item;
|
||||
playerVideo(item);
|
||||
nextTick(() => {
|
||||
//播放第一个
|
||||
let one = <any>Object.values(calcOtherVideo())[0];
|
||||
bVideoClick({ target: { playerId: 'other-'+ one.id} })
|
||||
});
|
||||
// playerVideo(item);
|
||||
});
|
||||
};
|
||||
|
||||
function playerVideo(item){
|
||||
nextTick(() => {
|
||||
|
||||
//changshang == 奥威亚
|
||||
// bVideoMainRef.value.connectFn(item.ip);
|
||||
//bVideoMainRef.value.connectFn('rtsp://176.139.87.16/axis-media/media.amp','external');
|
||||
// bVideoLeftRef.value.connectFn('rtsp://176.139.87.16/axis-media/media.amp','external');
|
||||
|
||||
//rtsp://admin:admin@10.250.116.235:8554/live
|
||||
console.log('bVideoRefs ->',bVideoRefs,Object.values(bVideoRefs.value));
|
||||
|
||||
(Object.keys(bVideoRefs.value)).forEach((key) => {
|
||||
console.log(`🚀 ~ file: index.vue:180 ~ key:`, key)
|
||||
// x.connectFn('rtsp://admin:admin@10.250.116.235:8554/live','external')
|
||||
// if(Number(Number(Math.random()).toFixed(1))*10 >= 5){
|
||||
// x.connectFn('rtsp://127.0.0.1:8554/video','external');
|
||||
// }else{
|
||||
// x.connectFn(`rtsp://${x.ip}/live`,'external')
|
||||
// }
|
||||
// return;
|
||||
let videoRef = bVideoRefs.value[key];
|
||||
console.log(`🚀 ~ file: index.vue:187 ~ videoRef:`, videoRef)
|
||||
|
||||
let childItem = currentItem.value.child[key];
|
||||
console.log(`🚀 ~ file: index.vue:189 ~ childItem:`, childItem)
|
||||
if(!childItem){
|
||||
console.log('无法找到视频链接对象,currentItem.value.child[key] ->',currentItem,key);
|
||||
return;
|
||||
}
|
||||
if(childItem.changshang == '奥威亚'){
|
||||
videoRef.connectFn(`rtsp://${childItem.ip}/stream/0?config.login=web`,'external')
|
||||
}else if(childItem.changshang == '卓智'){
|
||||
videoRef.connectFn(`rtsp://${childItem.ip}/live`,'external')
|
||||
}else{
|
||||
videoRef.connectFn(`rtsp://${childItem.ip}/stream/0?config.login=web`,'external')
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
// (Object.values(bVideoRefs.value)).forEach((videoRef: any) => {
|
||||
|
||||
// console.log(`🚀 ~ file: index.vue:148 ~ playerVideo ~ videoRef:`, videoRef);
|
||||
// });
|
||||
setTimeout(() => {
|
||||
switchVideoToMain();
|
||||
},1000);
|
||||
})
|
||||
//bVideoRefs['main'].connectFn('rtsp://admin:admin@10.250.116.235:8554/live','external');
|
||||
}
|
||||
|
||||
/**
|
||||
* 拆分对象(过滤器)
|
||||
*/
|
||||
function calcOtherVideo() :any{
|
||||
if(!currentItem.value.child) return {};
|
||||
let map = {};
|
||||
|
@ -225,46 +123,21 @@ function calcOtherVideo() :any{
|
|||
return map;
|
||||
}
|
||||
|
||||
function switchVideoToMain(){
|
||||
console.log(`🚀 ~ file: index.vue:188 ~ switchVideoToMain ~ switchVideoToMain: 自动切换第一个子界面到主界面`);
|
||||
nextTick(() => {
|
||||
let firstBox = <HTMLVideoElement> document.querySelector('.videoMax');
|
||||
let titleBox = <HTMLVideoElement> firstBox?.querySelector('.ant-card-head-title');
|
||||
let title = titleBox?.textContent;
|
||||
|
||||
mainVideoCardBoxTitle.value = title;
|
||||
|
||||
let mainVideo = <HTMLVideoElement> document.querySelector('#mainVideo');
|
||||
let firstVideo = <HTMLVideoElement> firstBox.querySelector('video');
|
||||
mainVideo.srcObject = firstVideo.srcObject
|
||||
mainVideo.play();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 点击时切换至大屏
|
||||
* @param e
|
||||
*/
|
||||
function bVideoClick(e){
|
||||
console.log(`bVideoClick: 切换至主界面`);
|
||||
let mainVideo = <HTMLVideoElement> document.querySelector('#mainVideo');
|
||||
let currentVideo = <HTMLVideoElement> e.srcElement;
|
||||
console.log(`bVideoClick: 点击切换至主界面`);
|
||||
console.log('e =>',e);
|
||||
|
||||
let title = currentVideo?.parentElement?.parentElement?.querySelector('.ant-card-head-title')?.textContent
|
||||
mainVideoCardBoxTitle.value = title;
|
||||
console.log(`🚀 --------------------------------------------------------------------🚀`);
|
||||
console.log(`🚀 ~ file: index.vue:238 ~ bVideoClick ~ currentVideo:`, currentVideo);
|
||||
console.log(`🚀 --------------------------------------------------------------------🚀`);
|
||||
let mainVideo = <any> document.querySelector('#mainVideo');
|
||||
let currentVideo = <any> document.querySelector('#'+e.target.playerId);
|
||||
let src = currentVideo.player?.src();
|
||||
|
||||
mainVideo.srcObject = currentVideo.srcObject
|
||||
mainVideo.play();
|
||||
mainVideo?.player?.src([{type:'application/x-mpegURL',src }])
|
||||
}
|
||||
|
||||
|
||||
//页面销毁时销毁webRtc
|
||||
onBeforeUnmount(() => {
|
||||
bVideoRefs.value.forEach(x => {
|
||||
x.closeWebRtcStreamerFn();
|
||||
});
|
||||
})
|
||||
|
||||
|
||||
</script>
|
||||
<style lang="less" scoped>
|
||||
.videoMax{
|
||||
|
|
|
@ -0,0 +1,282 @@
|
|||
<template>
|
||||
<div style="width:100%;height: 100%;">
|
||||
<a-row>
|
||||
<a-col :span="4">
|
||||
<a-menu
|
||||
v-model:openKeys="openKeys"
|
||||
v-model:selectedKeys="selectedKeys"
|
||||
style="overflow: hidden;overflow-y:scroll"
|
||||
:style="{ height: `calc(100vh - ${topWidth})`, borderRight: 0 }"
|
||||
mode="inline"
|
||||
>
|
||||
<a-menu-item v-for="(item, index) of leftList" :key="index" @click="(e) => titleClick(e,item)" :title="`${item.jsmc}-${item.xm}`">
|
||||
{{ item.jsmc }}-{{ item.xm }}
|
||||
</a-menu-item>
|
||||
</a-menu>
|
||||
<!-- document.querySelector('.ant-layout .jeecg-default-layout-main > div').style.height -->
|
||||
</a-col>
|
||||
<a-col :span="20">
|
||||
<!-- <a-row> -->
|
||||
<!-- <a-col :span="12" v-if="currentItem?.child?.录播主机">
|
||||
<div>{{ currentItem?.child?.录播主机?.xm }}</div>
|
||||
<bVideo :ref="el=> bVideoRefs['main']=el" :videoOption="{ autoPlay: true }" :videoKey="'main'"/>
|
||||
</a-col> -->
|
||||
<!-- <a-col :span="12">
|
||||
<a-row>
|
||||
<a-col v-for="(item,index) of calcOtherVideo()" :span="12">
|
||||
<div>{{ index }}</div>
|
||||
<bVideo :ref="el=> bVideoRefs[index]=el" :videoOption="{ autoPlay: true }" :videoKey="'other-'+item.id"/>
|
||||
</a-col>
|
||||
</a-row>
|
||||
</a-col> -->
|
||||
<!-- <a-col v-for="(item,index) of calcOtherVideo()" :span="4">
|
||||
</a-col> -->
|
||||
<!-- <a-col :span="4"> -->
|
||||
<!-- <bVideo ref="bVideoLeftRef" :videoOption="{ autoPlay: true }" :videoKey="'left-'+currentItem?.child?.学生定位?.id"/> -->
|
||||
<!-- </a-col> -->
|
||||
<!-- </a-row> -->
|
||||
<div>
|
||||
<a-card :title="mainVideoCardBoxTitle" class="videoCardMain">
|
||||
<video id="mainVideo" v-bind="videoOption" style="width:100%" @click.prevent.stop></video>
|
||||
</a-card>
|
||||
</div>
|
||||
<div style="display: flex;flex-direction: row;flex-wrap: nowrap;overflow-x: scroll;">
|
||||
<div v-for="(item,index) of calcOtherVideo()" class="videoMax">
|
||||
<a-card :title="item?.xm" style="width: 300px" class="videoCardMain">
|
||||
<bVideo :ref="el=> bVideoRefs[index]=el" :videoOption="{ autoPlay: true, onClick: bVideoClick }" :videoKey="'other-'+item.id"/>
|
||||
</a-card>
|
||||
</div>
|
||||
</div>
|
||||
</a-col>
|
||||
</a-row>
|
||||
</div>
|
||||
<!-- <a-layout>
|
||||
<a-layout-sider width="200" style="background: #fff">
|
||||
<a-menu
|
||||
v-model:openKeys="openKeys"
|
||||
v-model:selectedKeys="selectedKeys"
|
||||
:style="{ height: '100%', borderRight: 0 }"
|
||||
mode="inline"
|
||||
>
|
||||
<a-menu-item v-for="(item, index) of leftList" :key="index" @click="(e) => titleClick(e,item)" :title="`${item.xq}-${item.jsmc}-${item.xm}`">
|
||||
{{ item.xq }}-{{ item.jsmc }}-{{ item.xm }}
|
||||
</a-menu-item>
|
||||
</a-menu>
|
||||
|
||||
</a-layout-sider>
|
||||
<a-layout>
|
||||
<a-layout-content> -->
|
||||
<!-- {{ currentItem }} -->
|
||||
<!-- <bVideo ref="bVideoMainRef" :videoOption="{ autoPlay: true }" :videoKey="'main'+currentItem.id"/> -->
|
||||
<!-- <a-row>
|
||||
<a-col :span="12">
|
||||
<bVideo ref="bVideoMainRef" :videoOption="{ autoPlay: true }" :videoKey="'main'+currentItem.id"/>
|
||||
</a-col>
|
||||
<a-col :span="12">
|
||||
<bVideo ref="bVideoLeftRef" :videoOption="{ autoPlay: true }" :videoKey="'main2'+currentItem.id"/>
|
||||
</a-col>
|
||||
</a-row> -->
|
||||
<!-- </a-layout-content>
|
||||
</a-layout> -->
|
||||
<!-- </a-layout> -->
|
||||
</template>
|
||||
<script lang="ts" setup name="zhihuijiaoshiIndexPage">
|
||||
import type { MenuProps } from 'ant-design-vue';
|
||||
import { defHttp } from '/@/utils/http/axios';
|
||||
import { useMessage } from "/@/hooks/web/useMessage";
|
||||
import { ref, onMounted, onBeforeUnmount, reactive, computed, VideoHTMLAttributes } from 'vue';
|
||||
import bVideo from '/@/views/site/common/webRTC/video.vue';
|
||||
import { nextTick } from 'vue';
|
||||
|
||||
const bVideoRefs = <any>ref([]);
|
||||
const _document = window.document;
|
||||
// const bVideoLeftRef = ref();
|
||||
|
||||
const leftList = <any>ref([]);
|
||||
const currentItem = <any>ref({});
|
||||
const topWidth = <any>ref('0');
|
||||
const mainVideoCardBoxTitle = <any>ref('');
|
||||
|
||||
const videoOption = reactive({
|
||||
// width: '800', //播放器高度
|
||||
// height: '450', //播放器高度
|
||||
color: "#409eff", //主题色
|
||||
title: '', //视频名称
|
||||
//src: "https://go.dreamwq.com/videos/IronMan.mp4", //视频源
|
||||
muted: true, //静音
|
||||
playsinline: true,
|
||||
webFullScreen: false,
|
||||
// speedRate: ["0.75", "1.0", "1.25", "1.5", "2.0"], //播放倍速
|
||||
autoPlay: false, //自动播放
|
||||
loop: false, //循环播放
|
||||
mirror: false, //镜像画面
|
||||
ligthOff: false, //关灯模式
|
||||
volume: 0.3, //默认音量大小
|
||||
controls: true, //是否显示控制器
|
||||
});
|
||||
|
||||
|
||||
onMounted(() => {
|
||||
list({ pageSize: -1, sfyx: '0' }).then(res => {
|
||||
let list = (res?.records) ?? [];
|
||||
//聚合
|
||||
let map = {};
|
||||
list.forEach(x => {
|
||||
let item = map[x.jsmc];
|
||||
if(item){
|
||||
item.child[x.xm] = x;
|
||||
}else{
|
||||
let child = {};
|
||||
child[x.xm] = x;
|
||||
map[x.jsmc] = {
|
||||
...x,
|
||||
child
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
leftList.value = Object.values(map);
|
||||
topWidth.value = _document?.querySelector('.ant-layout .jeecg-default-layout-main > div')?.style?.height?? '0';
|
||||
// console.log(_document?.querySelector('.ant-layout .jeecg-default-layout-main > div')?.style?.height?? '0')
|
||||
});
|
||||
});
|
||||
|
||||
// const topWidthCalc = computed(() => {
|
||||
// return _document?.querySelector('.ant-layout .jeecg-default-layout-main > div')?.style?.height?? '0';
|
||||
// });
|
||||
// xxx = document.querySelector('.ant-layout .jeecg-default-layout-main > div').style.height
|
||||
//
|
||||
enum Api {
|
||||
list = '/jiaoshi/kcZhihuijiaoshi/list',
|
||||
}
|
||||
/**
|
||||
* 列表接口
|
||||
* @param params
|
||||
*/
|
||||
const list = (params) => defHttp.get({ url: Api.list, params });
|
||||
|
||||
|
||||
const selectedKeys = ref<string[]>(['1']);
|
||||
const openKeys = ref<string[]>(['sub1']);
|
||||
const titleClick = (e: Event, item: any) => {
|
||||
console.log('titleClick ->', e, item);
|
||||
currentItem.value = item;
|
||||
playerVideo(item);
|
||||
};
|
||||
|
||||
function playerVideo(item){
|
||||
nextTick(() => {
|
||||
|
||||
//changshang == 奥威亚
|
||||
// bVideoMainRef.value.connectFn(item.ip);
|
||||
//bVideoMainRef.value.connectFn('rtsp://176.139.87.16/axis-media/media.amp','external');
|
||||
// bVideoLeftRef.value.connectFn('rtsp://176.139.87.16/axis-media/media.amp','external');
|
||||
|
||||
//rtsp://admin:admin@10.250.116.235:8554/live
|
||||
console.log('bVideoRefs ->',bVideoRefs,Object.values(bVideoRefs.value));
|
||||
|
||||
(Object.keys(bVideoRefs.value)).forEach((key) => {
|
||||
console.log(`🚀 ~ file: index.vue:180 ~ key:`, key)
|
||||
// x.connectFn('rtsp://admin:admin@10.250.116.235:8554/live','external')
|
||||
// if(Number(Number(Math.random()).toFixed(1))*10 >= 5){
|
||||
// x.connectFn('rtsp://127.0.0.1:8554/video','external');
|
||||
// }else{
|
||||
// x.connectFn(`rtsp://${x.ip}/live`,'external')
|
||||
// }
|
||||
// return;
|
||||
let videoRef = bVideoRefs.value[key];
|
||||
console.log(`🚀 ~ file: index.vue:187 ~ videoRef:`, videoRef)
|
||||
|
||||
let childItem = currentItem.value.child[key];
|
||||
console.log(`🚀 ~ file: index.vue:189 ~ childItem:`, childItem)
|
||||
if(!childItem){
|
||||
console.log('无法找到视频链接对象,currentItem.value.child[key] ->',currentItem,key);
|
||||
return;
|
||||
}
|
||||
if(childItem.changshang == '奥威亚'){
|
||||
videoRef.connectFn(`rtsp://${childItem.ip}/stream/0?config.login=web`,'external')
|
||||
}else if(childItem.changshang == '卓智'){
|
||||
videoRef.connectFn(`rtsp://${childItem.ip}/live`,'external')
|
||||
}else{
|
||||
videoRef.connectFn(`rtsp://${childItem.ip}/stream/0?config.login=web`,'external')
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
// (Object.values(bVideoRefs.value)).forEach((videoRef: any) => {
|
||||
|
||||
// console.log(`🚀 ~ file: index.vue:148 ~ playerVideo ~ videoRef:`, videoRef);
|
||||
// });
|
||||
setTimeout(() => {
|
||||
switchVideoToMain();
|
||||
},1000);
|
||||
})
|
||||
//bVideoRefs['main'].connectFn('rtsp://admin:admin@10.250.116.235:8554/live','external');
|
||||
}
|
||||
|
||||
function calcOtherVideo() :any{
|
||||
if(!currentItem.value.child) return {};
|
||||
let map = {};
|
||||
Object.keys(currentItem.value.child).forEach(key => {
|
||||
// if(key != '录播主机' && key.indexOf('音频处理器') ==-1){
|
||||
map[key] = currentItem.value.child[key];
|
||||
// }
|
||||
});
|
||||
return map;
|
||||
}
|
||||
|
||||
function switchVideoToMain(){
|
||||
console.log(`🚀 ~ file: index.vue:188 ~ switchVideoToMain ~ switchVideoToMain: 自动切换第一个子界面到主界面`);
|
||||
nextTick(() => {
|
||||
let firstBox = <HTMLVideoElement> document.querySelector('.videoMax');
|
||||
let titleBox = <HTMLVideoElement> firstBox?.querySelector('.ant-card-head-title');
|
||||
let title = titleBox?.textContent;
|
||||
|
||||
mainVideoCardBoxTitle.value = title;
|
||||
|
||||
let mainVideo = <HTMLVideoElement> document.querySelector('#mainVideo');
|
||||
let firstVideo = <HTMLVideoElement> firstBox.querySelector('video');
|
||||
mainVideo.srcObject = firstVideo.srcObject
|
||||
mainVideo.play();
|
||||
});
|
||||
}
|
||||
|
||||
function bVideoClick(e){
|
||||
console.log(`bVideoClick: 切换至主界面`);
|
||||
let mainVideo = <HTMLVideoElement> document.querySelector('#mainVideo');
|
||||
let currentVideo = <HTMLVideoElement> e.srcElement;
|
||||
|
||||
let title = currentVideo?.parentElement?.parentElement?.querySelector('.ant-card-head-title')?.textContent
|
||||
mainVideoCardBoxTitle.value = title;
|
||||
console.log(`🚀 --------------------------------------------------------------------🚀`);
|
||||
console.log(`🚀 ~ file: index.vue:238 ~ bVideoClick ~ currentVideo:`, currentVideo);
|
||||
console.log(`🚀 --------------------------------------------------------------------🚀`);
|
||||
|
||||
mainVideo.srcObject = currentVideo.srcObject
|
||||
mainVideo.play();
|
||||
}
|
||||
|
||||
|
||||
//页面销毁时销毁webRtc
|
||||
onBeforeUnmount(() => {
|
||||
bVideoRefs.value.forEach(x => {
|
||||
x.closeWebRtcStreamerFn();
|
||||
});
|
||||
})
|
||||
|
||||
|
||||
</script>
|
||||
<style lang="less" scoped>
|
||||
.videoMax{
|
||||
width: 300px;
|
||||
}
|
||||
.videoCardMain {
|
||||
:deep(.ant-card-body) {
|
||||
padding: 0;
|
||||
}
|
||||
}
|
||||
/* 隐藏video 进度条 */
|
||||
video::-webkit-media-controls-timeline {
|
||||
display: none;
|
||||
}
|
||||
</style>
|
|
@ -17,7 +17,9 @@
|
|||
</div>
|
||||
<span class="topTitle">
|
||||
{{ projectName }}
|
||||
<RouterLink hidden target='_blank' :to="{path:'/site/liveView',query:{ url: 'rtsp://176.139.87.16/axis-media/media.amp' }}">直播测试页</RouterLink>
|
||||
<RouterLink hidden target='_blank' :to="{path:'/site/liveView',query:{ url: 'rtsp://176.139.87.16/axis-media/media.amp' }}">直播测试页rtsp</RouterLink>
|
||||
<RouterLink hidden target='_blank' :to="{path:'/site/liveFlvView',query:{ url: 'rtsp://176.139.87.16/axis-media/media.amp' }}">直播测试页flv</RouterLink>
|
||||
<RouterLink hidden target='_blank' :to="{path:'/site/livem3u8View',query:{ url: 'rtsp://176.139.87.16/axis-media/media.amp' }}">直播测试页m3u8</RouterLink>
|
||||
</span>
|
||||
<span class="topRight">
|
||||
<a-dropdown>
|
||||
|
|
|
@ -0,0 +1,78 @@
|
|||
<template>
|
||||
<!-- <div @click="onPlay">点击开始播放(连接)直播</div>
|
||||
<div @click="onPlay2">点击开始播放(连接)直播2</div> -->
|
||||
<!-- <div>{{ route.query.url }}</div> -->
|
||||
<!-- <bVideo ref="bVideoRef"/> -->
|
||||
<!-- <video id="video" muted playsinline controls style=""></video> -->
|
||||
<!-- <video id="myVideo" class="video-js vjs-default-skin vjs-big-play-centered" controls autoplay data-setup='{}' style='width: 100%;height: auto'>
|
||||
<source id="source" src="http://127.0.0.1/01.m3u8" type="application/x-mpegURL"/>
|
||||
</video> -->
|
||||
<div>--不好用,屏蔽掉</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
// import { ref, onMounted, onBeforeUnmount} from 'vue';
|
||||
// import { useRoute } from 'vue-router'
|
||||
// import flvjs from 'flv.js'
|
||||
// // import bVideo from '/@/views/site/common/webRTC/video.vue';
|
||||
|
||||
|
||||
// // const bVideoRef = ref();
|
||||
|
||||
// const route = useRoute();
|
||||
|
||||
// // //页面销毁时销毁webRtc
|
||||
// // onBeforeUnmount(() => {
|
||||
// // bVideoRef.value.closeWebRtcStreamerFn();
|
||||
// // })
|
||||
|
||||
// onMounted(() => {
|
||||
// if(route.query.url){
|
||||
// if (flvjs.isSupported()) {
|
||||
// var videoDom = <HTMLVideoElement> document.getElementById('video')
|
||||
// // 创建一个播放器实例
|
||||
// let option = <flvjs.MediaDataSource>({
|
||||
// type: 'flv', // 媒体类型,默认是 flv
|
||||
// cors: true, //跨域
|
||||
// isLive: true, // 是否是直播流
|
||||
// hasAudio: true, // 是否有音频
|
||||
// hanVideo: true, // 是否有视频
|
||||
// // url: 'ws://127.0.0.1:1935/live/soures', // 流地址
|
||||
// // url: 'ws://127.0.0.1/live_hls/soures', // 流地址
|
||||
// url: 'http://127.0.0.1/live_hls/soures.m3u8', // 流地址
|
||||
// })
|
||||
// let config = <any>({
|
||||
// // 其他的配置项可以根据项目实际情况参考 api 去配置
|
||||
// autoCleanupMinBackwardDuration: true, // 清除缓存 对 SourceBuffer 进行自动清理
|
||||
// })
|
||||
// var player = flvjs.createPlayer(option, config);
|
||||
// player.attachMediaElement(videoDom)
|
||||
// player.load()
|
||||
// player.play()
|
||||
|
||||
// //this.player = player
|
||||
// }
|
||||
|
||||
// // bVideoRef.value.connectFn(route.query.url);
|
||||
// }
|
||||
// })
|
||||
|
||||
// onMounted(() => {
|
||||
// var myVideo = videojs('myVideo', {
|
||||
// bigPlayButton: true,
|
||||
// textTrackDisplay: false,
|
||||
// posterImage: false,
|
||||
// errorDisplay: false,
|
||||
// })
|
||||
// myVideo.play()
|
||||
// })
|
||||
|
||||
</script>
|
||||
<style lang="less" scoped>
|
||||
video {
|
||||
//margin: auto;
|
||||
//left: 0;
|
||||
//right: 0;
|
||||
//position: relative;
|
||||
background: grey;
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,83 @@
|
|||
<template>
|
||||
<!-- <div @click="onPlay2">点击开始播放(连接)直播2</div> -->
|
||||
<!-- <div>{{ route.query.url }}</div> -->
|
||||
<video
|
||||
id="my-player"
|
||||
class="video-js"
|
||||
controls
|
||||
preload="auto"
|
||||
poster="//vjs.zencdn.net/v/oceans.png"
|
||||
>
|
||||
<!-- <source src="//vjs.zencdn.net/v/oceans.mp4" type="video/mp4"/>
|
||||
<source src="//vjs.zencdn.net/v/oceans.webm" type="video/webm"/>
|
||||
<source src="//vjs.zencdn.net/v/oceans.ogv" type="video/ogg"/> -->
|
||||
<!-- <source src="http://127.0.0.1/live_hls/soures.m3u8" type="video/mp4"/> -->
|
||||
<!-- <source src="http://127.0.0.1/live_hls/soures.m3u8" type="rtmp/flv"/> -->
|
||||
<p class="vjs-no-js">
|
||||
要观看此视频,请启用JavaScript,并考虑升级web浏览器
|
||||
<a href="https://videojs.com/html5-video-support/" target="_blank">
|
||||
支持HTML5视频
|
||||
</a>
|
||||
</p>
|
||||
</video>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { ref, onMounted, onBeforeUnmount} from 'vue';
|
||||
import { useRoute } from 'vue-router'
|
||||
|
||||
import videojs from "video.js";
|
||||
import "video.js/dist/video-js.css";
|
||||
// import bVideo from '/@/views/site/common/webRTC/video.vue';
|
||||
|
||||
|
||||
// const bVideoRef = ref();
|
||||
|
||||
const route = useRoute();
|
||||
|
||||
// //页面销毁时销毁webRtc
|
||||
// onBeforeUnmount(() => {
|
||||
// bVideoRef.value.closeWebRtcStreamerFn();
|
||||
// })
|
||||
|
||||
// onMounted(() => {
|
||||
// if(route.query.url){
|
||||
// bVideoRef.value.connectFn(route.query.url);
|
||||
// }
|
||||
// })
|
||||
|
||||
onMounted(() => {
|
||||
if(route.query.url){
|
||||
var player = videojs('my-player',{
|
||||
autoplay: true,
|
||||
controls: true,
|
||||
muted: true,
|
||||
preload: 'auto',
|
||||
language: 'zh-CN',
|
||||
playbackRates: [1,2,3,4,5,8,10,20],
|
||||
trechIrder: ['flash'],
|
||||
sources: [{
|
||||
// type: 'rtmp/flv',
|
||||
// src: 'rtmp://127.0.0.1:1935/live/soures',
|
||||
type: route.query.type??'application/x-mpegURL',
|
||||
src: route.query.url??'http://127.0.0.1/live_hls/soures.m3u8',
|
||||
}],
|
||||
flash: {
|
||||
swf: 'https://cnd.bootcdn.net/ajax/libs/videojs-swf/5.4.2/video-js.swf',
|
||||
}
|
||||
},() => {
|
||||
console.log("加载完成!");
|
||||
|
||||
});
|
||||
}
|
||||
})
|
||||
|
||||
</script>
|
||||
<style lang="less" scoped>
|
||||
video {
|
||||
//margin: auto;
|
||||
//left: 0;
|
||||
//right: 0;
|
||||
//position: relative;
|
||||
background: grey;
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,32 @@
|
|||
// import { ref, nextTick, onBeforeUnmount} from 'vue';
|
||||
|
||||
// export const rtcServerUrl = import.meta.env.VITE_GLOB_RTC_SERVER;
|
||||
|
||||
export function getDefOptions(object) {
|
||||
// const windowObj = <any>window;
|
||||
// const WebRtcStreamer = windowObj.WebRtcStreamer;
|
||||
let o = {
|
||||
autoplay: true,
|
||||
controls: true,
|
||||
muted: true,
|
||||
errorDisplay: false,
|
||||
preload: 'auto',
|
||||
language: 'zh-CN',
|
||||
aspectRatio: "16:9",
|
||||
fluid: true,
|
||||
liveui: true,
|
||||
hotkeys: false,
|
||||
// playbackRates: [1,2,3,4,5,8,10,20],
|
||||
trechIrder: ['flash'],
|
||||
// sources: [{
|
||||
// // type: 'rtmp/flv',
|
||||
// // src: 'rtmp://127.0.0.1:1935/live/soures',
|
||||
// type: 'application/x-mpegURL',
|
||||
// src: 'http://127.0.0.1/live_hls/soures.m3u8',
|
||||
// }],
|
||||
flash: {
|
||||
swf: 'https://cnd.bootcdn.net/ajax/libs/videojs-swf/5.4.2/video-js.swf',
|
||||
}
|
||||
};
|
||||
return Object.assign(o,object);
|
||||
}
|
|
@ -0,0 +1,66 @@
|
|||
<template>
|
||||
<!-- <div @click="onPlay2">点击开始播放(连接)直播2</div> -->
|
||||
<!-- <div>{{ route.query.url }}</div> -->
|
||||
<video
|
||||
:id="props.videoId"
|
||||
playsinline="true"
|
||||
class="video-js"
|
||||
controls
|
||||
preload="auto"
|
||||
poster="//vjs.zencdn.net/v/oceans.png"
|
||||
>
|
||||
<p class="vjs-no-js">
|
||||
要观看此视频,请启用JavaScript,并考虑升级web浏览器
|
||||
<a href="https://videojs.com/html5-video-support/" target="_blank">
|
||||
支持HTML5视频
|
||||
</a>
|
||||
</p>
|
||||
</video>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { ref, onMounted, onBeforeUnmount} from 'vue';
|
||||
import { propTypes } from '/@/utils/propTypes';
|
||||
import { getDefOptions } from './util.ts';
|
||||
|
||||
import videojs from "video.js";
|
||||
import "video.js/dist/video-js.css";
|
||||
|
||||
const props = defineProps({
|
||||
videoId: propTypes.string.def('playerId'),
|
||||
src: propTypes.string.def(''),
|
||||
type: propTypes.string.def('application/x-mpegURL'),
|
||||
videoOption: propTypes.object.def({}),
|
||||
});
|
||||
|
||||
const player = ref();
|
||||
|
||||
onMounted(() => {
|
||||
let sources = [ { type: props.type, src: props.src, } ];
|
||||
let playerMain = <any> videojs(props.videoId, getDefOptions(Object.assign({ sources },props.videoOption)),() => {
|
||||
console.log("加载完成!",playerMain,props.videoOption);
|
||||
playerMain.on('pause', function(...d) {
|
||||
console.log('点击了??',...d);
|
||||
|
||||
// myAwesomePlayer.play();
|
||||
// ...so you can do here all the stuff you want while the video is playing
|
||||
|
||||
});
|
||||
});
|
||||
player.value = playerMain;
|
||||
|
||||
})
|
||||
|
||||
defineExpose({
|
||||
player
|
||||
});
|
||||
|
||||
</script>
|
||||
<style lang="less" scoped>
|
||||
// video {
|
||||
// //margin: auto;
|
||||
// //left: 0;
|
||||
// //right: 0;
|
||||
// //position: relative;
|
||||
// background: grey;
|
||||
// }
|
||||
</style>
|
|
@ -0,0 +1,52 @@
|
|||
<template>
|
||||
<!-- <div @click="onPlay">点击开始播放(连接)直播</div>
|
||||
<div @click="onPlay2">点击开始播放(连接)直播2</div> -->
|
||||
<!-- <div>{{ route.query.url }}</div> -->
|
||||
<!-- 使用webRTC-streamer播放rtsp流,但是没有声音。。。 -->
|
||||
<bVideo ref="bVideoRef"/>
|
||||
<!-- <video id="video" muted="" playsinline="" controls="" style="opacity: 1;"></video> -->
|
||||
<!-- <video id="myVideo" class="video-js vjs-default-skin vjs-big-play-centered" controls autoplay data-setup='{}' style='width: 100%;height: auto'>
|
||||
<source id="source" src="http://127.0.0.1/01.m3u8" type="application/x-mpegURL"/>
|
||||
</video> -->
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { ref, onMounted, onBeforeUnmount} from 'vue';
|
||||
import { useRoute } from 'vue-router'
|
||||
import bVideo from '/@/views/site/common/webRTC/video.vue';
|
||||
|
||||
|
||||
const bVideoRef = ref();
|
||||
|
||||
const route = useRoute();
|
||||
|
||||
//页面销毁时销毁webRtc
|
||||
onBeforeUnmount(() => {
|
||||
bVideoRef.value.closeWebRtcStreamerFn();
|
||||
})
|
||||
|
||||
onMounted(() => {
|
||||
if(route.query.url){
|
||||
bVideoRef.value.connectFn(route.query.url);
|
||||
}
|
||||
})
|
||||
|
||||
// onMounted(() => {
|
||||
// var myVideo = videojs('myVideo', {
|
||||
// bigPlayButton: true,
|
||||
// textTrackDisplay: false,
|
||||
// posterImage: false,
|
||||
// errorDisplay: false,
|
||||
// })
|
||||
// myVideo.play()
|
||||
// })
|
||||
|
||||
</script>
|
||||
<style lang="less" scoped>
|
||||
video {
|
||||
//margin: auto;
|
||||
//left: 0;
|
||||
//right: 0;
|
||||
//position: relative;
|
||||
background: grey;
|
||||
}
|
||||
</style>
|
|
@ -4,6 +4,9 @@
|
|||
<!-- <div>{{ route.query.url }}</div> -->
|
||||
<bVideo ref="bVideoRef"/>
|
||||
<!-- <video id="video" muted="" playsinline="" controls="" style="opacity: 1;"></video> -->
|
||||
<!-- <video id="myVideo" class="video-js vjs-default-skin vjs-big-play-centered" controls autoplay data-setup='{}' style='width: 100%;height: auto'>
|
||||
<source id="source" src="http://127.0.0.1/01.m3u8" type="application/x-mpegURL"/>
|
||||
</video> -->
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { ref, onMounted, onBeforeUnmount} from 'vue';
|
||||
|
|
Loading…
Reference in New Issue