mirror of
				https://github.com/Monibuca/plugin-record.git
				synced 2025-10-31 03:46:21 +08:00 
			
		
		
		
	适配3.0
This commit is contained in:
		
							
								
								
									
										43
									
								
								flv.go
									
									
									
									
									
								
							
							
						
						
									
										43
									
								
								flv.go
									
									
									
									
									
								
							| @@ -6,19 +6,19 @@ import ( | |||||||
| 	"path" | 	"path" | ||||||
| 	"path/filepath" | 	"path/filepath" | ||||||
|  |  | ||||||
| 	. "github.com/Monibuca/engine/v2" | 	. "github.com/Monibuca/engine/v3" | ||||||
| 	"github.com/Monibuca/engine/v2/avformat" | 	. "github.com/Monibuca/utils/v3" | ||||||
| 	"github.com/Monibuca/engine/v2/util" | 	"github.com/Monibuca/utils/v3/codec" | ||||||
| ) | ) | ||||||
|  |  | ||||||
| func getDuration(file *os.File) uint32 { | func getDuration(file *os.File) uint32 { | ||||||
| 	_, err := file.Seek(-4, io.SeekEnd) | 	_, err := file.Seek(-4, io.SeekEnd) | ||||||
| 	if err == nil { | 	if err == nil { | ||||||
| 		var tagSize uint32 | 		var tagSize uint32 | ||||||
| 		if tagSize, err = util.ReadByteToUint32(file, true); err == nil { | 		if tagSize, err = ReadByteToUint32(file, true); err == nil { | ||||||
| 			_, err = file.Seek(-int64(tagSize)-4, io.SeekEnd) | 			_, err = file.Seek(-int64(tagSize)-4, io.SeekEnd) | ||||||
| 			if err == nil { | 			if err == nil { | ||||||
| 				_, timestamp, _, err := avformat.ReadFLVTag(file) | 				_, timestamp, _, err := codec.ReadFLVTag(file) | ||||||
| 				if err == nil { | 				if err == nil { | ||||||
| 					return timestamp | 					return timestamp | ||||||
| 				} | 				} | ||||||
| @@ -35,28 +35,43 @@ func SaveFlv(streamPath string, append bool) error { | |||||||
| 		flag = flag | os.O_TRUNC | os.O_WRONLY | 		flag = flag | os.O_TRUNC | os.O_WRONLY | ||||||
| 	} | 	} | ||||||
| 	filePath := filepath.Join(config.Path, streamPath+".flv") | 	filePath := filepath.Join(config.Path, streamPath+".flv") | ||||||
| 	os.MkdirAll(path.Dir(filePath), 0775) | 	os.MkdirAll(path.Dir(filePath), 0755) | ||||||
| 	file, err := os.OpenFile(filePath, flag, 0775) | 	file, err := os.OpenFile(filePath, flag, 0755) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return err | 		return err | ||||||
| 	} | 	} | ||||||
| 	p := Subscriber{OnData: func(packet *avformat.SendPacket) error { | 	// return avformat.WriteFLVTag(file, packet) | ||||||
| 		return avformat.WriteFLVTag(file, packet) | 	p := Subscriber{ | ||||||
| 	}} | 		ID:   filePath, | ||||||
| 	p.ID = filePath | 		Type: "FlvRecord", | ||||||
| 	p.Type = "FlvRecord" | 	} | ||||||
|  |  | ||||||
| 	if append { | 	if append { | ||||||
| 		p.OffsetTime = getDuration(file) | 		p.OffsetTime = getDuration(file) | ||||||
| 		file.Seek(0, io.SeekEnd) | 		file.Seek(0, io.SeekEnd) | ||||||
| 	} else { | 	} else { | ||||||
| 		_, err = file.Write(avformat.FLVHeader) | 		_, err = file.Write(codec.FLVHeader) | ||||||
| 	} | 	} | ||||||
| 	if err == nil { | 	if err == nil { | ||||||
| 		recordings.Store(filePath, &p) | 		recordings.Store(filePath, &p) | ||||||
|  | 		if err := p.Subscribe(streamPath); err == nil { | ||||||
|  | 			at, vt := p.OriginAudioTrack, p.OriginVideoTrack | ||||||
|  | 			var aac byte | ||||||
|  | 			if at.SoundFormat == 10 { | ||||||
|  | 				aac = at.RtmpTag[0] | ||||||
|  | 			} | ||||||
|  | 			p.OnAudio = func(audio AudioPack) { | ||||||
|  | 				codec.WriteFLVTag(file, codec.FLV_TAG_TYPE_AUDIO, audio.Timestamp, audio.ToRTMPTag(aac)) | ||||||
|  | 			} | ||||||
|  | 			p.OnVideo = func(video VideoPack) { | ||||||
|  | 				codec.WriteFLVTag(file, codec.FLV_TAG_TYPE_VIDEO, video.Timestamp, video.ToRTMPTag()) | ||||||
|  | 			} | ||||||
| 			go func() { | 			go func() { | ||||||
| 			p.Subscribe(streamPath) | 				p.Play(at, vt) | ||||||
| 				file.Close() | 				file.Close() | ||||||
| 			}() | 			}() | ||||||
|  | 		} | ||||||
|  |  | ||||||
| 	} else { | 	} else { | ||||||
| 		file.Close() | 		file.Close() | ||||||
| 	} | 	} | ||||||
|   | |||||||
							
								
								
									
										8
									
								
								go.mod
									
									
									
									
									
								
							
							
						
						
									
										8
									
								
								go.mod
									
									
									
									
									
								
							| @@ -1,5 +1,9 @@ | |||||||
| module github.com/Monibuca/plugin-record | module github.com/Monibuca/plugin-record/v3 | ||||||
|  |  | ||||||
| go 1.13 | go 1.13 | ||||||
|  |  | ||||||
| require github.com/Monibuca/engine/v2 v2.0.0 | require ( | ||||||
|  | 	github.com/Monibuca/engine/v3 v3.0.0-alpha6 | ||||||
|  | 	github.com/Monibuca/utils/v3 v3.0.0-alpha5 | ||||||
|  | 	github.com/pion/rtp v1.6.2 // indirect | ||||||
|  | ) | ||||||
|   | |||||||
							
								
								
									
										49
									
								
								go.sum
									
									
									
									
									
								
							
							
						
						
									
										49
									
								
								go.sum
									
									
									
									
									
								
							| @@ -1,47 +1,28 @@ | |||||||
| github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= | github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= | ||||||
| github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= | github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= | ||||||
| github.com/Monibuca/engine v1.0.3 h1:/xwiEpqgQDAzjDb6zAwqFSZP8y0MOOVXv5aUx1os5nM= | github.com/Monibuca/engine/v3 v3.0.0-alpha6 h1:USZa+JDVJd13rb9wmX06ZxjRCrqYTAPe5wVD+0IODEE= | ||||||
| github.com/Monibuca/engine v1.0.3/go.mod h1:NjqVgtXuRSOyk3+NWgCuDf2p7TsBisjYxoEwA9uCZ38= | github.com/Monibuca/engine/v3 v3.0.0-alpha6/go.mod h1:V0/kfen6K5O/RLXHPsZj4DF/LboDZ0OqfeCfn35bWMo= | ||||||
| github.com/Monibuca/engine v1.1.1 h1:wk5qBJCssCOpeA7jyGU/oInVmFnfc9r+eT+sbjOIZfw= | github.com/Monibuca/utils/v3 v3.0.0-alpha4/go.mod h1:3xYmhQbgAZBHLyIMteUCd1va+1z/xnd72B585mCaT3c= | ||||||
| github.com/Monibuca/engine v1.1.1/go.mod h1:NjqVgtXuRSOyk3+NWgCuDf2p7TsBisjYxoEwA9uCZ38= | github.com/Monibuca/utils/v3 v3.0.0-alpha5 h1:IOyW/KJSRdRg+TPcgwkHLBynqfNQOV6p3iP7LgXEMFc= | ||||||
| github.com/Monibuca/engine v1.2.1 h1:TJmC6eZA1lR1MScWgempZLiEZD4T6aY/nn/rlQ9UdK8= | github.com/Monibuca/utils/v3 v3.0.0-alpha5/go.mod h1:3xYmhQbgAZBHLyIMteUCd1va+1z/xnd72B585mCaT3c= | ||||||
| github.com/Monibuca/engine v1.2.1/go.mod h1:WbDkXENLjcPjyjCR1Mix1GA+uAlwORkv/+8aMVrDX2g= |  | ||||||
| github.com/Monibuca/engine v1.2.2 h1:hNjsrZpOmui8lYhgCJ5ltJU8g/k0Rrdysx2tHNGGnbI= |  | ||||||
| github.com/Monibuca/engine/v2 v2.0.0-alpha2 h1:45yazqnnxEEcfHcOJGuIr1xtnBzQT6cPvhlymeZrDmA= |  | ||||||
| github.com/Monibuca/engine/v2 v2.0.0-alpha2/go.mod h1:34EYjjV15G6myuHOKaJkO7y5tJ1Arq/NfC9Weacr2mc= |  | ||||||
| github.com/Monibuca/engine/v2 v2.0.0-alpha3 h1:G1Mbq3Q0hbZuA0evrByf8qqRx/rk3lbvJa7Qp55tOsw= |  | ||||||
| github.com/Monibuca/engine/v2 v2.0.0-alpha3/go.mod h1:34EYjjV15G6myuHOKaJkO7y5tJ1Arq/NfC9Weacr2mc= |  | ||||||
| github.com/Monibuca/engine/v2 v2.0.0 h1:8FjaScrtN8QdbcxO9zZYABMC0Re3I1O1T4p94zAXYb0= |  | ||||||
| github.com/Monibuca/engine/v2 v2.0.0/go.mod h1:34EYjjV15G6myuHOKaJkO7y5tJ1Arq/NfC9Weacr2mc= |  | ||||||
| github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d h1:G0m3OIz70MZUWq3EgK3CesDbo8upS2Vm9/P3FtgI+Jk= |  | ||||||
| github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg= |  | ||||||
| github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= |  | ||||||
| github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= |  | ||||||
| github.com/funny/slab v0.0.0-20180511031532-b1fad5e5d478 h1:Db9StoJ6RZN3YttC0Pm0I4Y5izITRYch3RMbT59BYN0= | github.com/funny/slab v0.0.0-20180511031532-b1fad5e5d478 h1:Db9StoJ6RZN3YttC0Pm0I4Y5izITRYch3RMbT59BYN0= | ||||||
| github.com/funny/slab v0.0.0-20180511031532-b1fad5e5d478/go.mod h1:0j1+svBH8ABEIPdUP0AIg4qedsybnXGJBakCEw8cfoo= | github.com/funny/slab v0.0.0-20180511031532-b1fad5e5d478/go.mod h1:0j1+svBH8ABEIPdUP0AIg4qedsybnXGJBakCEw8cfoo= | ||||||
| github.com/funny/utest v0.0.0-20161029064919-43870a374500 h1:Z0r1CZnoIWFB/Uiwh1BU5FYmuFe6L5NPi6XWQEmsTRg= | github.com/funny/utest v0.0.0-20161029064919-43870a374500 h1:Z0r1CZnoIWFB/Uiwh1BU5FYmuFe6L5NPi6XWQEmsTRg= | ||||||
| github.com/funny/utest v0.0.0-20161029064919-43870a374500/go.mod h1:mUn39tBov9jKnTWV1RlOYoNzxdBFHiSzXWdY1FoNGGg= | github.com/funny/utest v0.0.0-20161029064919-43870a374500/go.mod h1:mUn39tBov9jKnTWV1RlOYoNzxdBFHiSzXWdY1FoNGGg= | ||||||
| github.com/go-ole/go-ole v1.2.4 h1:nNBDSCOigTSiarFpYE9J/KtEA1IOW4CNeqT9TQDqCxI= | github.com/logrusorgru/aurora v2.0.3+incompatible h1:tOpm7WcpBTn4fjmVfgpQq0EfczGlG91VSDkswnjF5A8= | ||||||
| github.com/go-ole/go-ole v1.2.4/go.mod h1:XCwSNxSkXRo4vlyPy93sltvi/qJq0jqQhjqQNIwKuxM= | github.com/logrusorgru/aurora v2.0.3+incompatible/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4= | ||||||
| github.com/logrusorgru/aurora v0.0.0-20200102142835-e9ef32dff381 h1:bqDmpDG49ZRnB5PcgP0RXtQvnMSgIF14M7CBd2shtXs= | github.com/mattn/go-colorable v0.1.8 h1:c1ghPdyEDarC70ftn0y+A/Ee++9zz8ljHG1b13eJ0s8= | ||||||
| github.com/logrusorgru/aurora v0.0.0-20200102142835-e9ef32dff381/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4= | github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= | ||||||
| github.com/mattn/go-colorable v0.1.6 h1:6Su7aK7lXmJ/U79bYtBjLNaha4Fs1Rg9plHpcH+vvnE= |  | ||||||
| github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= |  | ||||||
| github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY= | github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY= | ||||||
| github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= | github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= | ||||||
|  | github.com/pion/randutil v0.1.0 h1:CFG1UdESneORglEsnimhUjf33Rwjubwj6xfiOXBa3mA= | ||||||
|  | github.com/pion/randutil v0.1.0/go.mod h1:XcJrSMMbbMRhASFVOlj/5hQial/Y8oH/HVo7TBZq+j8= | ||||||
|  | github.com/pion/rtp v1.6.2 h1:iGBerLX6JiDjB9NXuaPzHyxHFG9JsIEdgwTC0lp5n/U= | ||||||
|  | github.com/pion/rtp v1.6.2/go.mod h1:bDb5n+BFZxXx0Ea7E5qe+klMuqiBrP+w8XSjiWtCUko= | ||||||
| github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= | github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= | ||||||
| github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= | github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= | ||||||
| github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= | golang.org/x/sync v0.0.0-20201207232520-09787c993a3a h1:DcqTD9SDLc+1P/r1EmRBwnVsrOwW+kk2vWf9n+1sGhs= | ||||||
| github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= | golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= | ||||||
| github.com/shirou/gopsutil v2.20.1+incompatible h1:oIq9Cq4i84Hk8uQAUOG3eNdI/29hBawGrD5YRl6JRDY= |  | ||||||
| github.com/shirou/gopsutil v2.20.1+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= |  | ||||||
| github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= |  | ||||||
| github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4= |  | ||||||
| github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= |  | ||||||
| golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||||||
| golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae h1:/WDfKMnPU+m5M4xB+6x4kaepxRw6jWvR5iDRdvjHgy8= | golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae h1:/WDfKMnPU+m5M4xB+6x4kaepxRw6jWvR5iDRdvjHgy8= | ||||||
| golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||||||
| gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= |  | ||||||
| gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= |  | ||||||
| gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= |  | ||||||
| gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= |  | ||||||
|   | |||||||
							
								
								
									
										31
									
								
								main.go
									
									
									
									
									
								
							
							
						
						
									
										31
									
								
								main.go
									
									
									
									
									
								
							| @@ -9,8 +9,8 @@ import ( | |||||||
| 	"strings" | 	"strings" | ||||||
| 	"sync" | 	"sync" | ||||||
|  |  | ||||||
| 	. "github.com/Monibuca/engine/v2" | 	. "github.com/Monibuca/engine/v3" | ||||||
| 	. "github.com/Monibuca/engine/v2/util" | 	. "github.com/Monibuca/utils/v3" | ||||||
| ) | ) | ||||||
|  |  | ||||||
| var config struct { | var config struct { | ||||||
| @@ -29,7 +29,6 @@ type FlvFileInfo struct { | |||||||
| func init() { | func init() { | ||||||
| 	InstallPlugin(&PluginConfig{ | 	InstallPlugin(&PluginConfig{ | ||||||
| 		Name:   "Record", | 		Name:   "Record", | ||||||
| 		Type:   PLUGIN_SUBSCRIBER, |  | ||||||
| 		Config: &config, | 		Config: &config, | ||||||
| 		Run:    run, | 		Run:    run, | ||||||
| 		HotConfig: map[string]func(interface{}){ | 		HotConfig: map[string]func(interface{}){ | ||||||
| @@ -43,10 +42,10 @@ func init() { | |||||||
| 	}) | 	}) | ||||||
| } | } | ||||||
| func run() { | func run() { | ||||||
| 	OnSubscribeHooks.AddHook(onSubscribe) | 	go AddHook(HOOK_SUBSCRIBE, onSubscribe) | ||||||
| 	OnPublishHooks.AddHook(onPublish) | 	go AddHook(HOOK_PUBLISH, onPublish) | ||||||
| 	os.MkdirAll(config.Path, 0755) | 	os.MkdirAll(config.Path, 0755) | ||||||
| 	http.HandleFunc("/record/flv/list", func(writer http.ResponseWriter, r *http.Request) { | 	http.HandleFunc("/api/record/flv/list", func(writer http.ResponseWriter, r *http.Request) { | ||||||
| 		if files, err := tree(config.Path, 0); err == nil { | 		if files, err := tree(config.Path, 0); err == nil { | ||||||
| 			var bytes []byte | 			var bytes []byte | ||||||
| 			if bytes, err = json.Marshal(files); err == nil { | 			if bytes, err = json.Marshal(files); err == nil { | ||||||
| @@ -58,7 +57,7 @@ func run() { | |||||||
| 			writer.Write([]byte("{\"err\":\"" + err.Error() + "\"}")) | 			writer.Write([]byte("{\"err\":\"" + err.Error() + "\"}")) | ||||||
| 		} | 		} | ||||||
| 	}) | 	}) | ||||||
| 	http.HandleFunc("/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") == "true"); err != nil { | 			if err := SaveFlv(streamPath, r.URL.Query().Get("append") == "true"); err != nil { | ||||||
| 				writer.Write([]byte(err.Error())) | 				writer.Write([]byte(err.Error())) | ||||||
| @@ -70,8 +69,8 @@ func run() { | |||||||
| 		} | 		} | ||||||
| 	}) | 	}) | ||||||
|  |  | ||||||
| 	http.HandleFunc("/record/flv/stop", func(w http.ResponseWriter, r *http.Request) { | 	http.HandleFunc("/api/record/flv/stop", func(w http.ResponseWriter, r *http.Request) { | ||||||
| 		w.Header().Set("Access-Control-Allow-Origin", "*") | 		CORS(w, r) | ||||||
| 		if streamPath := r.URL.Query().Get("streamPath"); streamPath != "" { | 		if streamPath := r.URL.Query().Get("streamPath"); streamPath != "" { | ||||||
| 			filePath := filepath.Join(config.Path, streamPath+".flv") | 			filePath := filepath.Join(config.Path, streamPath+".flv") | ||||||
| 			if stream, ok := recordings.Load(filePath); ok { | 			if stream, ok := recordings.Load(filePath); ok { | ||||||
| @@ -85,7 +84,7 @@ func run() { | |||||||
| 			w.Write([]byte("no such stream")) | 			w.Write([]byte("no such stream")) | ||||||
| 		} | 		} | ||||||
| 	}) | 	}) | ||||||
| 	http.HandleFunc("/record/flv/play", func(w http.ResponseWriter, r *http.Request) { | 	http.HandleFunc("/api/record/flv/play", func(w http.ResponseWriter, r *http.Request) { | ||||||
| 		if streamPath := r.URL.Query().Get("streamPath"); streamPath != "" { | 		if streamPath := r.URL.Query().Get("streamPath"); streamPath != "" { | ||||||
| 			if err := PublishFlvFile(streamPath); err != nil { | 			if err := PublishFlvFile(streamPath); err != nil { | ||||||
| 				w.Write([]byte(err.Error())) | 				w.Write([]byte(err.Error())) | ||||||
| @@ -96,7 +95,7 @@ func run() { | |||||||
| 			w.Write([]byte("no streamPath")) | 			w.Write([]byte("no streamPath")) | ||||||
| 		} | 		} | ||||||
| 	}) | 	}) | ||||||
| 	http.HandleFunc("/record/flv/delete", func(w http.ResponseWriter, r *http.Request) { | 	http.HandleFunc("/api/record/flv/delete", func(w http.ResponseWriter, r *http.Request) { | ||||||
| 		if streamPath := r.URL.Query().Get("streamPath"); streamPath != "" { | 		if streamPath := r.URL.Query().Get("streamPath"); streamPath != "" { | ||||||
| 			filePath := filepath.Join(config.Path, streamPath+".flv") | 			filePath := filepath.Join(config.Path, streamPath+".flv") | ||||||
| 			if Exist(filePath) { | 			if Exist(filePath) { | ||||||
| @@ -113,17 +112,19 @@ func run() { | |||||||
| 		} | 		} | ||||||
| 	}) | 	}) | ||||||
| } | } | ||||||
| func onSubscribe(s *Subscriber) { | func onSubscribe(v interface{}) { | ||||||
|  | 	s:=v.(*Subscriber) | ||||||
| 	if config.AutoPublish { | 	if config.AutoPublish { | ||||||
| 		filePath := filepath.Join(config.Path, s.StreamPath+".flv") | 		filePath := filepath.Join(config.Path, s.StreamPath+".flv") | ||||||
| 		if s.Publisher == nil && Exist(filePath) { | 		if s.Publisher == nil && Exist(filePath) { | ||||||
| 			go PublishFlvFile(s.StreamPath) | 			PublishFlvFile(s.StreamPath) | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| func onPublish(p *Stream) { | func onPublish(v interface{}) { | ||||||
|  | 	p := v.(*Stream) | ||||||
| 	if config.AutoRecord { | 	if config.AutoRecord { | ||||||
| 		go SaveFlv(p.StreamPath, false) | 		SaveFlv(p.StreamPath, false) | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										23
									
								
								publisher.go
									
									
									
									
									
								
							
							
						
						
									
										23
									
								
								publisher.go
									
									
									
									
									
								
							| @@ -7,8 +7,9 @@ import ( | |||||||
| 	"path/filepath" | 	"path/filepath" | ||||||
| 	"time" | 	"time" | ||||||
|  |  | ||||||
| 	. "github.com/Monibuca/engine/v2" | 	. "github.com/Monibuca/engine/v3" | ||||||
| 	"github.com/Monibuca/engine/v2/avformat" | 	. "github.com/Monibuca/utils/v3" | ||||||
|  | 	"github.com/Monibuca/utils/v3/codec" | ||||||
| ) | ) | ||||||
|  |  | ||||||
| type FlvFile struct { | type FlvFile struct { | ||||||
| @@ -19,25 +20,27 @@ func PublishFlvFile(streamPath string) error { | |||||||
| 	flvPath := filepath.Join(config.Path, streamPath+".flv") | 	flvPath := filepath.Join(config.Path, streamPath+".flv") | ||||||
| 	os.MkdirAll(filepath.Dir(flvPath), 0755) | 	os.MkdirAll(filepath.Dir(flvPath), 0755) | ||||||
| 	if file, err := os.Open(flvPath); err == nil { | 	if file, err := os.Open(flvPath); err == nil { | ||||||
| 		stream := FlvFile{} | 		var stream FlvFile | ||||||
| 		if stream.Publish(streamPath) { | 		if stream.Publish(streamPath) { | ||||||
| 			stream.Type = "FlvFile" | 			stream.Type = "FlvFile" | ||||||
| 			defer stream.Close() | 			defer stream.Close() | ||||||
| 			stream.UseTimestamp = true | 			file.Seek(int64(len(codec.FLVHeader)), io.SeekStart) | ||||||
| 			file.Seek(int64(len(avformat.FLVHeader)), io.SeekStart) |  | ||||||
| 			var lastTime uint32 | 			var lastTime uint32 | ||||||
|  | 			at := NewAudioTrack() | ||||||
|  | 			vt := NewVideoTrack() | ||||||
|  | 			stream.SetOriginAT(at) | ||||||
| 			for { | 			for { | ||||||
| 				if t, timestamp, payload, err := avformat.ReadFLVTag(file); err == nil { | 				if t, timestamp, payload, err := codec.ReadFLVTag(file); err == nil { | ||||||
| 					switch t { | 					switch t { | ||||||
| 					case avformat.FLV_TAG_TYPE_AUDIO: | 					case codec.FLV_TAG_TYPE_AUDIO: | ||||||
| 						stream.PushAudio(timestamp, payload) | 						at.Push(timestamp, payload) | ||||||
| 					case avformat.FLV_TAG_TYPE_VIDEO: | 					case codec.FLV_TAG_TYPE_VIDEO: | ||||||
| 						if timestamp != 0 { | 						if timestamp != 0 { | ||||||
| 							if lastTime == 0 { | 							if lastTime == 0 { | ||||||
| 								lastTime = timestamp | 								lastTime = timestamp | ||||||
| 							} | 							} | ||||||
| 						} | 						} | ||||||
| 						stream.PushVideo(timestamp, payload) | 						vt.Push(VideoPack{Timestamp: timestamp, CompositionTime: BigEndian.Uint24(payload[2:5]), Payload: payload[5:]}) | ||||||
| 						time.Sleep(time.Duration(timestamp-lastTime) * time.Millisecond) | 						time.Sleep(time.Duration(timestamp-lastTime) * time.Millisecond) | ||||||
| 						lastTime = timestamp | 						lastTime = timestamp | ||||||
| 					} | 					} | ||||||
|   | |||||||
							
								
								
									
										19
									
								
								ui/dist/demo.html
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										19
									
								
								ui/dist/demo.html
									
									
									
									
										vendored
									
									
								
							| @@ -1,19 +0,0 @@ | |||||||
| <meta charset="utf-8"> |  | ||||||
| <title>plugin-record demo</title> |  | ||||||
| <script src="https://unpkg.com/vue"></script> |  | ||||||
| <script src="./plugin-record.umd.js"></script> |  | ||||||
|  |  | ||||||
| <link rel="stylesheet" href="./plugin-record.css"> |  | ||||||
|  |  | ||||||
|  |  | ||||||
| <div id="app"> |  | ||||||
|   <demo></demo> |  | ||||||
| </div> |  | ||||||
|  |  | ||||||
| <script> |  | ||||||
| new Vue({ |  | ||||||
|   components: { |  | ||||||
|     demo: plugin-record |  | ||||||
|   } |  | ||||||
| }).$mount('#app') |  | ||||||
| </script> |  | ||||||
							
								
								
									
										524
									
								
								ui/dist/plugin-record.common.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										524
									
								
								ui/dist/plugin-record.common.js
									
									
									
									
										vendored
									
									
								
							| @@ -1,524 +0,0 @@ | |||||||
| module.exports = |  | ||||||
| /******/ (function(modules) { // webpackBootstrap |  | ||||||
| /******/ 	// The module cache |  | ||||||
| /******/ 	var installedModules = {}; |  | ||||||
| /******/ |  | ||||||
| /******/ 	// The require function |  | ||||||
| /******/ 	function __webpack_require__(moduleId) { |  | ||||||
| /******/ |  | ||||||
| /******/ 		// Check if module is in cache |  | ||||||
| /******/ 		if(installedModules[moduleId]) { |  | ||||||
| /******/ 			return installedModules[moduleId].exports; |  | ||||||
| /******/ 		} |  | ||||||
| /******/ 		// Create a new module (and put it into the cache) |  | ||||||
| /******/ 		var module = installedModules[moduleId] = { |  | ||||||
| /******/ 			i: moduleId, |  | ||||||
| /******/ 			l: false, |  | ||||||
| /******/ 			exports: {} |  | ||||||
| /******/ 		}; |  | ||||||
| /******/ |  | ||||||
| /******/ 		// Execute the module function |  | ||||||
| /******/ 		modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); |  | ||||||
| /******/ |  | ||||||
| /******/ 		// Flag the module as loaded |  | ||||||
| /******/ 		module.l = true; |  | ||||||
| /******/ |  | ||||||
| /******/ 		// Return the exports of the module |  | ||||||
| /******/ 		return module.exports; |  | ||||||
| /******/ 	} |  | ||||||
| /******/ |  | ||||||
| /******/ |  | ||||||
| /******/ 	// expose the modules object (__webpack_modules__) |  | ||||||
| /******/ 	__webpack_require__.m = modules; |  | ||||||
| /******/ |  | ||||||
| /******/ 	// expose the module cache |  | ||||||
| /******/ 	__webpack_require__.c = installedModules; |  | ||||||
| /******/ |  | ||||||
| /******/ 	// define getter function for harmony exports |  | ||||||
| /******/ 	__webpack_require__.d = function(exports, name, getter) { |  | ||||||
| /******/ 		if(!__webpack_require__.o(exports, name)) { |  | ||||||
| /******/ 			Object.defineProperty(exports, name, { enumerable: true, get: getter }); |  | ||||||
| /******/ 		} |  | ||||||
| /******/ 	}; |  | ||||||
| /******/ |  | ||||||
| /******/ 	// define __esModule on exports |  | ||||||
| /******/ 	__webpack_require__.r = function(exports) { |  | ||||||
| /******/ 		if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { |  | ||||||
| /******/ 			Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); |  | ||||||
| /******/ 		} |  | ||||||
| /******/ 		Object.defineProperty(exports, '__esModule', { value: true }); |  | ||||||
| /******/ 	}; |  | ||||||
| /******/ |  | ||||||
| /******/ 	// create a fake namespace object |  | ||||||
| /******/ 	// mode & 1: value is a module id, require it |  | ||||||
| /******/ 	// mode & 2: merge all properties of value into the ns |  | ||||||
| /******/ 	// mode & 4: return value when already ns object |  | ||||||
| /******/ 	// mode & 8|1: behave like require |  | ||||||
| /******/ 	__webpack_require__.t = function(value, mode) { |  | ||||||
| /******/ 		if(mode & 1) value = __webpack_require__(value); |  | ||||||
| /******/ 		if(mode & 8) return value; |  | ||||||
| /******/ 		if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value; |  | ||||||
| /******/ 		var ns = Object.create(null); |  | ||||||
| /******/ 		__webpack_require__.r(ns); |  | ||||||
| /******/ 		Object.defineProperty(ns, 'default', { enumerable: true, value: value }); |  | ||||||
| /******/ 		if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key)); |  | ||||||
| /******/ 		return ns; |  | ||||||
| /******/ 	}; |  | ||||||
| /******/ |  | ||||||
| /******/ 	// getDefaultExport function for compatibility with non-harmony modules |  | ||||||
| /******/ 	__webpack_require__.n = function(module) { |  | ||||||
| /******/ 		var getter = module && module.__esModule ? |  | ||||||
| /******/ 			function getDefault() { return module['default']; } : |  | ||||||
| /******/ 			function getModuleExports() { return module; }; |  | ||||||
| /******/ 		__webpack_require__.d(getter, 'a', getter); |  | ||||||
| /******/ 		return getter; |  | ||||||
| /******/ 	}; |  | ||||||
| /******/ |  | ||||||
| /******/ 	// Object.prototype.hasOwnProperty.call |  | ||||||
| /******/ 	__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; |  | ||||||
| /******/ |  | ||||||
| /******/ 	// __webpack_public_path__ |  | ||||||
| /******/ 	__webpack_require__.p = ""; |  | ||||||
| /******/ |  | ||||||
| /******/ |  | ||||||
| /******/ 	// Load entry module and return exports |  | ||||||
| /******/ 	return __webpack_require__(__webpack_require__.s = "fb15"); |  | ||||||
| /******/ }) |  | ||||||
| /************************************************************************/ |  | ||||||
| /******/ ({ |  | ||||||
|  |  | ||||||
| /***/ "5941": |  | ||||||
| /***/ (function(module, exports, __webpack_require__) { |  | ||||||
|  |  | ||||||
| // extracted by mini-css-extract-plugin |  | ||||||
|  |  | ||||||
| /***/ }), |  | ||||||
|  |  | ||||||
| /***/ "f6fd": |  | ||||||
| /***/ (function(module, exports) { |  | ||||||
|  |  | ||||||
| // document.currentScript polyfill by Adam Miller |  | ||||||
|  |  | ||||||
| // MIT license |  | ||||||
|  |  | ||||||
| (function(document){ |  | ||||||
|   var currentScript = "currentScript", |  | ||||||
|       scripts = document.getElementsByTagName('script'); // Live NodeList collection |  | ||||||
|  |  | ||||||
|   // If browser needs currentScript polyfill, add get currentScript() to the document object |  | ||||||
|   if (!(currentScript in document)) { |  | ||||||
|     Object.defineProperty(document, currentScript, { |  | ||||||
|       get: function(){ |  | ||||||
|  |  | ||||||
|         // IE 6-10 supports script readyState |  | ||||||
|         // IE 10+ support stack trace |  | ||||||
|         try { throw new Error(); } |  | ||||||
|         catch (err) { |  | ||||||
|  |  | ||||||
|           // Find the second match for the "at" string to get file src url from stack. |  | ||||||
|           // Specifically works with the format of stack traces in IE. |  | ||||||
|           var i, res = ((/.*at [^\(]*\((.*):.+:.+\)$/ig).exec(err.stack) || [false])[1]; |  | ||||||
|  |  | ||||||
|           // For all scripts on the page, if src matches or if ready state is interactive, return the script tag |  | ||||||
|           for(i in scripts){ |  | ||||||
|             if(scripts[i].src == res || scripts[i].readyState == "interactive"){ |  | ||||||
|               return scripts[i]; |  | ||||||
|             } |  | ||||||
|           } |  | ||||||
|  |  | ||||||
|           // If no match, return null |  | ||||||
|           return null; |  | ||||||
|         } |  | ||||||
|       } |  | ||||||
|     }); |  | ||||||
|   } |  | ||||||
| })(document); |  | ||||||
|  |  | ||||||
|  |  | ||||||
| /***/ }), |  | ||||||
|  |  | ||||||
| /***/ "f87e": |  | ||||||
| /***/ (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_015b8bdf_scoped_true_lang_css___WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__("5941"); |  | ||||||
| /* 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_015b8bdf_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_015b8bdf_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_015b8bdf_scoped_true_lang_css___WEBPACK_IMPORTED_MODULE_0___default.a);  |  | ||||||
|  |  | ||||||
| /***/ }), |  | ||||||
|  |  | ||||||
| /***/ "fb15": |  | ||||||
| /***/ (function(module, __webpack_exports__, __webpack_require__) { |  | ||||||
|  |  | ||||||
| "use strict"; |  | ||||||
| // ESM COMPAT FLAG |  | ||||||
| __webpack_require__.r(__webpack_exports__); |  | ||||||
|  |  | ||||||
| // CONCATENATED MODULE: ./node_modules/@vue/cli-service/lib/commands/build/setPublicPath.js |  | ||||||
| // This file is imported into lib/wc client bundles. |  | ||||||
|  |  | ||||||
| if (typeof window !== 'undefined') { |  | ||||||
|   if (true) { |  | ||||||
|     __webpack_require__("f6fd") |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   var i |  | ||||||
|   if ((i = window.document.currentScript) && (i = i.src.match(/(.+\/)[^/]+\.js(\?.*)?$/))) { |  | ||||||
|     __webpack_require__.p = i[1] // eslint-disable-line |  | ||||||
|   } |  | ||||||
| } |  | ||||||
|  |  | ||||||
| // 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=015b8bdf&scoped=true& |  | ||||||
| var render = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('div',[(_vm.$parent.titleTabActive==1)?_c('Records',{ref:"recordsPanel"}):_c('stream-table',{scopedSlots:_vm._u([{key:"default",fn:function(ref){ |  | ||||||
| var stream = ref.row; |  | ||||||
| return [(_vm.isRecording(stream))?_c('m-button',{attrs:{"blink":""},on:{"click":function($event){return _vm.stopRecord(stream)}}},[_vm._v("正在录制")]):_c('m-button',{on:{"click":function($event){return _vm.record(stream)}}},[_vm._v("录制")])]}}])})],1)} |  | ||||||
| var staticRenderFns = [] |  | ||||||
|  |  | ||||||
|  |  | ||||||
| // CONCATENATED MODULE: ./src/App.vue?vue&type=template&id=015b8bdf&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=675e088d& |  | ||||||
| var Recordsvue_type_template_id_675e088d_render = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('mu-data-table',{attrs:{"data":_vm.data,"columns":_vm.columns},scopedSlots:_vm._u([{key:"default",fn:function(ref){ |  | ||||||
| var row = ref.row; |  | ||||||
| return [_c('td',[_vm._v(_vm._s(row.Path))]),_c('td',[_vm._v(_vm._s(_vm.unitFormat(row.Size)))]),_c('td',[_vm._v(_vm._s(_vm.toDurationStr(row.Duration)))]),_c('td',[_c('mu-button',{attrs:{"icon":"","small":""},on:{"click":function($event){return _vm.play(row)}}},[_c('mu-icon',{attrs:{"value":"play_arrow"}})],1),_c('mu-button',{attrs:{"icon":"","small":""},on:{"click":function($event){return _vm.deleteFlv(row)}}},[_c('mu-icon',{attrs:{"value":"delete_forever"}})],1)],1)]}}])})} |  | ||||||
| var Recordsvue_type_template_id_675e088d_staticRenderFns = [] |  | ||||||
|  |  | ||||||
|  |  | ||||||
| // CONCATENATED MODULE: ./src/components/Records.vue?vue&type=template&id=675e088d& |  | ||||||
|  |  | ||||||
| // CONCATENATED MODULE: ./node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/vue-loader/lib??vue-loader-options!./src/components/Records.vue?vue&type=script&lang=js& |  | ||||||
| // |  | ||||||
| // |  | ||||||
| // |  | ||||||
| // |  | ||||||
| // |  | ||||||
| // |  | ||||||
| // |  | ||||||
| // |  | ||||||
| // |  | ||||||
| // |  | ||||||
| // |  | ||||||
| // |  | ||||||
| // |  | ||||||
| // |  | ||||||
| // |  | ||||||
| // |  | ||||||
| // |  | ||||||
| // |  | ||||||
|  |  | ||||||
| /* harmony default export */ var Recordsvue_type_script_lang_js_ = ({ |  | ||||||
|     data() { |  | ||||||
|         return { |  | ||||||
|             data: [], |  | ||||||
|             columns:[ |  | ||||||
|                 { |  | ||||||
|                     title:"文件路径" |  | ||||||
|                 },{ |  | ||||||
|                     title:"大小" |  | ||||||
|                 },{ |  | ||||||
|                     title:"时长" |  | ||||||
|                 },{title:"操作"} |  | ||||||
|             ] |  | ||||||
|         }; |  | ||||||
|     }, |  | ||||||
|     methods: { |  | ||||||
|         play(item) { |  | ||||||
|             this.ajax.get( |  | ||||||
|                 "/record/flv/play", |  | ||||||
|                 { streamPath: item.Path.replace(".flv", "") }, |  | ||||||
|                 x => { |  | ||||||
|                     if (x == "success") { |  | ||||||
|                         this.ajax.getJSON("/record/flv/list", x => this.data = x); |  | ||||||
|                         this.$toast.success("开始发布"); |  | ||||||
|                     } else { |  | ||||||
|                         this.$toast.error(x); |  | ||||||
|                     } |  | ||||||
|                 } |  | ||||||
|             ); |  | ||||||
|         }, |  | ||||||
|         deleteFlv(item) { |  | ||||||
|             this.$confirm("是否删除Flv文件", "提示").then(result => { |  | ||||||
|                 if (result) { |  | ||||||
|                     return this.ajax.get( |  | ||||||
|                         "/record/flv/delete", |  | ||||||
|                         { streamPath: item.Path.replace(".flv", "") }, |  | ||||||
|                         x => { |  | ||||||
|                             if (x == "success") { |  | ||||||
|                                 this.$toast.success("删除成功"); |  | ||||||
|                             } else { |  | ||||||
|                                 this.$toast.error(x); |  | ||||||
|                             } |  | ||||||
|                         } |  | ||||||
|                     ); |  | ||||||
|                 } |  | ||||||
|             }); |  | ||||||
|         }, |  | ||||||
|         toDurationStr(value) { |  | ||||||
|             if (value > 1000) { |  | ||||||
|                 let s = value / 1000; |  | ||||||
|                 if (s > 60) { |  | ||||||
|                     s = s | 0; |  | ||||||
|                     let min = (s / 60) >> 0; |  | ||||||
|                     if (min > 60) { |  | ||||||
|                         let hour = (min / 60) >> 0; |  | ||||||
|                         return hour + "hour" + (min % 60) + "min"; |  | ||||||
|                     } else { |  | ||||||
|                         return min + "min" + (s % 60) + "s"; |  | ||||||
|                     } |  | ||||||
|                 } else { |  | ||||||
|                     return s.toFixed(3) + "s"; |  | ||||||
|                 } |  | ||||||
|             } else { |  | ||||||
|                 return value + "ms"; |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|     }, |  | ||||||
|     mounted() { |  | ||||||
|         this.ajax.getJSON("/record/flv/list", x => this.data = x); |  | ||||||
|     } |  | ||||||
| }); |  | ||||||
|  |  | ||||||
| // CONCATENATED MODULE: ./src/components/Records.vue?vue&type=script&lang=js& |  | ||||||
|  /* harmony default export */ var components_Recordsvue_type_script_lang_js_ = (Recordsvue_type_script_lang_js_);  |  | ||||||
| // CONCATENATED MODULE: ./node_modules/vue-loader/lib/runtime/componentNormalizer.js |  | ||||||
| /* globals __VUE_SSR_CONTEXT__ */ |  | ||||||
|  |  | ||||||
| // IMPORTANT: Do NOT use ES2015 features in this file (except for modules). |  | ||||||
| // This module is a runtime utility for cleaner component module output and will |  | ||||||
| // be included in the final webpack user bundle. |  | ||||||
|  |  | ||||||
| function normalizeComponent ( |  | ||||||
|   scriptExports, |  | ||||||
|   render, |  | ||||||
|   staticRenderFns, |  | ||||||
|   functionalTemplate, |  | ||||||
|   injectStyles, |  | ||||||
|   scopeId, |  | ||||||
|   moduleIdentifier, /* server only */ |  | ||||||
|   shadowMode /* vue-cli only */ |  | ||||||
| ) { |  | ||||||
|   // Vue.extend constructor export interop |  | ||||||
|   var options = typeof scriptExports === 'function' |  | ||||||
|     ? scriptExports.options |  | ||||||
|     : scriptExports |  | ||||||
|  |  | ||||||
|   // render functions |  | ||||||
|   if (render) { |  | ||||||
|     options.render = render |  | ||||||
|     options.staticRenderFns = staticRenderFns |  | ||||||
|     options._compiled = true |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   // functional template |  | ||||||
|   if (functionalTemplate) { |  | ||||||
|     options.functional = true |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   // scopedId |  | ||||||
|   if (scopeId) { |  | ||||||
|     options._scopeId = 'data-v-' + scopeId |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   var hook |  | ||||||
|   if (moduleIdentifier) { // server build |  | ||||||
|     hook = function (context) { |  | ||||||
|       // 2.3 injection |  | ||||||
|       context = |  | ||||||
|         context || // cached call |  | ||||||
|         (this.$vnode && this.$vnode.ssrContext) || // stateful |  | ||||||
|         (this.parent && this.parent.$vnode && this.parent.$vnode.ssrContext) // functional |  | ||||||
|       // 2.2 with runInNewContext: true |  | ||||||
|       if (!context && typeof __VUE_SSR_CONTEXT__ !== 'undefined') { |  | ||||||
|         context = __VUE_SSR_CONTEXT__ |  | ||||||
|       } |  | ||||||
|       // inject component styles |  | ||||||
|       if (injectStyles) { |  | ||||||
|         injectStyles.call(this, context) |  | ||||||
|       } |  | ||||||
|       // register component module identifier for async chunk inferrence |  | ||||||
|       if (context && context._registeredComponents) { |  | ||||||
|         context._registeredComponents.add(moduleIdentifier) |  | ||||||
|       } |  | ||||||
|     } |  | ||||||
|     // used by ssr in case component is cached and beforeCreate |  | ||||||
|     // never gets called |  | ||||||
|     options._ssrRegister = hook |  | ||||||
|   } else if (injectStyles) { |  | ||||||
|     hook = shadowMode |  | ||||||
|       ? function () { injectStyles.call(this, this.$root.$options.shadowRoot) } |  | ||||||
|       : injectStyles |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   if (hook) { |  | ||||||
|     if (options.functional) { |  | ||||||
|       // for template-only hot-reload because in that case the render fn doesn't |  | ||||||
|       // go through the normalizer |  | ||||||
|       options._injectStyles = hook |  | ||||||
|       // register for functional component in vue file |  | ||||||
|       var originalRender = options.render |  | ||||||
|       options.render = function renderWithStyleInjection (h, context) { |  | ||||||
|         hook.call(context) |  | ||||||
|         return originalRender(h, context) |  | ||||||
|       } |  | ||||||
|     } else { |  | ||||||
|       // inject component registration as beforeCreate hook |  | ||||||
|       var existing = options.beforeCreate |  | ||||||
|       options.beforeCreate = existing |  | ||||||
|         ? [].concat(existing, hook) |  | ||||||
|         : [hook] |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   return { |  | ||||||
|     exports: scriptExports, |  | ||||||
|     options: options |  | ||||||
|   } |  | ||||||
| } |  | ||||||
|  |  | ||||||
| // CONCATENATED MODULE: ./src/components/Records.vue |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
| /* normalize component */ |  | ||||||
|  |  | ||||||
| var component = normalizeComponent( |  | ||||||
|   components_Recordsvue_type_script_lang_js_, |  | ||||||
|   Recordsvue_type_template_id_675e088d_render, |  | ||||||
|   Recordsvue_type_template_id_675e088d_staticRenderFns, |  | ||||||
|   false, |  | ||||||
|   null, |  | ||||||
|   null, |  | ||||||
|   null |  | ||||||
|    |  | ||||||
| ) |  | ||||||
|  |  | ||||||
| /* harmony default export */ var Records = (component.exports); |  | ||||||
| // CONCATENATED MODULE: ./node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/vue-loader/lib??vue-loader-options!./src/App.vue?vue&type=script&lang=js& |  | ||||||
| // |  | ||||||
| // |  | ||||||
| // |  | ||||||
| // |  | ||||||
| // |  | ||||||
| // |  | ||||||
| // |  | ||||||
| // |  | ||||||
| // |  | ||||||
| // |  | ||||||
| // |  | ||||||
| // |  | ||||||
|  |  | ||||||
|  |  | ||||||
| /* harmony default export */ var Appvue_type_script_lang_js_ = ({ |  | ||||||
|     components: { |  | ||||||
|         Records: Records |  | ||||||
|     }, |  | ||||||
|     data() { |  | ||||||
|         return {}; |  | ||||||
|     }, |  | ||||||
|     methods: { |  | ||||||
|         record(item) { |  | ||||||
|             let append = false; |  | ||||||
|             this.$confirm( |  | ||||||
|                 h => |  | ||||||
|                     h("mu-switch", { |  | ||||||
|                         props: { |  | ||||||
|                             label: "追加模式" |  | ||||||
|                         }, |  | ||||||
|                         on: { |  | ||||||
|                             change(value) { |  | ||||||
|                                 append = value; |  | ||||||
|                             } |  | ||||||
|                         } |  | ||||||
|                     }), |  | ||||||
|                 "是否开始录制" |  | ||||||
|             ).then(result => { |  | ||||||
|                 if (result) { |  | ||||||
|                     this.ajax.get( |  | ||||||
|                         "/record/flv?append=" + append, |  | ||||||
|                         { streamPath: item.StreamPath }, |  | ||||||
|                         x => { |  | ||||||
|                             if (x == "success") { |  | ||||||
|                                 this.$toast.success( |  | ||||||
|                                     "开始录制" + (append ? "(追加模式)" : "") |  | ||||||
|                                 ); |  | ||||||
|                             } else { |  | ||||||
|                                 this.$toast.error(x); |  | ||||||
|                             } |  | ||||||
|                         } |  | ||||||
|                     ); |  | ||||||
|                 } |  | ||||||
|             }); |  | ||||||
|         }, |  | ||||||
|         stopRecord(item) { |  | ||||||
|             this.$confirm("是否停止录制", "提示").then(result => { |  | ||||||
|                 if(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") |  | ||||||
|             ); |  | ||||||
|         } |  | ||||||
|     }, |  | ||||||
|     mounted() { |  | ||||||
|         this.$parent.titleTabs = ["StreamList", "录制的视频"]; |  | ||||||
|     } |  | ||||||
| }); |  | ||||||
|  |  | ||||||
| // 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&id=015b8bdf&scoped=true&lang=css& |  | ||||||
| var Appvue_type_style_index_0_id_015b8bdf_scoped_true_lang_css_ = __webpack_require__("f87e"); |  | ||||||
|  |  | ||||||
| // CONCATENATED MODULE: ./src/App.vue |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
| /* normalize component */ |  | ||||||
|  |  | ||||||
| var App_component = normalizeComponent( |  | ||||||
|   src_Appvue_type_script_lang_js_, |  | ||||||
|   render, |  | ||||||
|   staticRenderFns, |  | ||||||
|   false, |  | ||||||
|   null, |  | ||||||
|   "015b8bdf", |  | ||||||
|   null |  | ||||||
|    |  | ||||||
| ) |  | ||||||
|  |  | ||||||
| /* harmony default export */ var App = (App_component.exports); |  | ||||||
| // CONCATENATED MODULE: ./node_modules/@vue/cli-service/lib/commands/build/entry-lib.js |  | ||||||
|  |  | ||||||
|  |  | ||||||
| /* harmony default export */ var entry_lib = __webpack_exports__["default"] = (App); |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
| /***/ }) |  | ||||||
|  |  | ||||||
| /******/ })["default"]; |  | ||||||
| //# sourceMappingURL=plugin-record.common.js.map |  | ||||||
							
								
								
									
										1
									
								
								ui/dist/plugin-record.common.js.map
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								ui/dist/plugin-record.common.js.map
									
									
									
									
										vendored
									
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										1
									
								
								ui/dist/plugin-record.css
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								ui/dist/plugin-record.css
									
									
									
									
										vendored
									
									
								
							| @@ -1 +0,0 @@ | |||||||
| @-webkit-keyframes recording-data-v-015b8bdf{0%{opacity:.2}50%{opacity:1}to{opacity:.2}}@keyframes recording-data-v-015b8bdf{0%{opacity:.2}50%{opacity:1}to{opacity:.2}}.recording[data-v-015b8bdf]{-webkit-animation:recording-data-v-015b8bdf 1s infinite;animation:recording-data-v-015b8bdf 1s infinite}.layout[data-v-015b8bdf]{padding-bottom:30px;display:flex;flex-wrap:wrap}.room[data-v-015b8bdf]{width:250px;margin:10px;text-align:left}.empty[data-v-015b8bdf]{color:#ffc107;width:100%;min-height:500px;display:flex;justify-content:center;align-items:center}.status[data-v-015b8bdf]{position:fixed;display:flex;left:5px;bottom:10px}.status>div[data-v-015b8bdf]{margin:0 5px} |  | ||||||
							
								
								
									
										534
									
								
								ui/dist/plugin-record.umd.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										534
									
								
								ui/dist/plugin-record.umd.js
									
									
									
									
										vendored
									
									
								
							| @@ -1,534 +0,0 @@ | |||||||
| (function webpackUniversalModuleDefinition(root, factory) { |  | ||||||
| 	if(typeof exports === 'object' && typeof module === 'object') |  | ||||||
| 		module.exports = factory(); |  | ||||||
| 	else if(typeof define === 'function' && define.amd) |  | ||||||
| 		define([], factory); |  | ||||||
| 	else if(typeof exports === 'object') |  | ||||||
| 		exports["plugin-record"] = factory(); |  | ||||||
| 	else |  | ||||||
| 		root["plugin-record"] = factory(); |  | ||||||
| })((typeof self !== 'undefined' ? self : this), function() { |  | ||||||
| return /******/ (function(modules) { // webpackBootstrap |  | ||||||
| /******/ 	// The module cache |  | ||||||
| /******/ 	var installedModules = {}; |  | ||||||
| /******/ |  | ||||||
| /******/ 	// The require function |  | ||||||
| /******/ 	function __webpack_require__(moduleId) { |  | ||||||
| /******/ |  | ||||||
| /******/ 		// Check if module is in cache |  | ||||||
| /******/ 		if(installedModules[moduleId]) { |  | ||||||
| /******/ 			return installedModules[moduleId].exports; |  | ||||||
| /******/ 		} |  | ||||||
| /******/ 		// Create a new module (and put it into the cache) |  | ||||||
| /******/ 		var module = installedModules[moduleId] = { |  | ||||||
| /******/ 			i: moduleId, |  | ||||||
| /******/ 			l: false, |  | ||||||
| /******/ 			exports: {} |  | ||||||
| /******/ 		}; |  | ||||||
| /******/ |  | ||||||
| /******/ 		// Execute the module function |  | ||||||
| /******/ 		modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); |  | ||||||
| /******/ |  | ||||||
| /******/ 		// Flag the module as loaded |  | ||||||
| /******/ 		module.l = true; |  | ||||||
| /******/ |  | ||||||
| /******/ 		// Return the exports of the module |  | ||||||
| /******/ 		return module.exports; |  | ||||||
| /******/ 	} |  | ||||||
| /******/ |  | ||||||
| /******/ |  | ||||||
| /******/ 	// expose the modules object (__webpack_modules__) |  | ||||||
| /******/ 	__webpack_require__.m = modules; |  | ||||||
| /******/ |  | ||||||
| /******/ 	// expose the module cache |  | ||||||
| /******/ 	__webpack_require__.c = installedModules; |  | ||||||
| /******/ |  | ||||||
| /******/ 	// define getter function for harmony exports |  | ||||||
| /******/ 	__webpack_require__.d = function(exports, name, getter) { |  | ||||||
| /******/ 		if(!__webpack_require__.o(exports, name)) { |  | ||||||
| /******/ 			Object.defineProperty(exports, name, { enumerable: true, get: getter }); |  | ||||||
| /******/ 		} |  | ||||||
| /******/ 	}; |  | ||||||
| /******/ |  | ||||||
| /******/ 	// define __esModule on exports |  | ||||||
| /******/ 	__webpack_require__.r = function(exports) { |  | ||||||
| /******/ 		if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { |  | ||||||
| /******/ 			Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); |  | ||||||
| /******/ 		} |  | ||||||
| /******/ 		Object.defineProperty(exports, '__esModule', { value: true }); |  | ||||||
| /******/ 	}; |  | ||||||
| /******/ |  | ||||||
| /******/ 	// create a fake namespace object |  | ||||||
| /******/ 	// mode & 1: value is a module id, require it |  | ||||||
| /******/ 	// mode & 2: merge all properties of value into the ns |  | ||||||
| /******/ 	// mode & 4: return value when already ns object |  | ||||||
| /******/ 	// mode & 8|1: behave like require |  | ||||||
| /******/ 	__webpack_require__.t = function(value, mode) { |  | ||||||
| /******/ 		if(mode & 1) value = __webpack_require__(value); |  | ||||||
| /******/ 		if(mode & 8) return value; |  | ||||||
| /******/ 		if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value; |  | ||||||
| /******/ 		var ns = Object.create(null); |  | ||||||
| /******/ 		__webpack_require__.r(ns); |  | ||||||
| /******/ 		Object.defineProperty(ns, 'default', { enumerable: true, value: value }); |  | ||||||
| /******/ 		if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key)); |  | ||||||
| /******/ 		return ns; |  | ||||||
| /******/ 	}; |  | ||||||
| /******/ |  | ||||||
| /******/ 	// getDefaultExport function for compatibility with non-harmony modules |  | ||||||
| /******/ 	__webpack_require__.n = function(module) { |  | ||||||
| /******/ 		var getter = module && module.__esModule ? |  | ||||||
| /******/ 			function getDefault() { return module['default']; } : |  | ||||||
| /******/ 			function getModuleExports() { return module; }; |  | ||||||
| /******/ 		__webpack_require__.d(getter, 'a', getter); |  | ||||||
| /******/ 		return getter; |  | ||||||
| /******/ 	}; |  | ||||||
| /******/ |  | ||||||
| /******/ 	// Object.prototype.hasOwnProperty.call |  | ||||||
| /******/ 	__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; |  | ||||||
| /******/ |  | ||||||
| /******/ 	// __webpack_public_path__ |  | ||||||
| /******/ 	__webpack_require__.p = ""; |  | ||||||
| /******/ |  | ||||||
| /******/ |  | ||||||
| /******/ 	// Load entry module and return exports |  | ||||||
| /******/ 	return __webpack_require__(__webpack_require__.s = "fb15"); |  | ||||||
| /******/ }) |  | ||||||
| /************************************************************************/ |  | ||||||
| /******/ ({ |  | ||||||
|  |  | ||||||
| /***/ "5941": |  | ||||||
| /***/ (function(module, exports, __webpack_require__) { |  | ||||||
|  |  | ||||||
| // extracted by mini-css-extract-plugin |  | ||||||
|  |  | ||||||
| /***/ }), |  | ||||||
|  |  | ||||||
| /***/ "f6fd": |  | ||||||
| /***/ (function(module, exports) { |  | ||||||
|  |  | ||||||
| // document.currentScript polyfill by Adam Miller |  | ||||||
|  |  | ||||||
| // MIT license |  | ||||||
|  |  | ||||||
| (function(document){ |  | ||||||
|   var currentScript = "currentScript", |  | ||||||
|       scripts = document.getElementsByTagName('script'); // Live NodeList collection |  | ||||||
|  |  | ||||||
|   // If browser needs currentScript polyfill, add get currentScript() to the document object |  | ||||||
|   if (!(currentScript in document)) { |  | ||||||
|     Object.defineProperty(document, currentScript, { |  | ||||||
|       get: function(){ |  | ||||||
|  |  | ||||||
|         // IE 6-10 supports script readyState |  | ||||||
|         // IE 10+ support stack trace |  | ||||||
|         try { throw new Error(); } |  | ||||||
|         catch (err) { |  | ||||||
|  |  | ||||||
|           // Find the second match for the "at" string to get file src url from stack. |  | ||||||
|           // Specifically works with the format of stack traces in IE. |  | ||||||
|           var i, res = ((/.*at [^\(]*\((.*):.+:.+\)$/ig).exec(err.stack) || [false])[1]; |  | ||||||
|  |  | ||||||
|           // For all scripts on the page, if src matches or if ready state is interactive, return the script tag |  | ||||||
|           for(i in scripts){ |  | ||||||
|             if(scripts[i].src == res || scripts[i].readyState == "interactive"){ |  | ||||||
|               return scripts[i]; |  | ||||||
|             } |  | ||||||
|           } |  | ||||||
|  |  | ||||||
|           // If no match, return null |  | ||||||
|           return null; |  | ||||||
|         } |  | ||||||
|       } |  | ||||||
|     }); |  | ||||||
|   } |  | ||||||
| })(document); |  | ||||||
|  |  | ||||||
|  |  | ||||||
| /***/ }), |  | ||||||
|  |  | ||||||
| /***/ "f87e": |  | ||||||
| /***/ (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_015b8bdf_scoped_true_lang_css___WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__("5941"); |  | ||||||
| /* 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_015b8bdf_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_015b8bdf_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_015b8bdf_scoped_true_lang_css___WEBPACK_IMPORTED_MODULE_0___default.a);  |  | ||||||
|  |  | ||||||
| /***/ }), |  | ||||||
|  |  | ||||||
| /***/ "fb15": |  | ||||||
| /***/ (function(module, __webpack_exports__, __webpack_require__) { |  | ||||||
|  |  | ||||||
| "use strict"; |  | ||||||
| // ESM COMPAT FLAG |  | ||||||
| __webpack_require__.r(__webpack_exports__); |  | ||||||
|  |  | ||||||
| // CONCATENATED MODULE: ./node_modules/@vue/cli-service/lib/commands/build/setPublicPath.js |  | ||||||
| // This file is imported into lib/wc client bundles. |  | ||||||
|  |  | ||||||
| if (typeof window !== 'undefined') { |  | ||||||
|   if (true) { |  | ||||||
|     __webpack_require__("f6fd") |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   var i |  | ||||||
|   if ((i = window.document.currentScript) && (i = i.src.match(/(.+\/)[^/]+\.js(\?.*)?$/))) { |  | ||||||
|     __webpack_require__.p = i[1] // eslint-disable-line |  | ||||||
|   } |  | ||||||
| } |  | ||||||
|  |  | ||||||
| // 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=015b8bdf&scoped=true& |  | ||||||
| var render = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('div',[(_vm.$parent.titleTabActive==1)?_c('Records',{ref:"recordsPanel"}):_c('stream-table',{scopedSlots:_vm._u([{key:"default",fn:function(ref){ |  | ||||||
| var stream = ref.row; |  | ||||||
| return [(_vm.isRecording(stream))?_c('m-button',{attrs:{"blink":""},on:{"click":function($event){return _vm.stopRecord(stream)}}},[_vm._v("正在录制")]):_c('m-button',{on:{"click":function($event){return _vm.record(stream)}}},[_vm._v("录制")])]}}])})],1)} |  | ||||||
| var staticRenderFns = [] |  | ||||||
|  |  | ||||||
|  |  | ||||||
| // CONCATENATED MODULE: ./src/App.vue?vue&type=template&id=015b8bdf&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=675e088d& |  | ||||||
| var Recordsvue_type_template_id_675e088d_render = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('mu-data-table',{attrs:{"data":_vm.data,"columns":_vm.columns},scopedSlots:_vm._u([{key:"default",fn:function(ref){ |  | ||||||
| var row = ref.row; |  | ||||||
| return [_c('td',[_vm._v(_vm._s(row.Path))]),_c('td',[_vm._v(_vm._s(_vm.unitFormat(row.Size)))]),_c('td',[_vm._v(_vm._s(_vm.toDurationStr(row.Duration)))]),_c('td',[_c('mu-button',{attrs:{"icon":"","small":""},on:{"click":function($event){return _vm.play(row)}}},[_c('mu-icon',{attrs:{"value":"play_arrow"}})],1),_c('mu-button',{attrs:{"icon":"","small":""},on:{"click":function($event){return _vm.deleteFlv(row)}}},[_c('mu-icon',{attrs:{"value":"delete_forever"}})],1)],1)]}}])})} |  | ||||||
| var Recordsvue_type_template_id_675e088d_staticRenderFns = [] |  | ||||||
|  |  | ||||||
|  |  | ||||||
| // CONCATENATED MODULE: ./src/components/Records.vue?vue&type=template&id=675e088d& |  | ||||||
|  |  | ||||||
| // CONCATENATED MODULE: ./node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/vue-loader/lib??vue-loader-options!./src/components/Records.vue?vue&type=script&lang=js& |  | ||||||
| // |  | ||||||
| // |  | ||||||
| // |  | ||||||
| // |  | ||||||
| // |  | ||||||
| // |  | ||||||
| // |  | ||||||
| // |  | ||||||
| // |  | ||||||
| // |  | ||||||
| // |  | ||||||
| // |  | ||||||
| // |  | ||||||
| // |  | ||||||
| // |  | ||||||
| // |  | ||||||
| // |  | ||||||
| // |  | ||||||
|  |  | ||||||
| /* harmony default export */ var Recordsvue_type_script_lang_js_ = ({ |  | ||||||
|     data() { |  | ||||||
|         return { |  | ||||||
|             data: [], |  | ||||||
|             columns:[ |  | ||||||
|                 { |  | ||||||
|                     title:"文件路径" |  | ||||||
|                 },{ |  | ||||||
|                     title:"大小" |  | ||||||
|                 },{ |  | ||||||
|                     title:"时长" |  | ||||||
|                 },{title:"操作"} |  | ||||||
|             ] |  | ||||||
|         }; |  | ||||||
|     }, |  | ||||||
|     methods: { |  | ||||||
|         play(item) { |  | ||||||
|             this.ajax.get( |  | ||||||
|                 "/record/flv/play", |  | ||||||
|                 { streamPath: item.Path.replace(".flv", "") }, |  | ||||||
|                 x => { |  | ||||||
|                     if (x == "success") { |  | ||||||
|                         this.ajax.getJSON("/record/flv/list", x => this.data = x); |  | ||||||
|                         this.$toast.success("开始发布"); |  | ||||||
|                     } else { |  | ||||||
|                         this.$toast.error(x); |  | ||||||
|                     } |  | ||||||
|                 } |  | ||||||
|             ); |  | ||||||
|         }, |  | ||||||
|         deleteFlv(item) { |  | ||||||
|             this.$confirm("是否删除Flv文件", "提示").then(result => { |  | ||||||
|                 if (result) { |  | ||||||
|                     return this.ajax.get( |  | ||||||
|                         "/record/flv/delete", |  | ||||||
|                         { streamPath: item.Path.replace(".flv", "") }, |  | ||||||
|                         x => { |  | ||||||
|                             if (x == "success") { |  | ||||||
|                                 this.$toast.success("删除成功"); |  | ||||||
|                             } else { |  | ||||||
|                                 this.$toast.error(x); |  | ||||||
|                             } |  | ||||||
|                         } |  | ||||||
|                     ); |  | ||||||
|                 } |  | ||||||
|             }); |  | ||||||
|         }, |  | ||||||
|         toDurationStr(value) { |  | ||||||
|             if (value > 1000) { |  | ||||||
|                 let s = value / 1000; |  | ||||||
|                 if (s > 60) { |  | ||||||
|                     s = s | 0; |  | ||||||
|                     let min = (s / 60) >> 0; |  | ||||||
|                     if (min > 60) { |  | ||||||
|                         let hour = (min / 60) >> 0; |  | ||||||
|                         return hour + "hour" + (min % 60) + "min"; |  | ||||||
|                     } else { |  | ||||||
|                         return min + "min" + (s % 60) + "s"; |  | ||||||
|                     } |  | ||||||
|                 } else { |  | ||||||
|                     return s.toFixed(3) + "s"; |  | ||||||
|                 } |  | ||||||
|             } else { |  | ||||||
|                 return value + "ms"; |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|     }, |  | ||||||
|     mounted() { |  | ||||||
|         this.ajax.getJSON("/record/flv/list", x => this.data = x); |  | ||||||
|     } |  | ||||||
| }); |  | ||||||
|  |  | ||||||
| // CONCATENATED MODULE: ./src/components/Records.vue?vue&type=script&lang=js& |  | ||||||
|  /* harmony default export */ var components_Recordsvue_type_script_lang_js_ = (Recordsvue_type_script_lang_js_);  |  | ||||||
| // CONCATENATED MODULE: ./node_modules/vue-loader/lib/runtime/componentNormalizer.js |  | ||||||
| /* globals __VUE_SSR_CONTEXT__ */ |  | ||||||
|  |  | ||||||
| // IMPORTANT: Do NOT use ES2015 features in this file (except for modules). |  | ||||||
| // This module is a runtime utility for cleaner component module output and will |  | ||||||
| // be included in the final webpack user bundle. |  | ||||||
|  |  | ||||||
| function normalizeComponent ( |  | ||||||
|   scriptExports, |  | ||||||
|   render, |  | ||||||
|   staticRenderFns, |  | ||||||
|   functionalTemplate, |  | ||||||
|   injectStyles, |  | ||||||
|   scopeId, |  | ||||||
|   moduleIdentifier, /* server only */ |  | ||||||
|   shadowMode /* vue-cli only */ |  | ||||||
| ) { |  | ||||||
|   // Vue.extend constructor export interop |  | ||||||
|   var options = typeof scriptExports === 'function' |  | ||||||
|     ? scriptExports.options |  | ||||||
|     : scriptExports |  | ||||||
|  |  | ||||||
|   // render functions |  | ||||||
|   if (render) { |  | ||||||
|     options.render = render |  | ||||||
|     options.staticRenderFns = staticRenderFns |  | ||||||
|     options._compiled = true |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   // functional template |  | ||||||
|   if (functionalTemplate) { |  | ||||||
|     options.functional = true |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   // scopedId |  | ||||||
|   if (scopeId) { |  | ||||||
|     options._scopeId = 'data-v-' + scopeId |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   var hook |  | ||||||
|   if (moduleIdentifier) { // server build |  | ||||||
|     hook = function (context) { |  | ||||||
|       // 2.3 injection |  | ||||||
|       context = |  | ||||||
|         context || // cached call |  | ||||||
|         (this.$vnode && this.$vnode.ssrContext) || // stateful |  | ||||||
|         (this.parent && this.parent.$vnode && this.parent.$vnode.ssrContext) // functional |  | ||||||
|       // 2.2 with runInNewContext: true |  | ||||||
|       if (!context && typeof __VUE_SSR_CONTEXT__ !== 'undefined') { |  | ||||||
|         context = __VUE_SSR_CONTEXT__ |  | ||||||
|       } |  | ||||||
|       // inject component styles |  | ||||||
|       if (injectStyles) { |  | ||||||
|         injectStyles.call(this, context) |  | ||||||
|       } |  | ||||||
|       // register component module identifier for async chunk inferrence |  | ||||||
|       if (context && context._registeredComponents) { |  | ||||||
|         context._registeredComponents.add(moduleIdentifier) |  | ||||||
|       } |  | ||||||
|     } |  | ||||||
|     // used by ssr in case component is cached and beforeCreate |  | ||||||
|     // never gets called |  | ||||||
|     options._ssrRegister = hook |  | ||||||
|   } else if (injectStyles) { |  | ||||||
|     hook = shadowMode |  | ||||||
|       ? function () { injectStyles.call(this, this.$root.$options.shadowRoot) } |  | ||||||
|       : injectStyles |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   if (hook) { |  | ||||||
|     if (options.functional) { |  | ||||||
|       // for template-only hot-reload because in that case the render fn doesn't |  | ||||||
|       // go through the normalizer |  | ||||||
|       options._injectStyles = hook |  | ||||||
|       // register for functional component in vue file |  | ||||||
|       var originalRender = options.render |  | ||||||
|       options.render = function renderWithStyleInjection (h, context) { |  | ||||||
|         hook.call(context) |  | ||||||
|         return originalRender(h, context) |  | ||||||
|       } |  | ||||||
|     } else { |  | ||||||
|       // inject component registration as beforeCreate hook |  | ||||||
|       var existing = options.beforeCreate |  | ||||||
|       options.beforeCreate = existing |  | ||||||
|         ? [].concat(existing, hook) |  | ||||||
|         : [hook] |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   return { |  | ||||||
|     exports: scriptExports, |  | ||||||
|     options: options |  | ||||||
|   } |  | ||||||
| } |  | ||||||
|  |  | ||||||
| // CONCATENATED MODULE: ./src/components/Records.vue |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
| /* normalize component */ |  | ||||||
|  |  | ||||||
| var component = normalizeComponent( |  | ||||||
|   components_Recordsvue_type_script_lang_js_, |  | ||||||
|   Recordsvue_type_template_id_675e088d_render, |  | ||||||
|   Recordsvue_type_template_id_675e088d_staticRenderFns, |  | ||||||
|   false, |  | ||||||
|   null, |  | ||||||
|   null, |  | ||||||
|   null |  | ||||||
|    |  | ||||||
| ) |  | ||||||
|  |  | ||||||
| /* harmony default export */ var Records = (component.exports); |  | ||||||
| // CONCATENATED MODULE: ./node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/vue-loader/lib??vue-loader-options!./src/App.vue?vue&type=script&lang=js& |  | ||||||
| // |  | ||||||
| // |  | ||||||
| // |  | ||||||
| // |  | ||||||
| // |  | ||||||
| // |  | ||||||
| // |  | ||||||
| // |  | ||||||
| // |  | ||||||
| // |  | ||||||
| // |  | ||||||
| // |  | ||||||
|  |  | ||||||
|  |  | ||||||
| /* harmony default export */ var Appvue_type_script_lang_js_ = ({ |  | ||||||
|     components: { |  | ||||||
|         Records: Records |  | ||||||
|     }, |  | ||||||
|     data() { |  | ||||||
|         return {}; |  | ||||||
|     }, |  | ||||||
|     methods: { |  | ||||||
|         record(item) { |  | ||||||
|             let append = false; |  | ||||||
|             this.$confirm( |  | ||||||
|                 h => |  | ||||||
|                     h("mu-switch", { |  | ||||||
|                         props: { |  | ||||||
|                             label: "追加模式" |  | ||||||
|                         }, |  | ||||||
|                         on: { |  | ||||||
|                             change(value) { |  | ||||||
|                                 append = value; |  | ||||||
|                             } |  | ||||||
|                         } |  | ||||||
|                     }), |  | ||||||
|                 "是否开始录制" |  | ||||||
|             ).then(result => { |  | ||||||
|                 if (result) { |  | ||||||
|                     this.ajax.get( |  | ||||||
|                         "/record/flv?append=" + append, |  | ||||||
|                         { streamPath: item.StreamPath }, |  | ||||||
|                         x => { |  | ||||||
|                             if (x == "success") { |  | ||||||
|                                 this.$toast.success( |  | ||||||
|                                     "开始录制" + (append ? "(追加模式)" : "") |  | ||||||
|                                 ); |  | ||||||
|                             } else { |  | ||||||
|                                 this.$toast.error(x); |  | ||||||
|                             } |  | ||||||
|                         } |  | ||||||
|                     ); |  | ||||||
|                 } |  | ||||||
|             }); |  | ||||||
|         }, |  | ||||||
|         stopRecord(item) { |  | ||||||
|             this.$confirm("是否停止录制", "提示").then(result => { |  | ||||||
|                 if(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") |  | ||||||
|             ); |  | ||||||
|         } |  | ||||||
|     }, |  | ||||||
|     mounted() { |  | ||||||
|         this.$parent.titleTabs = ["StreamList", "录制的视频"]; |  | ||||||
|     } |  | ||||||
| }); |  | ||||||
|  |  | ||||||
| // 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&id=015b8bdf&scoped=true&lang=css& |  | ||||||
| var Appvue_type_style_index_0_id_015b8bdf_scoped_true_lang_css_ = __webpack_require__("f87e"); |  | ||||||
|  |  | ||||||
| // CONCATENATED MODULE: ./src/App.vue |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
| /* normalize component */ |  | ||||||
|  |  | ||||||
| var App_component = normalizeComponent( |  | ||||||
|   src_Appvue_type_script_lang_js_, |  | ||||||
|   render, |  | ||||||
|   staticRenderFns, |  | ||||||
|   false, |  | ||||||
|   null, |  | ||||||
|   "015b8bdf", |  | ||||||
|   null |  | ||||||
|    |  | ||||||
| ) |  | ||||||
|  |  | ||||||
| /* harmony default export */ var App = (App_component.exports); |  | ||||||
| // CONCATENATED MODULE: ./node_modules/@vue/cli-service/lib/commands/build/entry-lib.js |  | ||||||
|  |  | ||||||
|  |  | ||||||
| /* harmony default export */ var entry_lib = __webpack_exports__["default"] = (App); |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
| /***/ }) |  | ||||||
|  |  | ||||||
| /******/ })["default"]; |  | ||||||
| }); |  | ||||||
| //# sourceMappingURL=plugin-record.umd.js.map |  | ||||||
							
								
								
									
										1
									
								
								ui/dist/plugin-record.umd.js.map
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								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
											
										
									
								
							
							
								
								
									
										1
									
								
								ui/dist/plugin-record.umd.min.js.map
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								ui/dist/plugin-record.umd.min.js.map
									
									
									
									
										vendored
									
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										9560
									
								
								ui/package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										9560
									
								
								ui/package-lock.json
									
									
									
										generated
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -1,15 +0,0 @@ | |||||||
| { |  | ||||||
|     "name": "dashboard", |  | ||||||
|     "version": "1.0.0", |  | ||||||
|     "description": "dashboard of record plugin for monibuca", |  | ||||||
|     "main": "index.js", |  | ||||||
|     "scripts": { |  | ||||||
|         "build": "vue-cli-service build --target lib --name plugin-record" |  | ||||||
|     }, |  | ||||||
|     "author": "dexter", |  | ||||||
|     "license": "ISC", |  | ||||||
|     "devDependencies": { |  | ||||||
|         "@vue/cli-service": "^4.2.3", |  | ||||||
|         "vue-template-compiler": "^2.6.11" |  | ||||||
|     } |  | ||||||
| } |  | ||||||
							
								
								
									
										135
									
								
								ui/src/App.vue
									
									
									
									
									
								
							
							
						
						
									
										135
									
								
								ui/src/App.vue
									
									
									
									
									
								
							| @@ -1,135 +0,0 @@ | |||||||
| <template> |  | ||||||
|     <div> |  | ||||||
|         <Records ref="recordsPanel" v-if="$parent.titleTabActive==1" /> |  | ||||||
|         <stream-table v-else> |  | ||||||
|             <template v-slot="{row:stream}"> |  | ||||||
|                 <m-button v-if="isRecording(stream)" @click="stopRecord(stream)" blink>正在录制</m-button> |  | ||||||
|                 <m-button v-else @click="record(stream)">录制</m-button> |  | ||||||
|             </template> |  | ||||||
|         </stream-table> |  | ||||||
|     </div> |  | ||||||
| </template> |  | ||||||
|  |  | ||||||
| <script> |  | ||||||
| import Records from "./components/Records"; |  | ||||||
| export default { |  | ||||||
|     components: { |  | ||||||
|         Records |  | ||||||
|     }, |  | ||||||
|     data() { |  | ||||||
|         return {}; |  | ||||||
|     }, |  | ||||||
|     methods: { |  | ||||||
|         record(item) { |  | ||||||
|             let append = false; |  | ||||||
|             this.$confirm( |  | ||||||
|                 h => |  | ||||||
|                     h("mu-switch", { |  | ||||||
|                         props: { |  | ||||||
|                             label: "追加模式" |  | ||||||
|                         }, |  | ||||||
|                         on: { |  | ||||||
|                             change(value) { |  | ||||||
|                                 append = value; |  | ||||||
|                             } |  | ||||||
|                         } |  | ||||||
|                     }), |  | ||||||
|                 "是否开始录制" |  | ||||||
|             ).then(result => { |  | ||||||
|                 if (result) { |  | ||||||
|                     this.ajax.get( |  | ||||||
|                         "/record/flv?append=" + append, |  | ||||||
|                         { streamPath: item.StreamPath }, |  | ||||||
|                         x => { |  | ||||||
|                             if (x == "success") { |  | ||||||
|                                 this.$toast.success( |  | ||||||
|                                     "开始录制" + (append ? "(追加模式)" : "") |  | ||||||
|                                 ); |  | ||||||
|                             } else { |  | ||||||
|                                 this.$toast.error(x); |  | ||||||
|                             } |  | ||||||
|                         } |  | ||||||
|                     ); |  | ||||||
|                 } |  | ||||||
|             }); |  | ||||||
|         }, |  | ||||||
|         stopRecord(item) { |  | ||||||
|             this.$confirm("是否停止录制", "提示").then(result => { |  | ||||||
|                 if(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") |  | ||||||
|             ); |  | ||||||
|         } |  | ||||||
|     }, |  | ||||||
|     mounted() { |  | ||||||
|         this.$parent.titleTabs = ["StreamList", "录制的视频"]; |  | ||||||
|     } |  | ||||||
| }; |  | ||||||
| </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; |  | ||||||
|     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; |  | ||||||
| } |  | ||||||
| </style> |  | ||||||
| @@ -1,92 +0,0 @@ | |||||||
| <template> |  | ||||||
|     <mu-data-table :data="data" :columns="columns"> |  | ||||||
|         <template #default="{row}"> |  | ||||||
|             <td>{{row.Path}}</td> |  | ||||||
|             <td>{{unitFormat(row.Size)}}</td> |  | ||||||
|             <td>{{toDurationStr(row.Duration)}}</td> |  | ||||||
|             <td> |  | ||||||
|                 <mu-button @click="play(row)" icon small> |  | ||||||
|                     <mu-icon value="play_arrow" /> |  | ||||||
|                 </mu-button> |  | ||||||
|                 <mu-button @click="deleteFlv(row)" icon small> |  | ||||||
|                     <mu-icon value="delete_forever" /> |  | ||||||
|                 </mu-button> |  | ||||||
|             </td> |  | ||||||
|         </template> |  | ||||||
|     </mu-data-table> |  | ||||||
| </template> |  | ||||||
|  |  | ||||||
| <script> |  | ||||||
| export default { |  | ||||||
|     data() { |  | ||||||
|         return { |  | ||||||
|             data: [], |  | ||||||
|             columns:[ |  | ||||||
|                 { |  | ||||||
|                     title:"文件路径" |  | ||||||
|                 },{ |  | ||||||
|                     title:"大小" |  | ||||||
|                 },{ |  | ||||||
|                     title:"时长" |  | ||||||
|                 },{title:"操作"} |  | ||||||
|             ] |  | ||||||
|         }; |  | ||||||
|     }, |  | ||||||
|     methods: { |  | ||||||
|         play(item) { |  | ||||||
|             this.ajax.get( |  | ||||||
|                 "/record/flv/play", |  | ||||||
|                 { streamPath: item.Path.replace(".flv", "") }, |  | ||||||
|                 x => { |  | ||||||
|                     if (x == "success") { |  | ||||||
|                         this.ajax.getJSON("/record/flv/list", x => this.data = x); |  | ||||||
|                         this.$toast.success("开始发布"); |  | ||||||
|                     } else { |  | ||||||
|                         this.$toast.error(x); |  | ||||||
|                     } |  | ||||||
|                 } |  | ||||||
|             ); |  | ||||||
|         }, |  | ||||||
|         deleteFlv(item) { |  | ||||||
|             this.$confirm("是否删除Flv文件", "提示").then(result => { |  | ||||||
|                 if (result) { |  | ||||||
|                     return this.ajax.get( |  | ||||||
|                         "/record/flv/delete", |  | ||||||
|                         { streamPath: item.Path.replace(".flv", "") }, |  | ||||||
|                         x => { |  | ||||||
|                             if (x == "success") { |  | ||||||
|                                 this.$toast.success("删除成功"); |  | ||||||
|                             } else { |  | ||||||
|                                 this.$toast.error(x); |  | ||||||
|                             } |  | ||||||
|                         } |  | ||||||
|                     ); |  | ||||||
|                 } |  | ||||||
|             }); |  | ||||||
|         }, |  | ||||||
|         toDurationStr(value) { |  | ||||||
|             if (value > 1000) { |  | ||||||
|                 let s = value / 1000; |  | ||||||
|                 if (s > 60) { |  | ||||||
|                     s = s | 0; |  | ||||||
|                     let min = (s / 60) >> 0; |  | ||||||
|                     if (min > 60) { |  | ||||||
|                         let hour = (min / 60) >> 0; |  | ||||||
|                         return hour + "hour" + (min % 60) + "min"; |  | ||||||
|                     } else { |  | ||||||
|                         return min + "min" + (s % 60) + "s"; |  | ||||||
|                     } |  | ||||||
|                 } else { |  | ||||||
|                     return s.toFixed(3) + "s"; |  | ||||||
|                 } |  | ||||||
|             } else { |  | ||||||
|                 return value + "ms"; |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|     }, |  | ||||||
|     mounted() { |  | ||||||
|         this.ajax.getJSON("/record/flv/list", x => this.data = x); |  | ||||||
|     } |  | ||||||
| }; |  | ||||||
| </script> |  | ||||||
|  |  | ||||||
		Reference in New Issue
	
	Block a user
	 langhuihui
					langhuihui