录制功能调试

This commit is contained in:
langhuihui
2020-01-29 17:11:09 +08:00
parent 4e0934451b
commit 5eb7f03dec
15 changed files with 56 additions and 31 deletions

View File

@@ -12,7 +12,7 @@ ListenAddr = ":81"
# #
#[Plugins.Auth] #[Plugins.Auth]
#Key="www.monibuca.com" #Key="www.monibuca.com"
#[Plugins.RecordFlv] [Plugins.RecordFlv]
#Path="./resouce" Path="./resouce"
[Plugins.QoS] [Plugins.QoS]
Suffix = ["high","medium","low"] Suffix = ["high","medium","low"]

View File

@@ -1,6 +1,6 @@
.DS_Store .DS_Store
node_modules node_modules
public/docs
# local env files # local env files
.env.local .env.local

View File

@@ -1 +0,0 @@
#app,body,html{height:100%}#app{font-family:Avenir,Helvetica,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;text-align:center;color:#184c18;position:relative}#app>div:first-child{position:absolute;top:10px;left:30px;font-size:x-large}.content{padding-top:60px}.feature-title[data-v-54efad41]{color:#eb5e46;font-weight:700;font-size:larger}p[data-v-54efad41]{margin:30px;font-size:20px}img[data-v-54efad41]{margin:20px}.root[data-v-e34eab40]{background:#d3d3d3}.root>img[data-v-e34eab40]{width:300px;margin:30px}@-webkit-keyframes recording-data-v-7b106554{0%{opacity:.2}50%{opacity:1}to{opacity:.2}}@keyframes recording-data-v-7b106554{0%{opacity:.2}50%{opacity:1}to{opacity:.2}}.recording[data-v-7b106554]{-webkit-animation:recording-data-v-7b106554 1s infinite;animation:recording-data-v-7b106554 1s infinite}.layout[data-v-7b106554]{padding-bottom:30px;position:relative}.room[data-v-7b106554]{width:250px;margin:10px;text-align:left}.empty[data-v-7b106554]{color:#eb5e46;width:100%;min-height:500px;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center}.empty[data-v-7b106554],.status[data-v-7b106554]{display:-webkit-box;display:-ms-flexbox;display:flex}.status[data-v-7b106554]{position:fixed;left:5px;bottom:10px}.status>div[data-v-7b106554]{margin:0 5px}

1
dashboard/dist/css/app.e2fa93b0.css vendored Normal file
View File

@@ -0,0 +1 @@
#app,body,html{height:100%}#app{font-family:Avenir,Helvetica,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;text-align:center;color:#184c18;position:relative}#app>div:first-child{position:absolute;top:10px;left:30px;font-size:x-large}.content{padding-top:60px}.feature-title[data-v-54efad41]{color:#eb5e46;font-weight:700;font-size:larger}p[data-v-54efad41]{margin:30px;font-size:20px}img[data-v-54efad41]{margin:20px}.root[data-v-e34eab40]{background:#d3d3d3}.root>img[data-v-e34eab40]{width:300px;margin:30px}@-webkit-keyframes recording-data-v-c2fdc660{0%{opacity:.2}50%{opacity:1}to{opacity:.2}}@keyframes recording-data-v-c2fdc660{0%{opacity:.2}50%{opacity:1}to{opacity:.2}}.recording[data-v-c2fdc660]{-webkit-animation:recording-data-v-c2fdc660 1s infinite;animation:recording-data-v-c2fdc660 1s infinite}.layout[data-v-c2fdc660]{padding-bottom:30px;display:-webkit-box;display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap}.room[data-v-c2fdc660]{width:250px;margin:10px;text-align:left}.empty[data-v-c2fdc660]{color:#eb5e46;width:100%;min-height:500px;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center}.empty[data-v-c2fdc660],.status[data-v-c2fdc660]{display:-webkit-box;display:-ms-flexbox;display:flex}.status[data-v-c2fdc660]{position:fixed;left:5px;bottom:10px}.status>div[data-v-c2fdc660]{margin:0 5px}

View File

