添加zlm集群支持
This commit is contained in:
@@ -7,22 +7,23 @@
|
||||
<el-main>
|
||||
<div style="background-color: #FFFFFF; margin-bottom: 1rem; position: relative; padding: 0.5rem; text-align: left;">
|
||||
<span style="font-size: 1rem; font-weight: bold;">云端录像</span>
|
||||
<div style="position: absolute; right: 5rem; top: 0.3rem;">
|
||||
节点选择: <el-select size="mini" @change="chooseMediaChange" style="width: 16rem; margin-right: 1rem;" v-model="mediaServer" placeholder="请选择" default-first-option>
|
||||
<el-option
|
||||
v-for="item in mediaServerList"
|
||||
:key="item.id"
|
||||
:label="item.id + '( ' + item.streamIp + ' )'"
|
||||
:value="item">
|
||||
</el-option>
|
||||
</el-select>
|
||||
</div>
|
||||
<div style="position: absolute; right: 1rem; top: 0.3rem;">
|
||||
<el-button v-if="!recordDetail" icon="el-icon-refresh-right" circle size="mini" :loading="loading" @click="getRecordList()"></el-button>
|
||||
<el-button v-if="recordDetail" icon="el-icon-arrow-left" circle size="mini" @click="backToList()"></el-button>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="!recordDetail">
|
||||
<div style="background-color: #FFFFFF; margin-bottom: 1rem; position: relative; padding: 0.5rem; text-align: left;font-size: 14px;">
|
||||
节点选择: <el-select size="mini" @change="chooseMediaChange" style="width: 16rem; margin-right: 1rem;" v-model="mediaServer" placeholder="请选择" default-first-option>
|
||||
<el-option
|
||||
v-for="item in mediaServerList"
|
||||
:key="item.generalMediaServerId"
|
||||
:label="item.generalMediaServerId + '( ' + item.wanIp + ' )'"
|
||||
:value="item">
|
||||
</el-option>
|
||||
</el-select>
|
||||
</div>
|
||||
|
||||
<!--设备列表-->
|
||||
<el-table :data="recordList" border style="width: 100%" :height="winHeight">
|
||||
<el-table-column prop="app" label="应用名" align="center">
|
||||
@@ -60,6 +61,7 @@
|
||||
<script>
|
||||
import uiHeader from './UiHeader.vue'
|
||||
import cloudRecordDetail from './CloudRecordDetail.vue'
|
||||
import MediaServer from './service/MediaServer'
|
||||
export default {
|
||||
name: 'app',
|
||||
components: {
|
||||
@@ -78,6 +80,7 @@
|
||||
count:15,
|
||||
total:0,
|
||||
loading: false,
|
||||
mediaServerObj : new MediaServer(),
|
||||
recordDetail: false
|
||||
|
||||
};
|
||||
@@ -107,20 +110,13 @@
|
||||
},
|
||||
getMediaServerList: function (){
|
||||
let that = this;
|
||||
this.$axios({
|
||||
method: 'get',
|
||||
url:`/api/server/media_server/list`,
|
||||
}).then(function (res) {
|
||||
console.log(res)
|
||||
that.mediaServerList = res.data;
|
||||
that.mediaServerObj.getMediaServerList((data)=>{
|
||||
that.mediaServerList = data;
|
||||
if (that.mediaServerList.length > 0) {
|
||||
that.mediaServer = that.mediaServerList[0]
|
||||
that.getRecordList();
|
||||
}
|
||||
|
||||
}).catch(function (error) {
|
||||
console.log(error);
|
||||
});
|
||||
})
|
||||
},
|
||||
getRecordList: function (){
|
||||
let that = this;
|
||||
|
||||
@@ -17,6 +17,8 @@
|
||||
</el-table-column>
|
||||
<el-table-column prop="gbId" label="国标编码" width="150" align="center">
|
||||
</el-table-column>
|
||||
<el-table-column prop="mediaServerId" label="流媒体" width="150" align="center">
|
||||
</el-table-column>
|
||||
<el-table-column label="开始时间" align="center" >
|
||||
<template slot-scope="scope">
|
||||
<el-button-group>
|
||||
@@ -29,7 +31,7 @@
|
||||
{{(scope.row.status == false && scope.row.gbId == null) || scope.row.status ?'是':'否'}}
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
|
||||
<el-table-column label="操作" width="360" align="center" fixed="right">
|
||||
<template slot-scope="scope">
|
||||
<el-button-group>
|
||||
@@ -125,7 +127,7 @@
|
||||
that.getDeviceListLoading = false;
|
||||
});
|
||||
},
|
||||
|
||||
|
||||
playPuhsh: function(row){
|
||||
let that = this;
|
||||
this.getListLoading = true;
|
||||
@@ -134,7 +136,8 @@
|
||||
url:`/api/media/stream_info_by_app_and_stream`,
|
||||
params: {
|
||||
app: row.app,
|
||||
stream: row.stream
|
||||
stream: row.stream,
|
||||
mediaServerId: row.mediaServerId
|
||||
}
|
||||
}).then(function (res) {
|
||||
that.getListLoading = false;
|
||||
|
||||
@@ -32,6 +32,15 @@
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="mediaServerId" label="流媒体" width="150" align="center"></el-table-column>
|
||||
<el-table-column label="类型" width="100" align="center">
|
||||
<template slot-scope="scope">
|
||||
<div slot="reference" class="name-wrapper">
|
||||
<el-tag size="medium">{{scope.row.type}}</el-tag>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column prop="gbId" label="国标编码" width="180" align="center" show-overflow-tooltip/>
|
||||
<el-table-column label="启用" width="120" align="center">
|
||||
<template slot-scope="scope">
|
||||
@@ -147,8 +156,6 @@
|
||||
count: that.count
|
||||
}
|
||||
}).then(function (res) {
|
||||
console.log(res);
|
||||
console.log(res.data.list);
|
||||
that.total = res.data.total;
|
||||
that.streamProxyList = res.data.list;
|
||||
that.getListLoading = false;
|
||||
@@ -170,7 +177,6 @@
|
||||
this.getListLoading = false;
|
||||
if (res.data.code == 0 ){
|
||||
if (res.data.data.length > 0) {
|
||||
console.log(res.data.data)
|
||||
this.$refs.onvifEdit.openDialog(res.data.data, (url)=>{
|
||||
if (url != null) {
|
||||
this.$refs.onvifEdit.close();
|
||||
@@ -200,7 +206,8 @@
|
||||
url:`/api/media/stream_info_by_app_and_stream`,
|
||||
params: {
|
||||
app: row.app,
|
||||
stream: row.stream
|
||||
stream: row.stream,
|
||||
mediaServerId: row.mediaServerId
|
||||
}
|
||||
}).then(function (res) {
|
||||
that.getListLoading = false;
|
||||
|
||||
@@ -7,6 +7,17 @@
|
||||
<el-main>
|
||||
<div style="background-color: #FFFFFF; margin-bottom: 1rem; position: relative; padding: 0.5rem; text-align: left;">
|
||||
<span style="font-size: 1rem; font-weight: bold;">控制台</span>
|
||||
<div style="position: absolute; right: 17rem; top: 0.3rem;">
|
||||
节点选择: <el-select size="mini" @change="chooseMediaChange" style="width: 16rem; margin-right: 1rem;" v-model="mediaServerChoose" placeholder="请选择" default-first-option>
|
||||
<el-option
|
||||
v-for="item in mediaServerList"
|
||||
:key="item.id"
|
||||
:label="item.id + '( ' + item.streamIp + ' )'"
|
||||
:value="item.id">
|
||||
</el-option>
|
||||
</el-select>
|
||||
<span >{{loadCount}}</span>
|
||||
</div>
|
||||
<div style="position: absolute; right: 1rem; top: 0.3rem;">
|
||||
<el-popover placement="bottom" width="750" height="300" trigger="click">
|
||||
<div style="height: 600px;overflow:auto;">
|
||||
@@ -53,6 +64,7 @@
|
||||
|
||||
<script>
|
||||
import uiHeader from './UiHeader.vue'
|
||||
import MediaServer from './service/MediaServer'
|
||||
|
||||
import echarts from 'echarts';
|
||||
export default {
|
||||
@@ -87,68 +99,101 @@ export default {
|
||||
chartInterval: 0, //更新图表统计图定时任务标识
|
||||
allSessionData: [],
|
||||
visible: false,
|
||||
serverConfig: {}
|
||||
serverConfig: {},
|
||||
mediaServer : new MediaServer(),
|
||||
mediaServerChoose : null,
|
||||
loadCount : 0,
|
||||
mediaServerList : []
|
||||
};
|
||||
},
|
||||
mounted() {
|
||||
this.getAllSession();
|
||||
|
||||
this.initTable();
|
||||
this.updateData();
|
||||
this.chartInterval = setInterval(this.updateData, 3000);
|
||||
this.mediaServer.getMediaServerList((data)=>{
|
||||
this.mediaServerList = data.data;
|
||||
if (this.mediaServerList && this.mediaServerList.length > 0) {
|
||||
this.mediaServerChoose = this.mediaServerList[0].id
|
||||
this.loadCount = this.mediaServerList[0].count;
|
||||
this.getThreadsLoad();
|
||||
this.getAllSession();
|
||||
}
|
||||
})
|
||||
},
|
||||
destroyed() {
|
||||
clearInterval(this.chartInterval); //释放定时任务
|
||||
},
|
||||
methods: {
|
||||
chooseMediaChange: function (val) {
|
||||
this.loadCount = 0
|
||||
this.initTable()
|
||||
this.updateData();
|
||||
},
|
||||
updateData: function () {
|
||||
this.getThreadsLoad();
|
||||
this.getLoadCount();
|
||||
this.getAllSession();
|
||||
},
|
||||
/**
|
||||
* 获取线程状态
|
||||
*/
|
||||
getThreadsLoad: function () {
|
||||
let that = this;
|
||||
this.$axios({
|
||||
if (that.mediaServerChoose != null) {
|
||||
this.$axios({
|
||||
method: 'get',
|
||||
url: '/zlm/index/api/getThreadsLoad'
|
||||
}).then(function (res) {
|
||||
url: '/zlm/' + that.mediaServerChoose +'/index/api/getThreadsLoad'
|
||||
}).then(function (res) {
|
||||
if (res.data.code == 0) {
|
||||
that.tableOption.xAxis.data.push(new Date().toLocaleTimeString('chinese', {
|
||||
hour12: false
|
||||
}));
|
||||
that.table1Option.xAxis.data.push(new Date().toLocaleTimeString('chinese', {
|
||||
hour12: false
|
||||
}));
|
||||
that.tableOption.xAxis.data.push(new Date().toLocaleTimeString('chinese', {
|
||||
hour12: false
|
||||
}));
|
||||
that.table1Option.xAxis.data.push(new Date().toLocaleTimeString('chinese', {
|
||||
hour12: false
|
||||
}));
|
||||
|
||||
for (var i = 0; i < res.data.data.length; i++) {
|
||||
if (that.tableOption.series[i] === undefined) {
|
||||
let data = {
|
||||
data: [],
|
||||
type: 'line'
|
||||
};
|
||||
let data1 = {
|
||||
data: [],
|
||||
type: 'line'
|
||||
};
|
||||
data.data.push(res.data.data[i].delay);
|
||||
data1.data.push(res.data.data[i].load);
|
||||
that.tableOption.series.push(data);
|
||||
that.table1Option.series.push(data1);
|
||||
} else {
|
||||
that.tableOption.series[i].data.push(res.data.data[i].delay);
|
||||
that.table1Option.series[i].data.push(res.data.data[i].load);
|
||||
}
|
||||
for (var i = 0; i < res.data.data.length; i++) {
|
||||
if (that.tableOption.series[i] === undefined) {
|
||||
let data = {
|
||||
data: [],
|
||||
type: 'line'
|
||||
};
|
||||
let data1 = {
|
||||
data: [],
|
||||
type: 'line'
|
||||
};
|
||||
data.data.push(res.data.data[i].delay);
|
||||
data1.data.push(res.data.data[i].load);
|
||||
that.tableOption.series.push(data);
|
||||
that.table1Option.series.push(data1);
|
||||
} else {
|
||||
that.tableOption.series[i].data.push(res.data.data[i].delay);
|
||||
that.table1Option.series[i].data.push(res.data.data[i].load);
|
||||
}
|
||||
that.tableOption.dataZoom[0].start = that.charZoomStart;
|
||||
that.tableOption.dataZoom[0].end = that.charZoomEnd;
|
||||
that.table1Option.dataZoom[0].start = that.charZoomStart;
|
||||
that.table1Option.dataZoom[0].end = that.charZoomEnd;
|
||||
//that.myChart = echarts.init(document.getElementById('ThreadsLoad'));
|
||||
that.myChart.setOption(that.tableOption, true);
|
||||
// that.myChart1 = echarts.init(document.getElementById('WorkThreadsLoad'));
|
||||
that.myChart1.setOption(that.table1Option, true);
|
||||
}
|
||||
that.tableOption.dataZoom[0].start = that.charZoomStart;
|
||||
that.tableOption.dataZoom[0].end = that.charZoomEnd;
|
||||
that.table1Option.dataZoom[0].start = that.charZoomStart;
|
||||
that.table1Option.dataZoom[0].end = that.charZoomEnd;
|
||||
//that.myChart = echarts.init(document.getElementById('ThreadsLoad'));
|
||||
that.myChart.setOption(that.tableOption, true);
|
||||
// that.myChart1 = echarts.init(document.getElementById('WorkThreadsLoad'));
|
||||
that.myChart1.setOption(that.table1Option, true);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
},
|
||||
getLoadCount: function (){
|
||||
let that = this;
|
||||
if (that.mediaServerChoose != null) {
|
||||
that.mediaServer.getMediaServer(that.mediaServerChoose, (data)=>{
|
||||
if (data.code == 0) {
|
||||
that.loadCount = data.data.count
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
initTable: function () {
|
||||
let that = this;
|
||||
@@ -242,10 +287,9 @@ export default {
|
||||
getAllSession: function () {
|
||||
let that = this;
|
||||
that.allSessionData = [];
|
||||
console.log("地址:" + '/zlm/index/api/getAllSession');
|
||||
this.$axios({
|
||||
method: 'get',
|
||||
url: '/zlm/index/api/getAllSession'
|
||||
url: '/zlm/' + that.mediaServerChoose +'/index/api/getAllSession'
|
||||
}).then(function (res) {
|
||||
res.data.data.forEach(item => {
|
||||
let data = {
|
||||
|
||||
@@ -39,6 +39,22 @@
|
||||
<el-form-item label="超时时间:毫秒" prop="timeout_ms" v-if="proxyParam.type=='ffmpeg'">
|
||||
<el-input v-model="proxyParam.timeout_ms" clearable></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="节点选择" prop="rtp_type">
|
||||
<el-select
|
||||
v-model="proxyParam.mediaServerId"
|
||||
@change="mediaServerIdChange"
|
||||
style="width: 100%"
|
||||
placeholder="请选择拉流节点"
|
||||
>
|
||||
<el-option label="自动选择" value="auto"></el-option>
|
||||
<el-option
|
||||
v-for="item in mediaServerList"
|
||||
:key="item.id"
|
||||
:label="item.id"
|
||||
:value="item.id">
|
||||
</el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="FFmpeg命令模板" prop="ffmpeg_cmd_key" v-if="proxyParam.type=='ffmpeg'">
|
||||
<!-- <el-input v-model="proxyParam.ffmpeg_cmd_key" clearable></el-input>-->
|
||||
<el-select
|
||||
@@ -68,6 +84,7 @@
|
||||
<el-option label="组播" value="2"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="国标平台">
|
||||
<el-select
|
||||
v-model="proxyParam.platformGbId"
|
||||
@@ -106,6 +123,8 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import MediaServer from './../service/MediaServer'
|
||||
|
||||
export default {
|
||||
name: "streamProxyEdit",
|
||||
props: {},
|
||||
@@ -134,27 +153,8 @@ export default {
|
||||
isLoging: false,
|
||||
dialogLoading: false,
|
||||
onSubmit_text: "立即创建",
|
||||
platformList: [{
|
||||
id: 1,
|
||||
enable: true,
|
||||
name: "141",
|
||||
serverGBId: "34020000002000000001",
|
||||
serverGBDomain: "3402000000",
|
||||
serverIP: "192.168.1.141",
|
||||
serverPort: 15060,
|
||||
deviceGBId: "34020000002000000001",
|
||||
deviceIp: "192.168.1.20",
|
||||
devicePort: "5060",
|
||||
username: "34020000002000000001",
|
||||
password: "12345678",
|
||||
expires: "300",
|
||||
keepTimeout: "60",
|
||||
transport: "UDP",
|
||||
characterSet: "GB2312",
|
||||
ptz: false,
|
||||
rtcp: false,
|
||||
status: true,
|
||||
}],
|
||||
platformList: [],
|
||||
mediaServer: new MediaServer(),
|
||||
proxyParam: {
|
||||
name: null,
|
||||
type: "default",
|
||||
@@ -170,7 +170,9 @@ export default {
|
||||
enable_hls: true,
|
||||
enable_mp4: false,
|
||||
platformGbId: null,
|
||||
mediaServerId: "auto",
|
||||
},
|
||||
mediaServerList:{},
|
||||
ffmpegCmdList:{},
|
||||
|
||||
rules: {
|
||||
@@ -193,7 +195,6 @@ export default {
|
||||
}
|
||||
|
||||
let that = this;
|
||||
|
||||
this.$axios({
|
||||
method: 'get',
|
||||
url:`/api/platform/query/10000/0`
|
||||
@@ -202,17 +203,28 @@ export default {
|
||||
}).catch(function (error) {
|
||||
console.log(error);
|
||||
});
|
||||
this.$axios({
|
||||
method: 'get',
|
||||
url:`/api/proxy/ffmpeg_cmd/list`
|
||||
}).then(function (res) {
|
||||
that.ffmpegCmdList = res.data.data;
|
||||
}).catch(function (error) {
|
||||
console.log(error);
|
||||
});
|
||||
this.mediaServer.getMediaServerList((data)=>{
|
||||
this.mediaServerList = data;
|
||||
})
|
||||
},
|
||||
mediaServerIdChange:function (){
|
||||
let that = this;
|
||||
if (that.proxyParam.mediaServerId !== "auto"){
|
||||
that.$axios({
|
||||
method: 'get',
|
||||
url:`/api/proxy/ffmpeg_cmd/list`,
|
||||
params: {
|
||||
mediaServerId: that.proxyParam.mediaServerId
|
||||
}
|
||||
}).then(function (res) {
|
||||
that.ffmpegCmdList = res.data.data;
|
||||
}).catch(function (error) {
|
||||
console.log(error);
|
||||
});
|
||||
}
|
||||
|
||||
},
|
||||
onSubmit: function () {
|
||||
console.log("onSubmit");
|
||||
this.dialogLoading = true;
|
||||
var that = this;
|
||||
that.$axios({
|
||||
@@ -239,7 +251,6 @@ export default {
|
||||
});
|
||||
},
|
||||
close: function () {
|
||||
console.log("关闭添加视频平台");
|
||||
this.showDialog = false;
|
||||
this.dialogLoading = false;
|
||||
this.$refs.streamProxy.resetFields();
|
||||
|
||||
@@ -181,6 +181,7 @@ export default {
|
||||
showVideoDialog: false,
|
||||
streamId: '',
|
||||
app : '',
|
||||
mediaServerId : '',
|
||||
convertKey: '',
|
||||
deviceId: '',
|
||||
channelId: '',
|
||||
@@ -218,7 +219,7 @@ export default {
|
||||
if (tab.name == "codec") {
|
||||
this.$axios({
|
||||
method: 'get',
|
||||
url: '/zlm/index/api/getMediaInfo?vhost=__defaultVhost__&schema=rtmp&app='+ this.app +'&stream='+ this.streamId
|
||||
url: '/zlm/' +this.mediaServerId+ '/index/api/getMediaInfo?vhost=__defaultVhost__&schema=rtmp&app='+ this.app +'&stream='+ this.streamId
|
||||
}).then(function (res) {
|
||||
that.tracksLoading = false;
|
||||
if (res.data.code == 0 && res.data.online) {
|
||||
@@ -235,12 +236,11 @@ export default {
|
||||
}
|
||||
},
|
||||
openDialog: function (tab, deviceId, channelId, param) {
|
||||
console.log("openDialog")
|
||||
console.log(param)
|
||||
this.tabActiveName = tab;
|
||||
this.channelId = channelId;
|
||||
this.deviceId = deviceId;
|
||||
this.streamId = "";
|
||||
this.mediaServerId = "";
|
||||
this.app = "";
|
||||
this.videoUrl = ""
|
||||
if (!!this.$refs.videoPlayer) {
|
||||
@@ -257,8 +257,8 @@ export default {
|
||||
break;
|
||||
case "streamPlay":
|
||||
this.tabActiveName = "media";
|
||||
this.showRrecord = false,
|
||||
this.showPtz = false,
|
||||
this.showRrecord = false;
|
||||
this.showPtz = false;
|
||||
this.play(param.streamInfo, param.hasAudio)
|
||||
break;
|
||||
case "control":
|
||||
@@ -269,19 +269,17 @@ export default {
|
||||
console.log(val)
|
||||
},
|
||||
play: function (streamInfo, hasAudio) {
|
||||
|
||||
this.hasAudio = hasAudio;
|
||||
this.isLoging = false;
|
||||
// this.videoUrl = streamInfo.rtc;
|
||||
this.videoUrl = this.getUrlByStreamInfo(streamInfo);
|
||||
this.streamId = streamInfo.streamId;
|
||||
this.app = streamInfo.app;
|
||||
this.mediaServerId = streamInfo.mediaServerId;
|
||||
this.playFromStreamInfo(false, streamInfo)
|
||||
},
|
||||
getUrlByStreamInfo(streamInfo){
|
||||
let baseZlmApi = process.env.NODE_ENV === 'development'?`${location.host}/debug/zlm`:`${location.host}/zlm`
|
||||
console.log(12121212)
|
||||
console.log(baseZlmApi)
|
||||
// return `${baseZlmApi}/${streamInfo.app}/${streamInfo.streamId}.flv`;
|
||||
// return `http://${baseZlmApi}/${streamInfo.app}/${streamInfo.streamId}.flv`;
|
||||
return streamInfo.ws_flv;
|
||||
@@ -430,6 +428,7 @@ export default {
|
||||
var streamInfo = res.data;
|
||||
that.app = streamInfo.app;
|
||||
that.streamId = streamInfo.streamId;
|
||||
that.mediaServerId = streamInfo.mediaServerId;
|
||||
that.videoUrl = that.getUrlByStreamInfo(streamInfo);
|
||||
that.recordPlay = true;
|
||||
});
|
||||
|
||||
32
web_src/src/components/service/MediaServer.js
Normal file
32
web_src/src/components/service/MediaServer.js
Normal file
@@ -0,0 +1,32 @@
|
||||
import axios from 'axios';
|
||||
|
||||
class MediaServer{
|
||||
|
||||
constructor() {
|
||||
this.$axios = axios;
|
||||
}
|
||||
|
||||
getMediaServerList(callback){
|
||||
this.$axios({
|
||||
method: 'get',
|
||||
url:`/api/server/media_server/list`,
|
||||
}).then(function (res) {
|
||||
if (typeof (callback) == "function") callback(res.data)
|
||||
}).catch(function (error) {
|
||||
console.log(error);
|
||||
});
|
||||
}
|
||||
|
||||
getMediaServer(id, callback){
|
||||
this.$axios({
|
||||
method: 'get',
|
||||
url:`/api/server/media_server/one/` + id,
|
||||
}).then(function (res) {
|
||||
if (typeof (callback) == "function") callback(res.data)
|
||||
}).catch(function (error) {
|
||||
console.log(error);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export default MediaServer;
|
||||
Reference in New Issue
Block a user