mirror of
https://github.com/Monibuca/plugin-record.git
synced 2025-09-26 20:51:24 +08:00
更新UI
This commit is contained in:
21
LICENSE
Normal file
21
LICENSE
Normal file
@@ -0,0 +1,21 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2019-present, dexter
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
12
main.go
12
main.go
@@ -27,12 +27,10 @@ type FlvFileInfo struct {
|
||||
|
||||
func init() {
|
||||
InstallPlugin(&PluginConfig{
|
||||
Name: "Record",
|
||||
Type: PLUGIN_SUBSCRIBER,
|
||||
Config: &config,
|
||||
Version: "1.0.0",
|
||||
UI: CurrentDir("dashboard", "ui", "plugin-record.min.js"),
|
||||
Run: run,
|
||||
Name: "Record",
|
||||
Type: PLUGIN_SUBSCRIBER,
|
||||
Config: &config,
|
||||
Run: run,
|
||||
})
|
||||
}
|
||||
func run() {
|
||||
@@ -52,7 +50,7 @@ func run() {
|
||||
})
|
||||
http.HandleFunc("/record/flv", func(writer http.ResponseWriter, r *http.Request) {
|
||||
if streamPath := r.URL.Query().Get("streamPath"); streamPath != "" {
|
||||
if err := SaveFlv(streamPath, r.URL.Query().Get("append") != ""); err != nil {
|
||||
if err := SaveFlv(streamPath, r.URL.Query().Get("append") == "true"); err != nil {
|
||||
writer.Write([]byte(err.Error()))
|
||||
} else {
|
||||
writer.Write([]byte("success"))
|
||||
|
218
ui/dist/plugin-record.common.js
vendored
218
ui/dist/plugin-record.common.js
vendored
@@ -87,17 +87,6 @@ module.exports =
|
||||
/************************************************************************/
|
||||
/******/ ({
|
||||
|
||||
/***/ "034f":
|
||||
/***/ (function(module, __webpack_exports__, __webpack_require__) {
|
||||
|
||||
"use strict";
|
||||
/* harmony import */ var _node_modules_mini_css_extract_plugin_dist_loader_js_ref_6_oneOf_1_0_node_modules_css_loader_dist_cjs_js_ref_6_oneOf_1_1_node_modules_vue_loader_lib_loaders_stylePostLoader_js_node_modules_postcss_loader_src_index_js_ref_6_oneOf_1_2_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_App_vue_vue_type_style_index_0_lang_css___WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__("85ec");
|
||||
/* harmony import */ var _node_modules_mini_css_extract_plugin_dist_loader_js_ref_6_oneOf_1_0_node_modules_css_loader_dist_cjs_js_ref_6_oneOf_1_1_node_modules_vue_loader_lib_loaders_stylePostLoader_js_node_modules_postcss_loader_src_index_js_ref_6_oneOf_1_2_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_App_vue_vue_type_style_index_0_lang_css___WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_node_modules_mini_css_extract_plugin_dist_loader_js_ref_6_oneOf_1_0_node_modules_css_loader_dist_cjs_js_ref_6_oneOf_1_1_node_modules_vue_loader_lib_loaders_stylePostLoader_js_node_modules_postcss_loader_src_index_js_ref_6_oneOf_1_2_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_App_vue_vue_type_style_index_0_lang_css___WEBPACK_IMPORTED_MODULE_0__);
|
||||
/* unused harmony reexport * */
|
||||
/* unused harmony default export */ var _unused_webpack_default_export = (_node_modules_mini_css_extract_plugin_dist_loader_js_ref_6_oneOf_1_0_node_modules_css_loader_dist_cjs_js_ref_6_oneOf_1_1_node_modules_vue_loader_lib_loaders_stylePostLoader_js_node_modules_postcss_loader_src_index_js_ref_6_oneOf_1_2_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_App_vue_vue_type_style_index_0_lang_css___WEBPACK_IMPORTED_MODULE_0___default.a);
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ "0e05":
|
||||
/***/ (function(module, __webpack_exports__, __webpack_require__) {
|
||||
|
||||
@@ -109,14 +98,25 @@ module.exports =
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ "85ec":
|
||||
/***/ "39a8":
|
||||
/***/ (function(module, __webpack_exports__, __webpack_require__) {
|
||||
|
||||
"use strict";
|
||||
/* harmony import */ var _node_modules_mini_css_extract_plugin_dist_loader_js_ref_6_oneOf_1_0_node_modules_css_loader_dist_cjs_js_ref_6_oneOf_1_1_node_modules_vue_loader_lib_loaders_stylePostLoader_js_node_modules_postcss_loader_src_index_js_ref_6_oneOf_1_2_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_App_vue_vue_type_style_index_0_id_3ce37488_scoped_true_lang_css___WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__("b3f8");
|
||||
/* harmony import */ var _node_modules_mini_css_extract_plugin_dist_loader_js_ref_6_oneOf_1_0_node_modules_css_loader_dist_cjs_js_ref_6_oneOf_1_1_node_modules_vue_loader_lib_loaders_stylePostLoader_js_node_modules_postcss_loader_src_index_js_ref_6_oneOf_1_2_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_App_vue_vue_type_style_index_0_id_3ce37488_scoped_true_lang_css___WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_node_modules_mini_css_extract_plugin_dist_loader_js_ref_6_oneOf_1_0_node_modules_css_loader_dist_cjs_js_ref_6_oneOf_1_1_node_modules_vue_loader_lib_loaders_stylePostLoader_js_node_modules_postcss_loader_src_index_js_ref_6_oneOf_1_2_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_App_vue_vue_type_style_index_0_id_3ce37488_scoped_true_lang_css___WEBPACK_IMPORTED_MODULE_0__);
|
||||
/* unused harmony reexport * */
|
||||
/* unused harmony default export */ var _unused_webpack_default_export = (_node_modules_mini_css_extract_plugin_dist_loader_js_ref_6_oneOf_1_0_node_modules_css_loader_dist_cjs_js_ref_6_oneOf_1_1_node_modules_vue_loader_lib_loaders_stylePostLoader_js_node_modules_postcss_loader_src_index_js_ref_6_oneOf_1_2_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_App_vue_vue_type_style_index_0_id_3ce37488_scoped_true_lang_css___WEBPACK_IMPORTED_MODULE_0___default.a);
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ "a189":
|
||||
/***/ (function(module, exports, __webpack_require__) {
|
||||
|
||||
// extracted by mini-css-extract-plugin
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ "a189":
|
||||
/***/ "b3f8":
|
||||
/***/ (function(module, exports, __webpack_require__) {
|
||||
|
||||
// extracted by mini-css-extract-plugin
|
||||
@@ -190,12 +190,12 @@ if (typeof window !== 'undefined') {
|
||||
// Indicate to webpack that this file can be concatenated
|
||||
/* harmony default export */ var setPublicPath = (null);
|
||||
|
||||
// CONCATENATED MODULE: ./node_modules/cache-loader/dist/cjs.js?{"cacheDirectory":"node_modules/.cache/vue-loader","cacheIdentifier":"5b04a8fd-vue-loader-template"}!./node_modules/vue-loader/lib/loaders/templateLoader.js??vue-loader-options!./node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/vue-loader/lib??vue-loader-options!./src/App.vue?vue&type=template&id=655db994&
|
||||
var render = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('div',[_c('mu-tabs',{attrs:{"value":_vm.active1,"indicator-color":"#80deea","inverse":"","center":""},on:{"update:value":function($event){_vm.active1=$event}}},[_c('mu-tab',[_vm._v("直播流")]),_c('mu-tab',[_vm._v("录制的视频")])],1),(_vm.Rooms.length==0 && _vm.active1==0)?_c('div',{staticClass:"empty"},[_c('Icon',{attrs:{"type":"md-wine","size":"50"}}),_vm._v("没有任何房间 ")],1):(_vm.active1==0)?_vm._l((_vm.Rooms),function(item){return _c('mu-card',{key:item.StreamPath,staticClass:"room"},[_c('mu-card-title',{attrs:{"title":item.StreamPath,"sub-title":item.StartTime}}),_c('mu-card-text',[_c('p',[_vm._v(" "+_vm._s(_vm.SoundFormat(item.AudioInfo.SoundFormat))+" "+_vm._s(item.AudioInfo.PacketCount)+" "+_vm._s(_vm.SoundRate(item.AudioInfo.SoundRate))+" 声道:"+_vm._s(item.AudioInfo.SoundType)+" ")]),_c('p',[_vm._v(" "+_vm._s(_vm.CodecID(item.VideoInfo.CodecID))+" "+_vm._s(item.VideoInfo.PacketCount)+" "+_vm._s(item.VideoInfo.SPSInfo.Width)+"x"+_vm._s(item.VideoInfo.SPSInfo.Height)+" ")])]),_c('mu-card-actions',[(_vm.isRecording(item))?_c('mu-button',{staticClass:"recording",attrs:{"icon":""},on:{"click":function($event){return _vm.stopRecord(item)}}},[_c('mu-icon',{attrs:{"value":"fiber_manual_record"}})],1):_c('mu-button',{attrs:{"icon":""},on:{"click":function($event){return _vm.record(item)}}},[_c('mu-icon',{attrs:{"value":"fiber_manual_record"}})],1)],1)],1)}):_vm._e(),(_vm.active1==1)?_c('Records',{ref:"recordsPanel"}):_vm._e()],2)}
|
||||
// CONCATENATED MODULE: ./node_modules/cache-loader/dist/cjs.js?{"cacheDirectory":"node_modules/.cache/vue-loader","cacheIdentifier":"5b04a8fd-vue-loader-template"}!./node_modules/vue-loader/lib/loaders/templateLoader.js??vue-loader-options!./node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/vue-loader/lib??vue-loader-options!./src/App.vue?vue&type=template&id=3ce37488&scoped=true&
|
||||
var render = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('div',[_c('mu-tabs',{attrs:{"value":_vm.active1,"indicator-color":"#80deea","inverse":"","center":""},on:{"update:value":function($event){_vm.active1=$event}}},[_c('mu-tab',[_vm._v("直播流")]),_c('mu-tab',[_vm._v("录制的视频")])],1),(_vm.active1==0)?_c('mu-data-table',{attrs:{"columns":_vm.columns,"data":_vm.$store.state.Room,"min-col-width":50},on:{"row-click":function (i,r){ return _vm.isRecording(r)?_vm.stopRecord(r):_vm.record(r); }},scopedSlots:_vm._u([{key:"default",fn:function(scope){return [(_vm.isRecording(scope.row))?_c('td',{staticClass:"is-center"}):_c('td',{staticClass:"is-center"}),_c('td',{staticClass:"is-center"},[_vm._v(_vm._s(scope.row.StreamPath))]),_c('td',{staticClass:"is-center"},[_vm._v(_vm._s(scope.row.Type||"await"))]),_c('td',{staticClass:"is-center"},[_c('StartTime',{attrs:{"value":scope.row.StartTime}})],1),_c('td',{staticClass:"is-center"},[_vm._v(_vm._s(_vm.SoundFormat(scope.row.AudioInfo.SoundFormat)))]),_c('td',{staticClass:"is-center"},[_vm._v(_vm._s(_vm.SoundRate(scope.row.AudioInfo.SoundRate)))]),_c('td',{staticClass:"is-center"},[_vm._v(_vm._s(scope.row.AudioInfo.SoundType))]),_c('td',{staticClass:"is-center"},[_vm._v(_vm._s(_vm.CodecID(scope.row.VideoInfo.CodecID)))]),_c('td',{staticClass:"is-center"},[_vm._v(_vm._s(scope.row.VideoInfo.SPSInfo.Width)+"x"+_vm._s(scope.row.VideoInfo.SPSInfo.Height))]),_c('td',{staticClass:"is-center"},[_vm._v(_vm._s(scope.row.AudioInfo.PacketCount)+"/"+_vm._s(scope.row.VideoInfo.PacketCount))]),_c('td',{staticClass:"is-center"},[_vm._v(_vm._s(_vm.getSubscriberCount(scope.row)))])]}}],null,false,1124011921)}):_vm._e(),(_vm.active1==1)?_c('Records',{ref:"recordsPanel"}):_vm._e()],1)}
|
||||
var staticRenderFns = []
|
||||
|
||||
|
||||
// CONCATENATED MODULE: ./src/App.vue?vue&type=template&id=655db994&
|
||||
// CONCATENATED MODULE: ./src/App.vue?vue&type=template&id=3ce37488&scoped=true&
|
||||
|
||||
// CONCATENATED MODULE: ./node_modules/cache-loader/dist/cjs.js?{"cacheDirectory":"node_modules/.cache/vue-loader","cacheIdentifier":"5b04a8fd-vue-loader-template"}!./node_modules/vue-loader/lib/loaders/templateLoader.js??vue-loader-options!./node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/vue-loader/lib??vue-loader-options!./src/components/Records.vue?vue&type=template&id=7c800264&scoped=true&
|
||||
var Recordsvue_type_template_id_7c800264_scoped_true_render = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('div',{staticClass:"records"},_vm._l((_vm.data),function(item){return _c('mu-card',{key:item},[_c('mu-card-title',{attrs:{"title":item.Path,"sub-title":_vm.unitFormat(item.Size)+' '+_vm.toDurationStr(item.Duration)}}),_c('mu-card-actions',[_c('mu-button',{attrs:{"icon":"","small":""},on:{"click":function($event){return _vm.play(item)}}},[_c('mu-icon',{attrs:{"value":"play_arrow"}})],1),_c('mu-button',{attrs:{"icon":"","small":""},on:{"click":function($event){return _vm.deleteFlv(item)}}},[_c('mu-icon',{attrs:{"value":"delete_forever"}})],1)],1)],1)}),1)}
|
||||
@@ -440,41 +440,7 @@ var component = normalizeComponent(
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
|
||||
let roomsES = null;
|
||||
const SoundFormat = {
|
||||
0: "Linear PCM, platform endian",
|
||||
1: "ADPCM",
|
||||
2: "MP3",
|
||||
3: "Linear PCM, little endian",
|
||||
4: "Nellymoser 16kHz mono",
|
||||
5: "Nellymoser 8kHz mono",
|
||||
6: "Nellymoser",
|
||||
7: "G.711 A-law logarithmic PCM",
|
||||
8: "G.711 mu-law logarithmic PCM",
|
||||
9: "reserved",
|
||||
10: "AAC",
|
||||
11: "Speex",
|
||||
14: "MP3 8Khz",
|
||||
15: "Device-specific sound"
|
||||
};
|
||||
const CodecID = {
|
||||
1: "JPEG (currently unused)",
|
||||
2: "Sorenson H.263",
|
||||
3: "Screen video",
|
||||
4: "On2 VP6",
|
||||
5: "On2 VP6 with alpha channel",
|
||||
6: "Screen video version 2",
|
||||
7: "AVC",
|
||||
12: "H265"
|
||||
};
|
||||
|
||||
/* harmony default export */ var Appvue_type_script_lang_js_ = ({
|
||||
components: {
|
||||
@@ -482,55 +448,81 @@ const CodecID = {
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
Rooms: [],
|
||||
typeMap: {
|
||||
Receiver: "📡",
|
||||
FlvFile: "🎥",
|
||||
TS: "🎬",
|
||||
HLS: "🍎",
|
||||
"": "⏳",
|
||||
Match365: "🏆",
|
||||
RTMP: "🚠"
|
||||
}
|
||||
columns: [
|
||||
{
|
||||
title: "房间",
|
||||
name: "StreamPath",
|
||||
sortable: true
|
||||
},
|
||||
{
|
||||
title: "类型",
|
||||
name: "Type",
|
||||
sortable: true
|
||||
},
|
||||
{
|
||||
title: "开始时间",
|
||||
name: "StartTime",
|
||||
sortable: true
|
||||
},
|
||||
{
|
||||
title: "音频格式",
|
||||
name: "AudioInfo"
|
||||
},
|
||||
{
|
||||
title: "采样率",
|
||||
name: "AudioInfo"
|
||||
},
|
||||
{
|
||||
title: "声道",
|
||||
name: "AudioInfo"
|
||||
},
|
||||
{
|
||||
title: "视频格式",
|
||||
name: "VideoInfo"
|
||||
},
|
||||
{
|
||||
title: "分辨率",
|
||||
name: "VideoInfo"
|
||||
},
|
||||
{
|
||||
title: "数据包",
|
||||
name: ""
|
||||
},
|
||||
{
|
||||
title: "订阅者",
|
||||
name: "Subscribes"
|
||||
}
|
||||
]
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
SoundFormat(soundFormat) {
|
||||
return SoundFormat[soundFormat];
|
||||
},
|
||||
CodecID(codec) {
|
||||
return CodecID[codec];
|
||||
},
|
||||
SoundRate(rate) {
|
||||
return rate > 1000 ? rate / 1000 + "kHz" : rate + "Hz";
|
||||
},
|
||||
record(item) {
|
||||
this.$Modal.confirm({
|
||||
title: "提示",
|
||||
content:
|
||||
"<p>是否使用追加模式</p><small>选择取消将覆盖已有文件</small>",
|
||||
onOk: () => {
|
||||
window.ajax.get(
|
||||
"/record/flv?append=true",
|
||||
{ streamPath: item.StreamPath },
|
||||
x => {
|
||||
if (x == "success") {
|
||||
this.$Message.success("开始录制(追加模式)");
|
||||
} else {
|
||||
this.$Message.error(x);
|
||||
let append = false;
|
||||
this.$confirm(
|
||||
h =>
|
||||
h("mu-switch", {
|
||||
props: {
|
||||
label: "追加模式"
|
||||
},
|
||||
on: {
|
||||
change(value) {
|
||||
append = value;
|
||||
}
|
||||
}
|
||||
);
|
||||
},
|
||||
onCancel: () => {
|
||||
window.ajax.get(
|
||||
"/record/flv",
|
||||
}),
|
||||
"是否开始录制"
|
||||
).then(result => {
|
||||
if (result) {
|
||||
this.ajax.get(
|
||||
"/record/flv?append=" + append,
|
||||
{ streamPath: item.StreamPath },
|
||||
x => {
|
||||
if (x == "success") {
|
||||
this.$Message.success("开始录制");
|
||||
this.$toast.success(
|
||||
"开始录制" + (append ? "(追加模式)" : "")
|
||||
);
|
||||
} else {
|
||||
this.$Message.error(x);
|
||||
this.$toast.error(x);
|
||||
}
|
||||
}
|
||||
);
|
||||
@@ -538,51 +530,33 @@ const CodecID = {
|
||||
});
|
||||
},
|
||||
stopRecord(item) {
|
||||
window.ajax.get(
|
||||
"/record/flv/stop",
|
||||
{ streamPath: item.StreamPath },
|
||||
x => {
|
||||
if (x == "success") {
|
||||
this.$Message.success("停止录制");
|
||||
} else {
|
||||
this.$Message.error(x);
|
||||
this.$confirm("是否停止录制", "提示").then(result => {
|
||||
this.ajax.get(
|
||||
"/record/flv/stop",
|
||||
{ streamPath: item.StreamPath },
|
||||
x => {
|
||||
if (x == "success") {
|
||||
this.$toast.success("停止录制");
|
||||
} else {
|
||||
this.$toast.error(x);
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
);
|
||||
});
|
||||
},
|
||||
isRecording(item) {
|
||||
return (
|
||||
item.SubscriberInfo &&
|
||||
item.SubscriberInfo.find(x => x.Type == "FlvRecord")
|
||||
);
|
||||
},
|
||||
fetchRooms() {
|
||||
roomsES = new EventSource("/api/summary");
|
||||
roomsES.onmessage = evt => {
|
||||
if (!evt.data) return;
|
||||
let summary = JSON.parse(evt.data);
|
||||
this.Rooms = (summary && summary.Rooms) || [];
|
||||
this.Rooms.sort((a, b) =>
|
||||
a.StreamPath > b.StreamPath ? 1 : -1
|
||||
);
|
||||
};
|
||||
},
|
||||
onClickTab(name) {
|
||||
this.$refs.recordsPanel.onVisible(name == "recordsPanel");
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.fetchRooms();
|
||||
},
|
||||
destroyed() {
|
||||
roomsES.close();
|
||||
}
|
||||
});
|
||||
|
||||
// CONCATENATED MODULE: ./src/App.vue?vue&type=script&lang=js&
|
||||
/* harmony default export */ var src_Appvue_type_script_lang_js_ = (Appvue_type_script_lang_js_);
|
||||
// EXTERNAL MODULE: ./src/App.vue?vue&type=style&index=0&lang=css&
|
||||
var Appvue_type_style_index_0_lang_css_ = __webpack_require__("034f");
|
||||
// EXTERNAL MODULE: ./src/App.vue?vue&type=style&index=0&id=3ce37488&scoped=true&lang=css&
|
||||
var Appvue_type_style_index_0_id_3ce37488_scoped_true_lang_css_ = __webpack_require__("39a8");
|
||||
|
||||
// CONCATENATED MODULE: ./src/App.vue
|
||||
|
||||
@@ -599,7 +573,7 @@ var App_component = normalizeComponent(
|
||||
staticRenderFns,
|
||||
false,
|
||||
null,
|
||||
null,
|
||||
"3ce37488",
|
||||
null
|
||||
|
||||
)
|
||||
|
2
ui/dist/plugin-record.common.js.map
vendored
2
ui/dist/plugin-record.common.js.map
vendored
File diff suppressed because one or more lines are too long
2
ui/dist/plugin-record.css
vendored
2
ui/dist/plugin-record.css
vendored
@@ -1 +1 @@
|
||||
.records[data-v-7c800264]{display:flex;flex-wrap:wrap;padding:0 15px}.records>[data-v-7c800264]{width:200px}@-webkit-keyframes recording{0%{opacity:.2}50%{opacity:1}to{opacity:.2}}@keyframes recording{0%{opacity:.2}50%{opacity:1}to{opacity:.2}}.recording{-webkit-animation:recording 1s infinite;animation:recording 1s infinite}.layout{padding-bottom:30px;display:flex;flex-wrap:wrap}.room{width:250px;margin:10px;text-align:left}.empty{color:#ffc107;width:100%;min-height:500px;display:flex;justify-content:center;align-items:center}.status{position:fixed;display:flex;left:5px;bottom:10px}.status>div{margin:0 5px}
|
||||
.records[data-v-7c800264]{display:flex;flex-wrap:wrap;padding:0 15px}.records>[data-v-7c800264]{width:200px}@-webkit-keyframes recording-data-v-3ce37488{0%{opacity:.2}50%{opacity:1}to{opacity:.2}}@keyframes recording-data-v-3ce37488{0%{opacity:.2}50%{opacity:1}to{opacity:.2}}.recording[data-v-3ce37488]{-webkit-animation:recording-data-v-3ce37488 1s infinite;animation:recording-data-v-3ce37488 1s infinite}.layout[data-v-3ce37488]{padding-bottom:30px;display:flex;flex-wrap:wrap}.room[data-v-3ce37488]{width:250px;margin:10px;text-align:left}.empty[data-v-3ce37488]{color:#ffc107;width:100%;min-height:500px;display:flex;justify-content:center;align-items:center}.status[data-v-3ce37488]{position:fixed;display:flex;left:5px;bottom:10px}.status>div[data-v-3ce37488]{margin:0 5px}
|
218
ui/dist/plugin-record.umd.js
vendored
218
ui/dist/plugin-record.umd.js
vendored
@@ -96,17 +96,6 @@ return /******/ (function(modules) { // webpackBootstrap
|
||||
/************************************************************************/
|
||||
/******/ ({
|
||||
|
||||
/***/ "034f":
|
||||
/***/ (function(module, __webpack_exports__, __webpack_require__) {
|
||||
|
||||
"use strict";
|
||||
/* harmony import */ var _node_modules_mini_css_extract_plugin_dist_loader_js_ref_6_oneOf_1_0_node_modules_css_loader_dist_cjs_js_ref_6_oneOf_1_1_node_modules_vue_loader_lib_loaders_stylePostLoader_js_node_modules_postcss_loader_src_index_js_ref_6_oneOf_1_2_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_App_vue_vue_type_style_index_0_lang_css___WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__("85ec");
|
||||
/* harmony import */ var _node_modules_mini_css_extract_plugin_dist_loader_js_ref_6_oneOf_1_0_node_modules_css_loader_dist_cjs_js_ref_6_oneOf_1_1_node_modules_vue_loader_lib_loaders_stylePostLoader_js_node_modules_postcss_loader_src_index_js_ref_6_oneOf_1_2_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_App_vue_vue_type_style_index_0_lang_css___WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_node_modules_mini_css_extract_plugin_dist_loader_js_ref_6_oneOf_1_0_node_modules_css_loader_dist_cjs_js_ref_6_oneOf_1_1_node_modules_vue_loader_lib_loaders_stylePostLoader_js_node_modules_postcss_loader_src_index_js_ref_6_oneOf_1_2_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_App_vue_vue_type_style_index_0_lang_css___WEBPACK_IMPORTED_MODULE_0__);
|
||||
/* unused harmony reexport * */
|
||||
/* unused harmony default export */ var _unused_webpack_default_export = (_node_modules_mini_css_extract_plugin_dist_loader_js_ref_6_oneOf_1_0_node_modules_css_loader_dist_cjs_js_ref_6_oneOf_1_1_node_modules_vue_loader_lib_loaders_stylePostLoader_js_node_modules_postcss_loader_src_index_js_ref_6_oneOf_1_2_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_App_vue_vue_type_style_index_0_lang_css___WEBPACK_IMPORTED_MODULE_0___default.a);
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ "0e05":
|
||||
/***/ (function(module, __webpack_exports__, __webpack_require__) {
|
||||
|
||||
@@ -118,14 +107,25 @@ return /******/ (function(modules) { // webpackBootstrap
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ "85ec":
|
||||
/***/ "39a8":
|
||||
/***/ (function(module, __webpack_exports__, __webpack_require__) {
|
||||
|
||||
"use strict";
|
||||
/* harmony import */ var _node_modules_mini_css_extract_plugin_dist_loader_js_ref_6_oneOf_1_0_node_modules_css_loader_dist_cjs_js_ref_6_oneOf_1_1_node_modules_vue_loader_lib_loaders_stylePostLoader_js_node_modules_postcss_loader_src_index_js_ref_6_oneOf_1_2_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_App_vue_vue_type_style_index_0_id_3ce37488_scoped_true_lang_css___WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__("b3f8");
|
||||
/* harmony import */ var _node_modules_mini_css_extract_plugin_dist_loader_js_ref_6_oneOf_1_0_node_modules_css_loader_dist_cjs_js_ref_6_oneOf_1_1_node_modules_vue_loader_lib_loaders_stylePostLoader_js_node_modules_postcss_loader_src_index_js_ref_6_oneOf_1_2_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_App_vue_vue_type_style_index_0_id_3ce37488_scoped_true_lang_css___WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_node_modules_mini_css_extract_plugin_dist_loader_js_ref_6_oneOf_1_0_node_modules_css_loader_dist_cjs_js_ref_6_oneOf_1_1_node_modules_vue_loader_lib_loaders_stylePostLoader_js_node_modules_postcss_loader_src_index_js_ref_6_oneOf_1_2_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_App_vue_vue_type_style_index_0_id_3ce37488_scoped_true_lang_css___WEBPACK_IMPORTED_MODULE_0__);
|
||||
/* unused harmony reexport * */
|
||||
/* unused harmony default export */ var _unused_webpack_default_export = (_node_modules_mini_css_extract_plugin_dist_loader_js_ref_6_oneOf_1_0_node_modules_css_loader_dist_cjs_js_ref_6_oneOf_1_1_node_modules_vue_loader_lib_loaders_stylePostLoader_js_node_modules_postcss_loader_src_index_js_ref_6_oneOf_1_2_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_App_vue_vue_type_style_index_0_id_3ce37488_scoped_true_lang_css___WEBPACK_IMPORTED_MODULE_0___default.a);
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ "a189":
|
||||
/***/ (function(module, exports, __webpack_require__) {
|
||||
|
||||
// extracted by mini-css-extract-plugin
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ "a189":
|
||||
/***/ "b3f8":
|
||||
/***/ (function(module, exports, __webpack_require__) {
|
||||
|
||||
// extracted by mini-css-extract-plugin
|
||||
@@ -199,12 +199,12 @@ if (typeof window !== 'undefined') {
|
||||
// Indicate to webpack that this file can be concatenated
|
||||
/* harmony default export */ var setPublicPath = (null);
|
||||
|
||||
// CONCATENATED MODULE: ./node_modules/cache-loader/dist/cjs.js?{"cacheDirectory":"node_modules/.cache/vue-loader","cacheIdentifier":"5b04a8fd-vue-loader-template"}!./node_modules/vue-loader/lib/loaders/templateLoader.js??vue-loader-options!./node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/vue-loader/lib??vue-loader-options!./src/App.vue?vue&type=template&id=655db994&
|
||||
var render = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('div',[_c('mu-tabs',{attrs:{"value":_vm.active1,"indicator-color":"#80deea","inverse":"","center":""},on:{"update:value":function($event){_vm.active1=$event}}},[_c('mu-tab',[_vm._v("直播流")]),_c('mu-tab',[_vm._v("录制的视频")])],1),(_vm.Rooms.length==0 && _vm.active1==0)?_c('div',{staticClass:"empty"},[_c('Icon',{attrs:{"type":"md-wine","size":"50"}}),_vm._v("没有任何房间 ")],1):(_vm.active1==0)?_vm._l((_vm.Rooms),function(item){return _c('mu-card',{key:item.StreamPath,staticClass:"room"},[_c('mu-card-title',{attrs:{"title":item.StreamPath,"sub-title":item.StartTime}}),_c('mu-card-text',[_c('p',[_vm._v(" "+_vm._s(_vm.SoundFormat(item.AudioInfo.SoundFormat))+" "+_vm._s(item.AudioInfo.PacketCount)+" "+_vm._s(_vm.SoundRate(item.AudioInfo.SoundRate))+" 声道:"+_vm._s(item.AudioInfo.SoundType)+" ")]),_c('p',[_vm._v(" "+_vm._s(_vm.CodecID(item.VideoInfo.CodecID))+" "+_vm._s(item.VideoInfo.PacketCount)+" "+_vm._s(item.VideoInfo.SPSInfo.Width)+"x"+_vm._s(item.VideoInfo.SPSInfo.Height)+" ")])]),_c('mu-card-actions',[(_vm.isRecording(item))?_c('mu-button',{staticClass:"recording",attrs:{"icon":""},on:{"click":function($event){return _vm.stopRecord(item)}}},[_c('mu-icon',{attrs:{"value":"fiber_manual_record"}})],1):_c('mu-button',{attrs:{"icon":""},on:{"click":function($event){return _vm.record(item)}}},[_c('mu-icon',{attrs:{"value":"fiber_manual_record"}})],1)],1)],1)}):_vm._e(),(_vm.active1==1)?_c('Records',{ref:"recordsPanel"}):_vm._e()],2)}
|
||||
// CONCATENATED MODULE: ./node_modules/cache-loader/dist/cjs.js?{"cacheDirectory":"node_modules/.cache/vue-loader","cacheIdentifier":"5b04a8fd-vue-loader-template"}!./node_modules/vue-loader/lib/loaders/templateLoader.js??vue-loader-options!./node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/vue-loader/lib??vue-loader-options!./src/App.vue?vue&type=template&id=3ce37488&scoped=true&
|
||||
var render = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('div',[_c('mu-tabs',{attrs:{"value":_vm.active1,"indicator-color":"#80deea","inverse":"","center":""},on:{"update:value":function($event){_vm.active1=$event}}},[_c('mu-tab',[_vm._v("直播流")]),_c('mu-tab',[_vm._v("录制的视频")])],1),(_vm.active1==0)?_c('mu-data-table',{attrs:{"columns":_vm.columns,"data":_vm.$store.state.Room,"min-col-width":50},on:{"row-click":function (i,r){ return _vm.isRecording(r)?_vm.stopRecord(r):_vm.record(r); }},scopedSlots:_vm._u([{key:"default",fn:function(scope){return [(_vm.isRecording(scope.row))?_c('td',{staticClass:"is-center"}):_c('td',{staticClass:"is-center"}),_c('td',{staticClass:"is-center"},[_vm._v(_vm._s(scope.row.StreamPath))]),_c('td',{staticClass:"is-center"},[_vm._v(_vm._s(scope.row.Type||"await"))]),_c('td',{staticClass:"is-center"},[_c('StartTime',{attrs:{"value":scope.row.StartTime}})],1),_c('td',{staticClass:"is-center"},[_vm._v(_vm._s(_vm.SoundFormat(scope.row.AudioInfo.SoundFormat)))]),_c('td',{staticClass:"is-center"},[_vm._v(_vm._s(_vm.SoundRate(scope.row.AudioInfo.SoundRate)))]),_c('td',{staticClass:"is-center"},[_vm._v(_vm._s(scope.row.AudioInfo.SoundType))]),_c('td',{staticClass:"is-center"},[_vm._v(_vm._s(_vm.CodecID(scope.row.VideoInfo.CodecID)))]),_c('td',{staticClass:"is-center"},[_vm._v(_vm._s(scope.row.VideoInfo.SPSInfo.Width)+"x"+_vm._s(scope.row.VideoInfo.SPSInfo.Height))]),_c('td',{staticClass:"is-center"},[_vm._v(_vm._s(scope.row.AudioInfo.PacketCount)+"/"+_vm._s(scope.row.VideoInfo.PacketCount))]),_c('td',{staticClass:"is-center"},[_vm._v(_vm._s(_vm.getSubscriberCount(scope.row)))])]}}],null,false,1124011921)}):_vm._e(),(_vm.active1==1)?_c('Records',{ref:"recordsPanel"}):_vm._e()],1)}
|
||||
var staticRenderFns = []
|
||||
|
||||
|
||||
// CONCATENATED MODULE: ./src/App.vue?vue&type=template&id=655db994&
|
||||
// CONCATENATED MODULE: ./src/App.vue?vue&type=template&id=3ce37488&scoped=true&
|
||||
|
||||
// CONCATENATED MODULE: ./node_modules/cache-loader/dist/cjs.js?{"cacheDirectory":"node_modules/.cache/vue-loader","cacheIdentifier":"5b04a8fd-vue-loader-template"}!./node_modules/vue-loader/lib/loaders/templateLoader.js??vue-loader-options!./node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/vue-loader/lib??vue-loader-options!./src/components/Records.vue?vue&type=template&id=7c800264&scoped=true&
|
||||
var Recordsvue_type_template_id_7c800264_scoped_true_render = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('div',{staticClass:"records"},_vm._l((_vm.data),function(item){return _c('mu-card',{key:item},[_c('mu-card-title',{attrs:{"title":item.Path,"sub-title":_vm.unitFormat(item.Size)+' '+_vm.toDurationStr(item.Duration)}}),_c('mu-card-actions',[_c('mu-button',{attrs:{"icon":"","small":""},on:{"click":function($event){return _vm.play(item)}}},[_c('mu-icon',{attrs:{"value":"play_arrow"}})],1),_c('mu-button',{attrs:{"icon":"","small":""},on:{"click":function($event){return _vm.deleteFlv(item)}}},[_c('mu-icon',{attrs:{"value":"delete_forever"}})],1)],1)],1)}),1)}
|
||||
@@ -449,41 +449,7 @@ var component = normalizeComponent(
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
|
||||
let roomsES = null;
|
||||
const SoundFormat = {
|
||||
0: "Linear PCM, platform endian",
|
||||
1: "ADPCM",
|
||||
2: "MP3",
|
||||
3: "Linear PCM, little endian",
|
||||
4: "Nellymoser 16kHz mono",
|
||||
5: "Nellymoser 8kHz mono",
|
||||
6: "Nellymoser",
|
||||
7: "G.711 A-law logarithmic PCM",
|
||||
8: "G.711 mu-law logarithmic PCM",
|
||||
9: "reserved",
|
||||
10: "AAC",
|
||||
11: "Speex",
|
||||
14: "MP3 8Khz",
|
||||
15: "Device-specific sound"
|
||||
};
|
||||
const CodecID = {
|
||||
1: "JPEG (currently unused)",
|
||||
2: "Sorenson H.263",
|
||||
3: "Screen video",
|
||||
4: "On2 VP6",
|
||||
5: "On2 VP6 with alpha channel",
|
||||
6: "Screen video version 2",
|
||||
7: "AVC",
|
||||
12: "H265"
|
||||
};
|
||||
|
||||
/* harmony default export */ var Appvue_type_script_lang_js_ = ({
|
||||
components: {
|
||||
@@ -491,55 +457,81 @@ const CodecID = {
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
Rooms: [],
|
||||
typeMap: {
|
||||
Receiver: "📡",
|
||||
FlvFile: "🎥",
|
||||
TS: "🎬",
|
||||
HLS: "🍎",
|
||||
"": "⏳",
|
||||
Match365: "🏆",
|
||||
RTMP: "🚠"
|
||||
}
|
||||
columns: [
|
||||
{
|
||||
title: "房间",
|
||||
name: "StreamPath",
|
||||
sortable: true
|
||||
},
|
||||
{
|
||||
title: "类型",
|
||||
name: "Type",
|
||||
sortable: true
|
||||
},
|
||||
{
|
||||
title: "开始时间",
|
||||
name: "StartTime",
|
||||
sortable: true
|
||||
},
|
||||
{
|
||||
title: "音频格式",
|
||||
name: "AudioInfo"
|
||||
},
|
||||
{
|
||||
title: "采样率",
|
||||
name: "AudioInfo"
|
||||
},
|
||||
{
|
||||
title: "声道",
|
||||
name: "AudioInfo"
|
||||
},
|
||||
{
|
||||
title: "视频格式",
|
||||
name: "VideoInfo"
|
||||
},
|
||||
{
|
||||
title: "分辨率",
|
||||
name: "VideoInfo"
|
||||
},
|
||||
{
|
||||
title: "数据包",
|
||||
name: ""
|
||||
},
|
||||
{
|
||||
title: "订阅者",
|
||||
name: "Subscribes"
|
||||
}
|
||||
]
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
SoundFormat(soundFormat) {
|
||||
return SoundFormat[soundFormat];
|
||||
},
|
||||
CodecID(codec) {
|
||||
return CodecID[codec];
|
||||
},
|
||||
SoundRate(rate) {
|
||||
return rate > 1000 ? rate / 1000 + "kHz" : rate + "Hz";
|
||||
},
|
||||
record(item) {
|
||||
this.$Modal.confirm({
|
||||
title: "提示",
|
||||
content:
|
||||
"<p>是否使用追加模式</p><small>选择取消将覆盖已有文件</small>",
|
||||
onOk: () => {
|
||||
window.ajax.get(
|
||||
"/record/flv?append=true",
|
||||
{ streamPath: item.StreamPath },
|
||||
x => {
|
||||
if (x == "success") {
|
||||
this.$Message.success("开始录制(追加模式)");
|
||||
} else {
|
||||
this.$Message.error(x);
|
||||
let append = false;
|
||||
this.$confirm(
|
||||
h =>
|
||||
h("mu-switch", {
|
||||
props: {
|
||||
label: "追加模式"
|
||||
},
|
||||
on: {
|
||||
change(value) {
|
||||
append = value;
|
||||
}
|
||||
}
|
||||
);
|
||||
},
|
||||
onCancel: () => {
|
||||
window.ajax.get(
|
||||
"/record/flv",
|
||||
}),
|
||||
"是否开始录制"
|
||||
).then(result => {
|
||||
if (result) {
|
||||
this.ajax.get(
|
||||
"/record/flv?append=" + append,
|
||||
{ streamPath: item.StreamPath },
|
||||
x => {
|
||||
if (x == "success") {
|
||||
this.$Message.success("开始录制");
|
||||
this.$toast.success(
|
||||
"开始录制" + (append ? "(追加模式)" : "")
|
||||
);
|
||||
} else {
|
||||
this.$Message.error(x);
|
||||
this.$toast.error(x);
|
||||
}
|
||||
}
|
||||
);
|
||||
@@ -547,51 +539,33 @@ const CodecID = {
|
||||
});
|
||||
},
|
||||
stopRecord(item) {
|
||||
window.ajax.get(
|
||||
"/record/flv/stop",
|
||||
{ streamPath: item.StreamPath },
|
||||
x => {
|
||||
if (x == "success") {
|
||||
this.$Message.success("停止录制");
|
||||
} else {
|
||||
this.$Message.error(x);
|
||||
this.$confirm("是否停止录制", "提示").then(result => {
|
||||
this.ajax.get(
|
||||
"/record/flv/stop",
|
||||
{ streamPath: item.StreamPath },
|
||||
x => {
|
||||
if (x == "success") {
|
||||
this.$toast.success("停止录制");
|
||||
} else {
|
||||
this.$toast.error(x);
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
);
|
||||
});
|
||||
},
|
||||
isRecording(item) {
|
||||
return (
|
||||
item.SubscriberInfo &&
|
||||
item.SubscriberInfo.find(x => x.Type == "FlvRecord")
|
||||
);
|
||||
},
|
||||
fetchRooms() {
|
||||
roomsES = new EventSource("/api/summary");
|
||||
roomsES.onmessage = evt => {
|
||||
if (!evt.data) return;
|
||||
let summary = JSON.parse(evt.data);
|
||||
this.Rooms = (summary && summary.Rooms) || [];
|
||||
this.Rooms.sort((a, b) =>
|
||||
a.StreamPath > b.StreamPath ? 1 : -1
|
||||
);
|
||||
};
|
||||
},
|
||||
onClickTab(name) {
|
||||
this.$refs.recordsPanel.onVisible(name == "recordsPanel");
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.fetchRooms();
|
||||
},
|
||||
destroyed() {
|
||||
roomsES.close();
|
||||
}
|
||||
});
|
||||
|
||||
// CONCATENATED MODULE: ./src/App.vue?vue&type=script&lang=js&
|
||||
/* harmony default export */ var src_Appvue_type_script_lang_js_ = (Appvue_type_script_lang_js_);
|
||||
// EXTERNAL MODULE: ./src/App.vue?vue&type=style&index=0&lang=css&
|
||||
var Appvue_type_style_index_0_lang_css_ = __webpack_require__("034f");
|
||||
// EXTERNAL MODULE: ./src/App.vue?vue&type=style&index=0&id=3ce37488&scoped=true&lang=css&
|
||||
var Appvue_type_style_index_0_id_3ce37488_scoped_true_lang_css_ = __webpack_require__("39a8");
|
||||
|
||||
// CONCATENATED MODULE: ./src/App.vue
|
||||
|
||||
@@ -608,7 +582,7 @@ var App_component = normalizeComponent(
|
||||
staticRenderFns,
|
||||
false,
|
||||
null,
|
||||
null,
|
||||
"3ce37488",
|
||||
null
|
||||
|
||||
)
|
||||
|
2
ui/dist/plugin-record.umd.js.map
vendored
2
ui/dist/plugin-record.umd.js.map
vendored
File diff suppressed because one or more lines are too long
2
ui/dist/plugin-record.umd.min.js
vendored
2
ui/dist/plugin-record.umd.min.js
vendored
File diff suppressed because one or more lines are too long
2
ui/dist/plugin-record.umd.min.js.map
vendored
2
ui/dist/plugin-record.umd.min.js.map
vendored
File diff suppressed because one or more lines are too long
220
ui/src/App.vue
220
ui/src/App.vue
@@ -4,64 +4,30 @@
|
||||
<mu-tab>直播流</mu-tab>
|
||||
<mu-tab>录制的视频</mu-tab>
|
||||
</mu-tabs>
|
||||
<div v-if="Rooms.length==0 && active1==0" class="empty">
|
||||
<Icon type="md-wine" size="50" />没有任何房间
|
||||
</div>
|
||||
<template v-else-if="active1==0">
|
||||
<mu-card v-for="item in Rooms" :key="item.StreamPath" class="room">
|
||||
<mu-card-title :title="item.StreamPath" :sub-title="item.StartTime" />
|
||||
<mu-card-text>
|
||||
<p>
|
||||
{{SoundFormat(item.AudioInfo.SoundFormat)}} {{item.AudioInfo.PacketCount}}
|
||||
{{SoundRate(item.AudioInfo.SoundRate)}} 声道:{{item.AudioInfo.SoundType}}
|
||||
</p>
|
||||
<p>
|
||||
{{CodecID(item.VideoInfo.CodecID)}} {{item.VideoInfo.PacketCount}}
|
||||
{{item.VideoInfo.SPSInfo.Width}}x{{item.VideoInfo.SPSInfo.Height}}
|
||||
</p>
|
||||
</mu-card-text>
|
||||
<mu-card-actions>
|
||||
<mu-button icon @click="stopRecord(item)" class="recording" v-if="isRecording(item)">
|
||||
<mu-icon value="fiber_manual_record" />
|
||||
</mu-button>
|
||||
<mu-button icon @click="record(item)" v-else>
|
||||
<mu-icon value="fiber_manual_record" />
|
||||
</mu-button>
|
||||
</mu-card-actions>
|
||||
</mu-card>
|
||||
</template>
|
||||
<mu-data-table v-if="active1==0" :columns="columns" :data="$store.state.Room" :min-col-width="50"
|
||||
@row-click="(i,r)=>isRecording(r)?stopRecord(r):record(r)">
|
||||
<template slot-scope="scope">
|
||||
<td class="is-center" v-if="isRecording(scope.row)"></td>
|
||||
<td class="is-center" v-else></td>
|
||||
<td class="is-center">{{scope.row.StreamPath}}</td>
|
||||
<td class="is-center">{{scope.row.Type||"await"}}</td>
|
||||
<td class="is-center">
|
||||
<StartTime :value="scope.row.StartTime"></StartTime>
|
||||
</td>
|
||||
<td class="is-center">{{SoundFormat(scope.row.AudioInfo.SoundFormat)}}</td>
|
||||
<td class="is-center">{{SoundRate(scope.row.AudioInfo.SoundRate)}}</td>
|
||||
<td class="is-center">{{scope.row.AudioInfo.SoundType}}</td>
|
||||
<td class="is-center">{{CodecID(scope.row.VideoInfo.CodecID)}}</td>
|
||||
<td class="is-center">{{scope.row.VideoInfo.SPSInfo.Width}}x{{scope.row.VideoInfo.SPSInfo.Height}}</td>
|
||||
<td class="is-center">{{scope.row.AudioInfo.PacketCount}}/{{scope.row.VideoInfo.PacketCount}}</td>
|
||||
<td class="is-center">{{getSubscriberCount(scope.row)}}</td>
|
||||
</template>
|
||||
</mu-data-table>
|
||||
<Records ref="recordsPanel" v-if="active1==1" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
let roomsES = null;
|
||||
const SoundFormat = {
|
||||
0: "Linear PCM, platform endian",
|
||||
1: "ADPCM",
|
||||
2: "MP3",
|
||||
3: "Linear PCM, little endian",
|
||||
4: "Nellymoser 16kHz mono",
|
||||
5: "Nellymoser 8kHz mono",
|
||||
6: "Nellymoser",
|
||||
7: "G.711 A-law logarithmic PCM",
|
||||
8: "G.711 mu-law logarithmic PCM",
|
||||
9: "reserved",
|
||||
10: "AAC",
|
||||
11: "Speex",
|
||||
14: "MP3 8Khz",
|
||||
15: "Device-specific sound"
|
||||
};
|
||||
const CodecID = {
|
||||
1: "JPEG (currently unused)",
|
||||
2: "Sorenson H.263",
|
||||
3: "Screen video",
|
||||
4: "On2 VP6",
|
||||
5: "On2 VP6 with alpha channel",
|
||||
6: "Screen video version 2",
|
||||
7: "AVC",
|
||||
12: "H265"
|
||||
};
|
||||
import Records from "./components/Records";
|
||||
export default {
|
||||
components: {
|
||||
@@ -69,55 +35,81 @@ export default {
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
Rooms: [],
|
||||
typeMap: {
|
||||
Receiver: "📡",
|
||||
FlvFile: "🎥",
|
||||
TS: "🎬",
|
||||
HLS: "🍎",
|
||||
"": "⏳",
|
||||
Match365: "🏆",
|
||||
RTMP: "🚠"
|
||||
}
|
||||
columns: [
|
||||
{
|
||||
title: "房间",
|
||||
name: "StreamPath",
|
||||
sortable: true
|
||||
},
|
||||
{
|
||||
title: "类型",
|
||||
name: "Type",
|
||||
sortable: true
|
||||
},
|
||||
{
|
||||
title: "开始时间",
|
||||
name: "StartTime",
|
||||
sortable: true
|
||||
},
|
||||
{
|
||||
title: "音频格式",
|
||||
name: "AudioInfo"
|
||||
},
|
||||
{
|
||||
title: "采样率",
|
||||
name: "AudioInfo"
|
||||
},
|
||||
{
|
||||
title: "声道",
|
||||
name: "AudioInfo"
|
||||
},
|
||||
{
|
||||
title: "视频格式",
|
||||
name: "VideoInfo"
|
||||
},
|
||||
{
|
||||
title: "分辨率",
|
||||
name: "VideoInfo"
|
||||
},
|
||||
{
|
||||
title: "数据包",
|
||||
name: ""
|
||||
},
|
||||
{
|
||||
title: "订阅者",
|
||||
name: "Subscribes"
|
||||
}
|
||||
]
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
SoundFormat(soundFormat) {
|
||||
return SoundFormat[soundFormat];
|
||||
},
|
||||
CodecID(codec) {
|
||||
return CodecID[codec];
|
||||
},
|
||||
SoundRate(rate) {
|
||||
return rate > 1000 ? rate / 1000 + "kHz" : rate + "Hz";
|
||||
},
|
||||
record(item) {
|
||||
this.$Modal.confirm({
|
||||
title: "提示",
|
||||
content:
|
||||
"<p>是否使用追加模式</p><small>选择取消将覆盖已有文件</small>",
|
||||
onOk: () => {
|
||||
window.ajax.get(
|
||||
"/record/flv?append=true",
|
||||
{ streamPath: item.StreamPath },
|
||||
x => {
|
||||
if (x == "success") {
|
||||
this.$Message.success("开始录制(追加模式)");
|
||||
} else {
|
||||
this.$Message.error(x);
|
||||
let append = false;
|
||||
this.$confirm(
|
||||
h =>
|
||||
h("mu-switch", {
|
||||
props: {
|
||||
label: "追加模式"
|
||||
},
|
||||
on: {
|
||||
change(value) {
|
||||
append = value;
|
||||
}
|
||||
}
|
||||
);
|
||||
},
|
||||
onCancel: () => {
|
||||
window.ajax.get(
|
||||
"/record/flv",
|
||||
}),
|
||||
"是否开始录制"
|
||||
).then(result => {
|
||||
if (result) {
|
||||
this.ajax.get(
|
||||
"/record/flv?append=" + append,
|
||||
{ streamPath: item.StreamPath },
|
||||
x => {
|
||||
if (x == "success") {
|
||||
this.$Message.success("开始录制");
|
||||
this.$toast.success(
|
||||
"开始录制" + (append ? "(追加模式)" : "")
|
||||
);
|
||||
} else {
|
||||
this.$Message.error(x);
|
||||
this.$toast.error(x);
|
||||
}
|
||||
}
|
||||
);
|
||||
@@ -125,49 +117,31 @@ export default {
|
||||
});
|
||||
},
|
||||
stopRecord(item) {
|
||||
window.ajax.get(
|
||||
"/record/flv/stop",
|
||||
{ streamPath: item.StreamPath },
|
||||
x => {
|
||||
if (x == "success") {
|
||||
this.$Message.success("停止录制");
|
||||
} else {
|
||||
this.$Message.error(x);
|
||||
this.$confirm("是否停止录制", "提示").then(result => {
|
||||
this.ajax.get(
|
||||
"/record/flv/stop",
|
||||
{ streamPath: item.StreamPath },
|
||||
x => {
|
||||
if (x == "success") {
|
||||
this.$toast.success("停止录制");
|
||||
} else {
|
||||
this.$toast.error(x);
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
);
|
||||
});
|
||||
},
|
||||
isRecording(item) {
|
||||
return (
|
||||
item.SubscriberInfo &&
|
||||
item.SubscriberInfo.find(x => x.Type == "FlvRecord")
|
||||
);
|
||||
},
|
||||
fetchRooms() {
|
||||
roomsES = new EventSource("/api/summary");
|
||||
roomsES.onmessage = evt => {
|
||||
if (!evt.data) return;
|
||||
let summary = JSON.parse(evt.data);
|
||||
this.Rooms = (summary && summary.Rooms) || [];
|
||||
this.Rooms.sort((a, b) =>
|
||||
a.StreamPath > b.StreamPath ? 1 : -1
|
||||
);
|
||||
};
|
||||
},
|
||||
onClickTab(name) {
|
||||
this.$refs.recordsPanel.onVisible(name == "recordsPanel");
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.fetchRooms();
|
||||
},
|
||||
destroyed() {
|
||||
roomsES.close();
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style>
|
||||
<style scoped>
|
||||
@keyframes recording {
|
||||
0% {
|
||||
opacity: 0.2;
|
||||
|
Reference in New Issue
Block a user