@@ -1 +1 @@
<!DOCTYPE html><html lang=en><head><meta charset=utf-8><meta http-equiv=X-UA-Compatible content="IE=edge"><meta name=viewport content="width=device-width,initial-scale=1"><link rel=icon href=/favicon.ico><title>Monibuca</title><script src=jessibuca/ajax.js></script><script src=jessibuca/renderer.js></script><link href=/css/app.b4fc79e8.css rel=preload as=style><link href=/css/chunk-vendors.22ebf426.css rel=preload as=style><link href=/js/app.9cc902b4.js rel=preload as=script><link href=/js/chunk-vendors.ae8ac63d.js rel=preload as=script><link href=/css/chunk-vendors.22ebf426.css rel=stylesheet><link href=/css/app.b4fc79e8.css rel=stylesheet></head><body><noscript><strong>We're sorry but dashboard doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript><div id=app></div><script src=/js/chunk-vendors.ae8ac63d.js></script><script src=/js/app.9cc902b4.js></script></body></html> <!DOCTYPE html><html lang=en><head><meta charset=utf-8><meta http-equiv=X-UA-Compatible content="IE=edge"><meta name=viewport content="width=device-width,initial-scale=1"><link rel=icon href=/favicon.ico><title>Monibuca</title><script src=jessibuca/ajax.js></script><script src=jessibuca/renderer.js></script><link href=/css/app.e2fa93b0.css rel=preload as=style><link href=/css/chunk-vendors.22ebf426.css rel=preload as=style><link href=/js/app.d106a496.js rel=preload as=script><link href=/js/chunk-vendors.ae8ac63d.js rel=preload as=script><link href=/css/chunk-vendors.22ebf426.css rel=stylesheet><link href=/css/app.e2fa93b0.css rel=stylesheet></head><body><noscript><strong>We're sorry but dashboard doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript><div id=app></div><script src=/js/chunk-vendors.ae8ac63d.js></script><script src=/js/app.d106a496.js></script></body></html>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

2
dashboard/dist/js/app.d106a496.js vendored Normal file

File diff suppressed because one or more lines are too long

1
dashboard/dist/js/app.d106a496.js.map vendored Normal file

File diff suppressed because one or more lines are too long

View File

