2023年4月24日 更改为rtmp直播方式,

This commit is contained in:
bai 2023-04-24 17:23:07 +08:00
parent 5c7dd98370
commit 8de8b89348
14 changed files with 668 additions and 172 deletions

View File

@ -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',
},
});

View File

@ -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>

View File

@ -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",

View File

@ -48,6 +48,8 @@ async function bootstrap() {
// 注册全局组件
registerGlobComp(app);
app.use(vue3videoPlay);
//CAS单点登录
await useSso().ssoLogin();

View File

@ -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',
}
},
],
};

View File

@ -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{

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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);
}

View File

@ -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>

View File

@ -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>

View File

@ -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';