录制的web界面

This commit is contained in:
langhuihui
2020-01-28 21:40:25 +08:00
parent 3a9851fcd6
commit 45748aa006
8 changed files with 99 additions and 52 deletions

1
README.md Normal file
View File

@@ -0,0 +1 @@
[中文文档](http://monibuca.com/docs)

View File

@@ -1,21 +1,38 @@
<template>
<div class="layout">
<Card v-for="item in Rooms" :key="item.StreamName" class="room">
<ButtonGroup vertical>
<Button icon="ios-folder"></Button>
<Button icon="md-bug"></Button>
<Button icon="md-settings"></Button>
</ButtonGroup>
<Card v-for="item in Rooms" :key="item.StreamPath" class="room">
<p slot="title">
{{typeMap[item.Type]||item.Type}}{{item.StreamName}}
{{typeMap[item.Type]||item.Type}}{{item.StreamPath}}
</p>
<StartTime slot="extra" :value="item.StartTime"></StartTime>
<p>
{{SoundFormat(item.AudioInfo.SoundFormat)}} {{item.AudioInfo.PacketCount}} {{SoundRate(item.AudioInfo.SoundRate)}} 声道:{{item.AudioInfo.SoundType}}
{{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}}
{{CodecID(item.VideoInfo.CodecID)}} {{item.VideoInfo.PacketCount}}
{{item.VideoInfo.SPSInfo.Width}}x{{item.VideoInfo.SPSInfo.Height}}
</p>
<Button @click="onShowDetail(item)">
👨👩👦👦 {{item.SubscriberInfo?item.SubscriberInfo.length:0}}
<Icon type="ios-people"/>
{{item.SubscriberInfo?item.SubscriberInfo.length:0}}
</Button>
<Button v-if="item.Type" @click="preview(item)">
👁Preview
<Icon type="md-eye"/>
Preview
</Button>
<Button @click="stopRecord(item)" v-if="isRecording(item)">
<Icon type="ios-radio-button-on" class="recording"/>
Stop Rec
</Button>
<Button @click="record(item)" v-else>
<Icon type="ios-radio-button-on"/>
Rec
</Button>
</Card>
<div v-if="Rooms.length==0" class="empty">
@@ -52,29 +69,31 @@
G: 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"}
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"}
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"
}
export default {
name: "Console",
components: {
@@ -123,7 +142,7 @@
'stopFetchSummary'
]),
preview(item) {
this.$refs.jessibuca.play("ws://" + location.hostname + ":8080/" + item.StreamName)
this.$refs.jessibuca.play("ws://" + location.hostname + ":8080/" + item.StreamPath)
this.showPreview = true
}, onShowDetail() {
// this.showDetail = true
@@ -135,14 +154,23 @@
}
return value.toFixed(2).replace(".00", "") + unit + "B"
},
SoundFormat(soundFormat){
SoundFormat(soundFormat) {
return SoundFormat[soundFormat]
},
CodecID(codec){
CodecID(codec) {
return CodecID[codec]
},
SoundRate(rate){
return rate>1000?(rate/1000)+"kHz":rate+"Hz"
SoundRate(rate) {
return rate > 1000 ? (rate / 1000) + "kHz" : rate + "Hz"
},
record(item) {
ajax.get("//" + location.host + "/api/record/flv",{streamPath:item.StreamPath})
},
stopRecord(item){
ajax.get("//" + location.host + "/api/record/flv/stop",{streamPath:item.StreamPath})
},
isRecording(item) {
return item.SubscriberInfo && item.SubscriberInfo.find(x => x.Type == "FlvRecord")
}
},
mounted() {
@@ -155,15 +183,33 @@
</script>
<style scoped>
@keyframes recording {
0% {
opacity: 0.2;
}
50% {
opacity: 1;
}
100% {
opacity: 0.2;
}
}
.recording {
animation: recording 1s infinite;
}
.layout {
padding-bottom: 30px;
position: relative;
}
.room{
.room {
width: 250px;
margin: 10px;
text-align: left;
}
.empty {
color: #eb5e46;
width: 100%;

View File

@@ -27,7 +27,7 @@ func (c *Collection) Get(name string) (result *Room) {
})
result = item.(*Room)
if !loaded {
result.StreamName = name
result.StreamPath = name
result.Context, result.Cancel = context.WithCancel(roomCtxBg)
go result.Run()
}
@@ -50,7 +50,7 @@ type Room struct {
}
type RoomInfo struct {
StreamName string
StreamPath string
StartTime time.Time
SubscriberInfo []*SubscriberInfo
Type string
@@ -79,8 +79,8 @@ type ChangeRoomCmd struct {
}
func (r *Room) onClosed() {
log.Printf("room destoryed :%s", r.StreamName)
AllRoom.Delete(r.StreamName)
log.Printf("room destoryed :%s", r.StreamPath)
AllRoom.Delete(r.StreamPath)
if r.Publisher != nil {
r.OnClosed()
}
@@ -89,7 +89,7 @@ func (r *Room) Subscribe(s *OutputStream) {
s.Room = r
if r.Err() == nil {
s.SubscribeTime = time.Now()
log.Printf("subscribe :%s %s,to room %s", s.Type, s.ID, r.StreamName)
log.Printf("subscribe :%s %s,to room %s", s.Type, s.ID, r.StreamPath)
s.packetQueue = make(chan *pool.SendPacket, 1024)
s.Context, s.Cancel = context.WithCancel(r)
s.Control <- &SubscribeCmd{s}
@@ -102,7 +102,7 @@ func (r *Room) UnSubscribe(s *OutputStream) {
}
}
func (r *Room) Run() {
log.Printf("room create :%s", r.StreamName)
log.Printf("room create :%s", r.StreamPath)
defer r.onClosed()
update := time.NewTicker(time.Second)
defer update.Stop()
@@ -121,14 +121,14 @@ func (r *Room) Run() {
switch v := s.(type) {
case *UnSubscribeCmd:
delete(r.Subscribers, v.ID)
log.Printf("%s subscriber %s removed remains:%d", r.StreamName, v.ID, len(r.Subscribers))
log.Printf("%s subscriber %s removed remains:%d", r.StreamPath, v.ID, len(r.Subscribers))
if len(r.Subscribers) == 0 && r.Publisher == nil {
r.Cancel()
}
case *SubscribeCmd:
if _, ok := r.Subscribers[v.ID]; !ok {
r.Subscribers[v.ID] = v.OutputStream
log.Printf("%s subscriber %s added remains:%d", r.StreamName, v.ID, len(r.Subscribers))
log.Printf("%s subscriber %s added remains:%d", r.StreamPath, v.ID, len(r.Subscribers))
OnSubscribeHooks.Trigger(v.OutputStream)
}
case *ChangeRoomCmd:

View File

@@ -139,7 +139,7 @@ func (ts *TS) run() {
time.Sleep(duration)
} else {
time.Sleep(time.Millisecond * 20)
log.Printf("stream:%s,duration:%d,dts:%d,lastDts:%d\n", ts.StreamName, duration/time.Millisecond, tsPesPkt.PesPkt.Header.Dts, lastDts)
log.Printf("stream:%s,duration:%d,dts:%d,lastDts:%d\n", ts.StreamPath, duration/time.Millisecond, tsPesPkt.PesPkt.Header.Dts, lastDts)
}
}
}
@@ -148,8 +148,8 @@ func (ts *TS) run() {
}
}
func (ts *TS) Publish(streamName string, publisher Publisher) (result bool) {
if result = ts.InputStream.Publish(streamName, publisher); result {
func (ts *TS) Publish(streamPath string, publisher Publisher) (result bool) {
if result = ts.InputStream.Publish(streamPath, publisher); result {
ts.TSInfo.RoomInfo = &ts.Room.RoomInfo
ts.MpegTsStream = mpegts.NewMpegTsStream(2048)
go ts.run()

View File

@@ -57,7 +57,7 @@ func (p *HLS) run(info *M3u8Info) {
lastTs := make(map[string]bool)
resp, err := client.Do(info.Req)
defer func() {
log.Printf("hls %s exit:%v", p.StreamName, err)
log.Printf("hls %s exit:%v", p.StreamPath, err)
p.Cancel()
}()
for ; err == nil && p.Err() == nil; resp, err = client.Do(info.Req) {
@@ -117,17 +117,17 @@ func (p *HLS) run(info *M3u8Info) {
tsCost.BufferLength = len(p.TsPesPktChan)
p.PesCount = tsCost.BufferLength - beginLen
} else if err != nil {
log.Printf("%s readTs:%v", p.StreamName, err)
log.Printf("%s readTs:%v", p.StreamPath, err)
}
} else if err != nil {
log.Printf("%s reqTs:%v", p.StreamName, err)
log.Printf("%s reqTs:%v", p.StreamPath, err)
}
info.M3u8Info[i] = tsCost
}
time.Sleep(time.Second * time.Duration(playlist.Target) * 2)
} else {
log.Printf("%s readM3u8:%v", p.StreamName, err)
log.Printf("%s readM3u8:%v", p.StreamPath, err)
return
}
}

View File

@@ -31,7 +31,7 @@ func init() {
func onPublish(r *Room) {
for _, v := range r.Subscribers {
if err := CheckSign(v.Sign); err != nil {
log.Printf("%s in room %s:%v", v.ID, r.StreamName, err)
log.Printf("%s in room %s:%v", v.ID, r.StreamPath, err)
v.Cancel()
}
}

View File

@@ -38,6 +38,6 @@ func run() {
func onSubscribe(s *OutputStream) {
if s.Publisher == nil {
go PullUpStream(s.StreamName)
go PullUpStream(s.StreamPath)
}
}

View File

@@ -200,7 +200,7 @@ func (conn *NetConnection) SendMessage(message string, args interface{}) error {
m.CommandName = "play"
m.TransactionId = 1
for i, v := range data {
if i == "StreamName" {
if i == "StreamPath" {
m.StreamName = v.(string)
} else if i == "Start" {
m.Start = v.(uint64)