@@ -48,6 +48,7 @@
"parser": "babel-eslint" "parser": "babel-eslint"
}, },
"rules": { "rules": {
"no-console": "off",
"vue/no-parsing-error": [ "vue/no-parsing-error": [
2, 2,
{ {

View File

@@ -18,22 +18,17 @@
{{CodecID(item.VideoInfo.CodecID)}} {{item.VideoInfo.PacketCount}} {{CodecID(item.VideoInfo.CodecID)}} {{item.VideoInfo.PacketCount}}
{{item.VideoInfo.SPSInfo.Width}}x{{item.VideoInfo.SPSInfo.Height}} {{item.VideoInfo.SPSInfo.Width}}x{{item.VideoInfo.SPSInfo.Height}}
</p> </p>
<Button @click="onShowDetail(item)"> <ButtonGroup size="small">
<Icon type="ios-people"/> <Button @click="onShowDetail(item)" icon="ios-people">
{{item.SubscriberInfo?item.SubscriberInfo.length:0}} {{item.SubscriberInfo?item.SubscriberInfo.length:0}}
</Button> </Button>
<Button v-if="item.Type" @click="preview(item)"> <Button v-if="item.Type" @click="preview(item)" icon="md-eye">
<Icon type="md-eye"/>
Preview
</Button> </Button>
<Button @click="stopRecord(item)" v-if="isRecording(item)"> <Button @click="stopRecord(item)" class="recording" v-if="isRecording(item)" icon="ios-radio-button-on">
<Icon type="ios-radio-button-on" class="recording"/>
Stop Rec
</Button> </Button>
<Button @click="record(item)" v-else> <Button @click="record(item)" v-else icon="ios-radio-button-on">
<Icon type="ios-radio-button-on"/>
Rec
</Button> </Button>
</ButtonGroup>
</Card> </Card>
<div v-if="Rooms.length==0" class="empty"> <div v-if="Rooms.length==0" class="empty">
<Icon type="md-wine" size="50"/> <Icon type="md-wine" size="50"/>
@@ -164,10 +159,22 @@
return rate > 1000 ? (rate / 1000) + "kHz" : rate + "Hz" return rate > 1000 ? (rate / 1000) + "kHz" : rate + "Hz"
}, },
record(item) { record(item) {
window.ajax.get("//" + location.host + "/api/record/flv",{streamPath:item.StreamPath}) window.ajax.get("//" + location.host + "/api/record/flv", {streamPath: item.StreamPath}, x => {
if (x == "success") {
this.$Message.success('开始录制');
} else {
this.$Message.error(x);
}
})
}, },
stopRecord(item) { stopRecord(item) {
window.ajax.get("//" + location.host + "/api/record/flv/stop",{streamPath:item.StreamPath}) window.ajax.get("//" + location.host + "/api/record/flv/stop", {streamPath: item.StreamPath}, x => {
if (x == "success") {
this.$Message.success('停止录制');
} else {
this.$Message.error(x);
}
})
}, },
isRecording(item) { isRecording(item) {
return item.SubscriberInfo && item.SubscriberInfo.find(x => x.Type == "FlvRecord") return item.SubscriberInfo && item.SubscriberInfo.find(x => x.Type == "FlvRecord")
@@ -201,7 +208,8 @@
.layout { .layout {
padding-bottom: 30px; padding-bottom: 30px;
position: relative; display: flex;
flex-wrap: wrap;
} }
.room { .room {

View File

@@ -1,6 +1,7 @@
package main package main
import ( import (
"flag"
. "github.com/langhuihui/monibuca/monica" . "github.com/langhuihui/monibuca/monica"
_ "github.com/langhuihui/monibuca/plugins" _ "github.com/langhuihui/monibuca/plugins"
"log" "log"
@@ -9,6 +10,8 @@ import (
func main() { func main() {
log.SetOutput(os.Stdout) log.SetOutput(os.Stdout)
Run("config.toml") configPath := flag.String("c", "config.toml", "configFile")
flag.Parse()
Run(*configPath)
select {} select {}
} }

View File

@@ -7,6 +7,7 @@ import (
"github.com/langhuihui/monibuca/monica/util" "github.com/langhuihui/monibuca/monica/util"
"io" "io"
"os" "os"
"path"
) )
func SaveFlv(streamPath string, append bool) error { func SaveFlv(streamPath string, append bool) error {
@@ -17,11 +18,11 @@ func SaveFlv(streamPath string, append bool) error {
flag = flag | os.O_TRUNC | os.O_WRONLY flag = flag | os.O_TRUNC | os.O_WRONLY
} }
filePath := config.Path + streamPath + ".flv" filePath := config.Path + streamPath + ".flv"
os.MkdirAll(path.Dir(filePath), 0666)
file, err := os.OpenFile(filePath, flag, 0666) file, err := os.OpenFile(filePath, flag, 0666)
if err != nil { if err != nil {
return err return err
} }
defer file.Close()
p := OutputStream{SendHandler: func(packet *pool.SendPacket) error { p := OutputStream{SendHandler: func(packet *pool.SendPacket) error {
return avformat.WriteFLVTag(file, packet) return avformat.WriteFLVTag(file, packet)
}} }}
@@ -47,7 +48,12 @@ func SaveFlv(streamPath string, append bool) error {
} }
if err == nil { if err == nil {
recordings.Store(filePath, &p) recordings.Store(filePath, &p)
go p.Play(streamPath) go func() {
p.Play(streamPath)
file.Close()
}()
} else {
file.Close()
} }
return err return err
} }

View File

@@ -3,6 +3,7 @@ package record
import ( import (
. "github.com/langhuihui/monibuca/monica" . "github.com/langhuihui/monibuca/monica"
"net/http" "net/http"
"strings"
"sync" "sync"
) )
@@ -20,6 +21,9 @@ func init() {
}) })
} }
func run() { func run() {
if !strings.HasSuffix(config.Path, "/") {
config.Path = config.Path + "/"
}
http.HandleFunc("/api/record/flv", func(writer http.ResponseWriter, r *http.Request) { http.HandleFunc("/api/record/flv", func(writer http.ResponseWriter, r *http.Request) {
if streamPath := r.URL.Query().Get("streamPath"); streamPath != "" { 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") != ""); err != nil {

View File

@@ -87,6 +87,9 @@ func processRtmp(conn net.Conn) {
} }
switch msg.MessageTypeID { switch msg.MessageTypeID {
case RTMP_MSG_AMF0_COMMAND: case RTMP_MSG_AMF0_COMMAND:
if msg.MsgData == nil {
break
}
cmd := msg.MsgData.(Commander).GetCommand() cmd := msg.MsgData.(Commander).GetCommand()
switch cmd.CommandName { switch cmd.CommandName {
case "createStream": case "createStream":