mirror of
https://github.com/Monibuca/plugin-rtsp.git
synced 2025-10-04 23:32:54 +08:00
Compare commits
1 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
55bd2ce785 |
158
client.go
158
client.go
@@ -6,8 +6,6 @@ import (
|
|||||||
"crypto/md5"
|
"crypto/md5"
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"fmt"
|
"fmt"
|
||||||
. "github.com/Monibuca/engine/v2"
|
|
||||||
"github.com/pixelbender/go-sdp/sdp"
|
|
||||||
"io"
|
"io"
|
||||||
"net"
|
"net"
|
||||||
"net/url"
|
"net/url"
|
||||||
@@ -15,6 +13,8 @@ import (
|
|||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
. "github.com/Monibuca/engine/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
// PullStream 从外部拉流
|
// PullStream 从外部拉流
|
||||||
@@ -28,7 +28,7 @@ func (rtsp *RTSP) PullStream(streamPath string, rtspUrl string) (result bool) {
|
|||||||
rtsp.aRTPChannel = 2
|
rtsp.aRTPChannel = 2
|
||||||
rtsp.aRTPControlChannel = 3
|
rtsp.aRTPControlChannel = 3
|
||||||
rtsp.URL = rtspUrl
|
rtsp.URL = rtspUrl
|
||||||
if err := rtsp.requestStream();err != nil {
|
if err := rtsp.requestStream(); err != nil {
|
||||||
rtsp.Close()
|
rtsp.Close()
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@@ -184,97 +184,87 @@ func (client *RTSP) requestStream() (err error) {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_sdp, err := sdp.ParseString(resp.Body)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
client.Sdp = _sdp
|
|
||||||
client.SDPRaw = resp.Body
|
client.SDPRaw = resp.Body
|
||||||
client.SDPMap = ParseSDP(client.SDPRaw)
|
client.SDPMap = ParseSDP(client.SDPRaw)
|
||||||
session := ""
|
session := ""
|
||||||
for _, media := range _sdp.Media {
|
if videoInfo, ok := client.SDPMap["video"]; ok {
|
||||||
switch media.Type {
|
client.VControl = videoInfo.Control
|
||||||
case "video":
|
client.VCodec = videoInfo.Codec
|
||||||
client.VControl = media.Attributes.Get("control")
|
client.SPS = videoInfo.SpropParameterSets[0]
|
||||||
client.VCodec = media.Format[0].Name
|
client.PPS = videoInfo.SpropParameterSets[1]
|
||||||
client.SPS = client.SDPMap["video"].SpropParameterSets[0]
|
var _url = ""
|
||||||
client.PPS = client.SDPMap["video"].SpropParameterSets[1]
|
if strings.Index(strings.ToLower(client.VControl), "rtsp://") == 0 {
|
||||||
var _url = ""
|
_url = client.VControl
|
||||||
if strings.Index(strings.ToLower(client.VControl), "rtsp://") == 0 {
|
} else {
|
||||||
_url = client.VControl
|
_url = strings.TrimRight(client.URL, "/") + "/" + strings.TrimLeft(client.VControl, "/")
|
||||||
} else {
|
|
||||||
_url = strings.TrimRight(client.URL, "/") + "/" + strings.TrimLeft(client.VControl, "/")
|
|
||||||
}
|
|
||||||
headers = make(map[string]string)
|
|
||||||
if client.TransType == TRANS_TYPE_TCP {
|
|
||||||
headers["Transport"] = fmt.Sprintf("RTP/AVP/TCP;unicast;interleaved=%d-%d", client.vRTPChannel, client.vRTPControlChannel)
|
|
||||||
} else {
|
|
||||||
if client.UDPServer == nil {
|
|
||||||
client.UDPServer = &UDPServer{Session: client}
|
|
||||||
}
|
|
||||||
//RTP/AVP;unicast;client_port=64864-64865
|
|
||||||
err = client.UDPServer.SetupVideo()
|
|
||||||
if err != nil {
|
|
||||||
Printf("Setup video err.%v", err)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
headers["Transport"] = fmt.Sprintf("RTP/AVP/UDP;unicast;client_port=%d-%d", client.UDPServer.VPort, client.UDPServer.VControlPort)
|
|
||||||
client.Conn.timeout = 0 // UDP ignore timeout
|
|
||||||
}
|
|
||||||
if session != "" {
|
|
||||||
headers["Session"] = session
|
|
||||||
}
|
|
||||||
Printf("Parse DESCRIBE response, VIDEO VControl:%s, VCode:%s, url:%s,Session:%s,vRTPChannel:%d,vRTPControlChannel:%d", client.VControl, client.VCodec, _url, session, client.vRTPChannel, client.vRTPControlChannel)
|
|
||||||
resp, err = client.RequestWithPath("SETUP", _url, headers, true)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
session, _ = resp.Header["Session"].(string)
|
|
||||||
case "audio":
|
|
||||||
client.AControl = media.Attributes.Get("control")
|
|
||||||
client.ACodec = media.Format[0].Name
|
|
||||||
client.AudioSpecificConfig = client.SDPMap["audio"].Config
|
|
||||||
var _url = ""
|
|
||||||
if strings.Index(strings.ToLower(client.AControl), "rtsp://") == 0 {
|
|
||||||
_url = client.AControl
|
|
||||||
} else {
|
|
||||||
_url = strings.TrimRight(client.URL, "/") + "/" + strings.TrimLeft(client.AControl, "/")
|
|
||||||
}
|
|
||||||
headers = make(map[string]string)
|
|
||||||
if client.TransType == TRANS_TYPE_TCP {
|
|
||||||
headers["Transport"] = fmt.Sprintf("RTP/AVP/TCP;unicast;interleaved=%d-%d", client.aRTPChannel, client.aRTPControlChannel)
|
|
||||||
} else {
|
|
||||||
if client.UDPServer == nil {
|
|
||||||
client.UDPServer = &UDPServer{Session: client}
|
|
||||||
}
|
|
||||||
err = client.UDPServer.SetupAudio()
|
|
||||||
if err != nil {
|
|
||||||
Printf("Setup audio err.%v", err)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
headers["Transport"] = fmt.Sprintf("RTP/AVP/UDP;unicast;client_port=%d-%d", client.UDPServer.APort, client.UDPServer.AControlPort)
|
|
||||||
client.Conn.timeout = 0 // UDP ignore timeout
|
|
||||||
}
|
|
||||||
if session != "" {
|
|
||||||
headers["Session"] = session
|
|
||||||
}
|
|
||||||
Printf("Parse DESCRIBE response, AUDIO AControl:%s, ACodec:%s, url:%s,Session:%s, aRTPChannel:%d,aRTPControlChannel:%d", client.AControl, client.ACodec, _url, session, client.aRTPChannel, client.aRTPControlChannel)
|
|
||||||
resp, err = client.RequestWithPath("SETUP", _url, headers, true)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
session, _ = resp.Header["Session"].(string)
|
|
||||||
}
|
}
|
||||||
|
headers = make(map[string]string)
|
||||||
|
if client.TransType == TRANS_TYPE_TCP {
|
||||||
|
headers["Transport"] = fmt.Sprintf("RTP/AVP/TCP;unicast;interleaved=%d-%d", client.vRTPChannel, client.vRTPControlChannel)
|
||||||
|
} else {
|
||||||
|
if client.UDPServer == nil {
|
||||||
|
client.UDPServer = &UDPServer{Session: client}
|
||||||
|
}
|
||||||
|
//RTP/AVP;unicast;client_port=64864-64865
|
||||||
|
err = client.UDPServer.SetupVideo()
|
||||||
|
if err != nil {
|
||||||
|
Printf("Setup video err.%v", err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
headers["Transport"] = fmt.Sprintf("RTP/AVP/UDP;unicast;client_port=%d-%d", client.UDPServer.VPort, client.UDPServer.VControlPort)
|
||||||
|
client.Conn.timeout = 0 // UDP ignore timeout
|
||||||
|
}
|
||||||
|
if session != "" {
|
||||||
|
headers["Session"] = session
|
||||||
|
}
|
||||||
|
Printf("Parse DESCRIBE response, VIDEO VControl:%s, VCode:%s, url:%s,Session:%s,vRTPChannel:%d,vRTPControlChannel:%d", client.VControl, client.VCodec, _url, session, client.vRTPChannel, client.vRTPControlChannel)
|
||||||
|
if resp, err = client.RequestWithPath("SETUP", _url, headers, true); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
session, _ = resp.Header["Session"].(string)
|
||||||
|
session = strings.Split(session, ";")[0]
|
||||||
|
}
|
||||||
|
if audioInfo, ok := client.SDPMap["audio"]; ok {
|
||||||
|
client.AControl = audioInfo.Control
|
||||||
|
client.ACodec = audioInfo.Codec
|
||||||
|
client.AudioSpecificConfig = audioInfo.Config
|
||||||
|
var _url = ""
|
||||||
|
if strings.Index(strings.ToLower(client.AControl), "rtsp://") == 0 {
|
||||||
|
_url = client.AControl
|
||||||
|
} else {
|
||||||
|
_url = strings.TrimRight(client.URL, "/") + "/" + strings.TrimLeft(client.AControl, "/")
|
||||||
|
}
|
||||||
|
headers = make(map[string]string)
|
||||||
|
if client.TransType == TRANS_TYPE_TCP {
|
||||||
|
headers["Transport"] = fmt.Sprintf("RTP/AVP/TCP;unicast;interleaved=%d-%d", client.aRTPChannel, client.aRTPControlChannel)
|
||||||
|
} else {
|
||||||
|
if client.UDPServer == nil {
|
||||||
|
client.UDPServer = &UDPServer{Session: client}
|
||||||
|
}
|
||||||
|
err = client.UDPServer.SetupAudio()
|
||||||
|
if err != nil {
|
||||||
|
Printf("Setup audio err.%v", err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
headers["Transport"] = fmt.Sprintf("RTP/AVP/UDP;unicast;client_port=%d-%d", client.UDPServer.APort, client.UDPServer.AControlPort)
|
||||||
|
client.Conn.timeout = 0 // UDP ignore timeout
|
||||||
|
}
|
||||||
|
if session != "" {
|
||||||
|
headers["Session"] = session
|
||||||
|
}
|
||||||
|
Printf("Parse DESCRIBE response, AUDIO AControl:%s, ACodec:%s, url:%s,Session:%s, aRTPChannel:%d,aRTPControlChannel:%d", client.AControl, client.ACodec, _url, session, client.aRTPChannel, client.aRTPControlChannel)
|
||||||
|
if resp, err = client.RequestWithPath("SETUP", _url, headers, true); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
session, _ = resp.Header["Session"].(string)
|
||||||
|
session = strings.Split(session, ";")[0]
|
||||||
}
|
}
|
||||||
headers = make(map[string]string)
|
headers = make(map[string]string)
|
||||||
if session != "" {
|
if session != "" {
|
||||||
headers["Session"] = session
|
headers["Session"] = session
|
||||||
}
|
}
|
||||||
resp, err = client.Request("PLAY", headers)
|
resp, err = client.Request("PLAY", headers)
|
||||||
if err != nil {
|
return err
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (client *RTSP) startStream() {
|
func (client *RTSP) startStream() {
|
||||||
|
3
go.mod
3
go.mod
@@ -4,6 +4,9 @@ go 1.13
|
|||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/Monibuca/engine/v2 v2.0.0
|
github.com/Monibuca/engine/v2 v2.0.0
|
||||||
|
github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee // indirect
|
||||||
|
github.com/gobwas/pool v0.2.0 // indirect
|
||||||
|
github.com/gobwas/ws v1.0.3 // indirect
|
||||||
github.com/jinzhu/gorm v1.9.12 // indirect
|
github.com/jinzhu/gorm v1.9.12 // indirect
|
||||||
github.com/pixelbender/go-sdp v1.0.0
|
github.com/pixelbender/go-sdp v1.0.0
|
||||||
github.com/reactivex/rxgo v1.0.0 // indirect
|
github.com/reactivex/rxgo v1.0.0 // indirect
|
||||||
|
6
go.sum
6
go.sum
@@ -25,6 +25,12 @@ github.com/go-ole/go-ole v1.2.4 h1:nNBDSCOigTSiarFpYE9J/KtEA1IOW4CNeqT9TQDqCxI=
|
|||||||
github.com/go-ole/go-ole v1.2.4/go.mod h1:XCwSNxSkXRo4vlyPy93sltvi/qJq0jqQhjqQNIwKuxM=
|
github.com/go-ole/go-ole v1.2.4/go.mod h1:XCwSNxSkXRo4vlyPy93sltvi/qJq0jqQhjqQNIwKuxM=
|
||||||
github.com/go-sql-driver/mysql v1.4.1 h1:g24URVg0OFbNUTx9qqY1IRZ9D9z3iPyi5zKhQZpNwpA=
|
github.com/go-sql-driver/mysql v1.4.1 h1:g24URVg0OFbNUTx9qqY1IRZ9D9z3iPyi5zKhQZpNwpA=
|
||||||
github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
|
github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
|
||||||
|
github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee h1:s+21KNqlpePfkah2I+gwHF8xmJWRjooY+5248k6m4A0=
|
||||||
|
github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee/go.mod h1:L0fX3K22YWvt/FAX9NnzrNzcI4wNYi9Yku4O0LKYflo=
|
||||||
|
github.com/gobwas/pool v0.2.0 h1:QEmUOlnSjWtnpRGHF3SauEiOsy82Cup83Vf2LcMlnc8=
|
||||||
|
github.com/gobwas/pool v0.2.0/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw=
|
||||||
|
github.com/gobwas/ws v1.0.3 h1:ZOigqf7iBxkA4jdQ3am7ATzdlOFp9YzA6NmuvEEZc9g=
|
||||||
|
github.com/gobwas/ws v1.0.3/go.mod h1:szmBTxLgaFppYjEmNtny/v3w89xOydFnnZMcgRRu/EM=
|
||||||
github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe h1:lXe2qZdvpiX5WZkZR4hgp4KJVfY3nMkvmwbVkpv1rVY=
|
github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe h1:lXe2qZdvpiX5WZkZR4hgp4KJVfY3nMkvmwbVkpv1rVY=
|
||||||
github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0=
|
github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0=
|
||||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||||
|
33
main.go
33
main.go
@@ -14,18 +14,16 @@ import (
|
|||||||
. "github.com/Monibuca/engine/v2"
|
. "github.com/Monibuca/engine/v2"
|
||||||
. "github.com/Monibuca/engine/v2/avformat"
|
. "github.com/Monibuca/engine/v2/avformat"
|
||||||
"github.com/Monibuca/engine/v2/util"
|
"github.com/Monibuca/engine/v2/util"
|
||||||
"github.com/pixelbender/go-sdp/sdp"
|
|
||||||
"github.com/teris-io/shortid"
|
"github.com/teris-io/shortid"
|
||||||
)
|
)
|
||||||
|
|
||||||
var collection = sync.Map{}
|
var collection = sync.Map{}
|
||||||
var config = struct {
|
var config = struct {
|
||||||
ListenAddr string
|
ListenAddr string
|
||||||
BufferLength int
|
AutoPull bool
|
||||||
AutoPull bool
|
RemoteAddr string
|
||||||
RemoteAddr string
|
Timeout int
|
||||||
Timeout int
|
}{":554", false, "rtsp://localhost/${streamPath}", 0}
|
||||||
}{":554", 2048, true, "rtsp://localhost/${streamPath}", 0}
|
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
InstallPlugin(&PluginConfig{
|
InstallPlugin(&PluginConfig{
|
||||||
@@ -54,7 +52,6 @@ func runPlugin() {
|
|||||||
collection.Range(func(key, value interface{}) bool {
|
collection.Range(func(key, value interface{}) bool {
|
||||||
rtsp := value.(*RTSP)
|
rtsp := value.(*RTSP)
|
||||||
pinfo := &rtsp.RTSPInfo
|
pinfo := &rtsp.RTSPInfo
|
||||||
//pinfo.BufferRate = len(rtsp.OutGoing) * 100 / config.BufferLength
|
|
||||||
info = append(info, pinfo)
|
info = append(info, pinfo)
|
||||||
return true
|
return true
|
||||||
})
|
})
|
||||||
@@ -158,19 +155,17 @@ type RTSP struct {
|
|||||||
Auth func(string) string
|
Auth func(string) string
|
||||||
}
|
}
|
||||||
type RTSPClientInfo struct {
|
type RTSPClientInfo struct {
|
||||||
Agent string
|
Agent string
|
||||||
Session string
|
Session string
|
||||||
Sdp *sdp.Session
|
authLine string
|
||||||
authLine string
|
Seq int
|
||||||
Seq int
|
|
||||||
}
|
}
|
||||||
type RTSPInfo struct {
|
type RTSPInfo struct {
|
||||||
URL string
|
URL string
|
||||||
SyncCount int64
|
SyncCount int64
|
||||||
Header *string
|
Header *string
|
||||||
BufferRate int
|
InBytes int
|
||||||
InBytes int
|
OutBytes int
|
||||||
OutBytes int
|
|
||||||
|
|
||||||
StreamInfo *StreamInfo
|
StreamInfo *StreamInfo
|
||||||
}
|
}
|
||||||
|
158
ui/dist/plugin-rtsp.common.js
vendored
158
ui/dist/plugin-rtsp.common.js
vendored
@@ -172,14 +172,14 @@ if (typeof window !== 'undefined') {
|
|||||||
// Indicate to webpack that this file can be concatenated
|
// Indicate to webpack that this file can be concatenated
|
||||||
/* harmony default export */ var setPublicPath = (null);
|
/* harmony default export */ var setPublicPath = (null);
|
||||||
|
|
||||||
// CONCATENATED MODULE: ./node_modules/cache-loader/dist/cjs.js?{"cacheDirectory":"node_modules/.cache/vue-loader","cacheIdentifier":"29918b3a-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=3ee6bce0&
|
// CONCATENATED MODULE: ./node_modules/cache-loader/dist/cjs.js?{"cacheDirectory":"node_modules/.cache/vue-loader","cacheIdentifier":"29918b3a-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=18f38531&
|
||||||
var render = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('div',[_c('mu-data-table',{attrs:{"data":_vm.Streams,"columns":_vm.columns},scopedSlots:_vm._u([{key:"default",fn:function(ref){
|
var render = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('div',[_c('mu-data-table',{attrs:{"data":_vm.Streams,"columns":_vm.columns},scopedSlots:_vm._u([{key:"default",fn:function(ref){
|
||||||
var item = ref.row;
|
var item = ref.row;
|
||||||
return [_c('td',[_vm._v(_vm._s(item.StreamInfo.StreamPath))]),_c('td',[_c('StartTime',{attrs:{"value":item.StreamInfo.StartTime}})],1),_c('td',[_c('Progress',{attrs:{"stroke-width":20,"percent":Math.ceil(item.BufferRate),"text-inside":""}})],1),_c('td',[_vm._v(_vm._s(item.SyncCount))]),_c('td',[_c('mu-button',{attrs:{"flat":""},on:{"click":function($event){return _vm.showHeader(item)}}},[_vm._v("头信息")])],1)]}}])}),_c('mu-dialog',{attrs:{"title":"拉流转发","width":"360","open":_vm.openPull},on:{"update:open":function($event){_vm.openPull=$event}}},[_c('mu-text-field',{attrs:{"label":"rtsp url","label-float":"","help-text":"Please enter URL of rtsp..."},model:{value:(_vm.remoteAddr),callback:function ($$v) {_vm.remoteAddr=$$v},expression:"remoteAddr"}}),_c('mu-text-field',{attrs:{"label":"streamPath","label-float":"","help-text":"Please enter streamPath to publish."},model:{value:(_vm.streamPath),callback:function ($$v) {_vm.streamPath=$$v},expression:"streamPath"}}),_c('mu-button',{attrs:{"slot":"actions","flat":"","color":"primary"},on:{"click":_vm.addPull},slot:"actions"},[_vm._v("确定")])],1)],1)}
|
return [_c('td',[_vm._v(_vm._s(item.StreamInfo.StreamPath))]),_c('td',[_c('StartTime',{attrs:{"value":item.StreamInfo.StartTime}})],1),_c('td',[_vm._v(_vm._s(item.InBytes))]),_c('td',[_vm._v(_vm._s(item.OutBytes))]),_c('td',[_c('mu-button',{attrs:{"flat":""},on:{"click":function($event){return _vm.showHeader(item)}}},[_vm._v("头信息")]),_c('mu-button',{attrs:{"flat":""},on:{"click":function($event){return _vm.stop(item)}}},[_vm._v("中止")])],1)]}}])}),_c('mu-dialog',{attrs:{"title":"拉流转发","width":"360","open":_vm.openPull},on:{"update:open":function($event){_vm.openPull=$event}}},[_c('mu-text-field',{attrs:{"label":"rtsp url","label-float":"","help-text":"Please enter URL of rtsp..."},model:{value:(_vm.remoteAddr),callback:function ($$v) {_vm.remoteAddr=$$v},expression:"remoteAddr"}}),_c('mu-text-field',{attrs:{"label":"streamPath","label-float":"","help-text":"Please enter streamPath to publish."},model:{value:(_vm.streamPath),callback:function ($$v) {_vm.streamPath=$$v},expression:"streamPath"}}),_c('mu-button',{attrs:{"slot":"actions","flat":"","color":"primary"},on:{"click":_vm.addPull},slot:"actions"},[_vm._v("确定")])],1)],1)}
|
||||||
var staticRenderFns = []
|
var staticRenderFns = []
|
||||||
|
|
||||||
|
|
||||||
// CONCATENATED MODULE: ./src/App.vue?vue&type=template&id=3ee6bce0&
|
// CONCATENATED MODULE: ./src/App.vue?vue&type=template&id=18f38531&
|
||||||
|
|
||||||
// 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&
|
// 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&
|
||||||
//
|
//
|
||||||
@@ -207,78 +207,100 @@ var staticRenderFns = []
|
|||||||
//
|
//
|
||||||
//
|
//
|
||||||
//
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
|
||||||
let listES = null;
|
let listES = null;
|
||||||
/* harmony default export */ var Appvue_type_script_lang_js_ = ({
|
/* harmony default export */ var Appvue_type_script_lang_js_ = ({
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
currentStream: null,
|
currentStream: null,
|
||||||
Streams: null,
|
Streams: null,
|
||||||
remoteAddr: "",
|
remoteAddr: "",
|
||||||
streamPath: "",
|
streamPath: "",
|
||||||
openPull: false,
|
openPull: false,
|
||||||
columns: [
|
columns: [
|
||||||
"StreamPath",
|
"StreamPath",
|
||||||
"开始时间",
|
"开始时间",
|
||||||
"缓冲",
|
"总接收",
|
||||||
"同步数",
|
"总发送",
|
||||||
"操作"
|
"操作"
|
||||||
].map(title => ({ title }))
|
].map(title => ({ title }))
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
fetchlist() {
|
fetchlist() {
|
||||||
listES = new EventSource(this.apiHost + "/rtsp/list");
|
listES = new EventSource(this.apiHost + "/rtsp/list");
|
||||||
listES.onmessage = evt => {
|
listES.onmessage = evt => {
|
||||||
if (!evt.data) return;
|
if (!evt.data) return;
|
||||||
this.Streams = JSON.parse(evt.data) || [];
|
this.Streams = JSON.parse(evt.data) || [];
|
||||||
this.Streams.sort((a, b) =>
|
this.Streams.sort((a, b) =>
|
||||||
a.StreamInfo.StreamPath > b.StreamInfo.StreamPath ? 1 : -1
|
a.StreamInfo.StreamPath > b.StreamInfo.StreamPath ? 1 : -1
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
},
|
|
||||||
showHeader(item) {
|
|
||||||
this.$Modal.info({
|
|
||||||
title: "RTSP Header",
|
|
||||||
width: "1000px",
|
|
||||||
scrollable: true,
|
|
||||||
content: item.Header
|
|
||||||
});
|
|
||||||
},
|
|
||||||
addPull() {
|
|
||||||
this.openPull = false;
|
|
||||||
this.ajax
|
|
||||||
.getJSON(this.apiHost + "/rtsp/pull", {
|
|
||||||
target: this.remoteAddr,
|
|
||||||
streamPath: this.streamPath
|
|
||||||
})
|
|
||||||
.then(x => {
|
|
||||||
if (x.code == 0) {
|
|
||||||
this.$toast.success("已启动拉流");
|
|
||||||
} else {
|
|
||||||
this.$toast.error(x.msg);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
mounted() {
|
showHeader(item) {
|
||||||
this.fetchlist();
|
this.$Modal.info({
|
||||||
let _this = this;
|
title: "RTSP Header",
|
||||||
this.$parent.titleOps = [
|
width: "1000px",
|
||||||
{
|
scrollable: true,
|
||||||
template: '<m-button @click="onClick">拉流转发</m-button>',
|
content: item.Header
|
||||||
methods: {
|
});
|
||||||
onClick() {
|
|
||||||
_this.openPull = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
];
|
|
||||||
},
|
},
|
||||||
destroyed() {
|
addPull() {
|
||||||
listES.close();
|
this.openPull = false;
|
||||||
|
this.ajax
|
||||||
|
.getJSON(this.apiHost + "/rtsp/pull", {
|
||||||
|
target: this.remoteAddr,
|
||||||
|
streamPath: this.streamPath
|
||||||
|
})
|
||||||
|
.then(x => {
|
||||||
|
if (x.code == 0) {
|
||||||
|
this.$toast.success("已启动拉流");
|
||||||
|
} else {
|
||||||
|
this.$toast.error(x.msg);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
stop(item) {
|
||||||
|
this.ajax
|
||||||
|
.get(this.apiHost + "/api/stop", {
|
||||||
|
stream: this.streamPath
|
||||||
|
})
|
||||||
|
.then(x => {
|
||||||
|
if (x == "success") {
|
||||||
|
this.$toast.success("已停止拉流");
|
||||||
|
} else {
|
||||||
|
this.$toast.error(x.msg);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
this.fetchlist();
|
||||||
|
let _this = this;
|
||||||
|
this.$parent.titleOps = [
|
||||||
|
{
|
||||||
|
template: '<m-button @click="onClick">拉流转发</m-button>',
|
||||||
|
methods: {
|
||||||
|
onClick() {
|
||||||
|
_this.openPull = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
];
|
||||||
|
},
|
||||||
|
destroyed() {
|
||||||
|
listES.close();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// CONCATENATED MODULE: ./src/App.vue?vue&type=script&lang=js&
|
// CONCATENATED MODULE: ./src/App.vue?vue&type=script&lang=js&
|
||||||
|
2
ui/dist/plugin-rtsp.common.js.map
vendored
2
ui/dist/plugin-rtsp.common.js.map
vendored
File diff suppressed because one or more lines are too long
158
ui/dist/plugin-rtsp.umd.js
vendored
158
ui/dist/plugin-rtsp.umd.js
vendored
@@ -181,14 +181,14 @@ if (typeof window !== 'undefined') {
|
|||||||
// Indicate to webpack that this file can be concatenated
|
// Indicate to webpack that this file can be concatenated
|
||||||
/* harmony default export */ var setPublicPath = (null);
|
/* harmony default export */ var setPublicPath = (null);
|
||||||
|
|
||||||
// CONCATENATED MODULE: ./node_modules/cache-loader/dist/cjs.js?{"cacheDirectory":"node_modules/.cache/vue-loader","cacheIdentifier":"29918b3a-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=3ee6bce0&
|
// CONCATENATED MODULE: ./node_modules/cache-loader/dist/cjs.js?{"cacheDirectory":"node_modules/.cache/vue-loader","cacheIdentifier":"29918b3a-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=18f38531&
|
||||||
var render = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('div',[_c('mu-data-table',{attrs:{"data":_vm.Streams,"columns":_vm.columns},scopedSlots:_vm._u([{key:"default",fn:function(ref){
|
var render = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('div',[_c('mu-data-table',{attrs:{"data":_vm.Streams,"columns":_vm.columns},scopedSlots:_vm._u([{key:"default",fn:function(ref){
|
||||||
var item = ref.row;
|
var item = ref.row;
|
||||||
return [_c('td',[_vm._v(_vm._s(item.StreamInfo.StreamPath))]),_c('td',[_c('StartTime',{attrs:{"value":item.StreamInfo.StartTime}})],1),_c('td',[_c('Progress',{attrs:{"stroke-width":20,"percent":Math.ceil(item.BufferRate),"text-inside":""}})],1),_c('td',[_vm._v(_vm._s(item.SyncCount))]),_c('td',[_c('mu-button',{attrs:{"flat":""},on:{"click":function($event){return _vm.showHeader(item)}}},[_vm._v("头信息")])],1)]}}])}),_c('mu-dialog',{attrs:{"title":"拉流转发","width":"360","open":_vm.openPull},on:{"update:open":function($event){_vm.openPull=$event}}},[_c('mu-text-field',{attrs:{"label":"rtsp url","label-float":"","help-text":"Please enter URL of rtsp..."},model:{value:(_vm.remoteAddr),callback:function ($$v) {_vm.remoteAddr=$$v},expression:"remoteAddr"}}),_c('mu-text-field',{attrs:{"label":"streamPath","label-float":"","help-text":"Please enter streamPath to publish."},model:{value:(_vm.streamPath),callback:function ($$v) {_vm.streamPath=$$v},expression:"streamPath"}}),_c('mu-button',{attrs:{"slot":"actions","flat":"","color":"primary"},on:{"click":_vm.addPull},slot:"actions"},[_vm._v("确定")])],1)],1)}
|
return [_c('td',[_vm._v(_vm._s(item.StreamInfo.StreamPath))]),_c('td',[_c('StartTime',{attrs:{"value":item.StreamInfo.StartTime}})],1),_c('td',[_vm._v(_vm._s(item.InBytes))]),_c('td',[_vm._v(_vm._s(item.OutBytes))]),_c('td',[_c('mu-button',{attrs:{"flat":""},on:{"click":function($event){return _vm.showHeader(item)}}},[_vm._v("头信息")]),_c('mu-button',{attrs:{"flat":""},on:{"click":function($event){return _vm.stop(item)}}},[_vm._v("中止")])],1)]}}])}),_c('mu-dialog',{attrs:{"title":"拉流转发","width":"360","open":_vm.openPull},on:{"update:open":function($event){_vm.openPull=$event}}},[_c('mu-text-field',{attrs:{"label":"rtsp url","label-float":"","help-text":"Please enter URL of rtsp..."},model:{value:(_vm.remoteAddr),callback:function ($$v) {_vm.remoteAddr=$$v},expression:"remoteAddr"}}),_c('mu-text-field',{attrs:{"label":"streamPath","label-float":"","help-text":"Please enter streamPath to publish."},model:{value:(_vm.streamPath),callback:function ($$v) {_vm.streamPath=$$v},expression:"streamPath"}}),_c('mu-button',{attrs:{"slot":"actions","flat":"","color":"primary"},on:{"click":_vm.addPull},slot:"actions"},[_vm._v("确定")])],1)],1)}
|
||||||
var staticRenderFns = []
|
var staticRenderFns = []
|
||||||
|
|
||||||
|
|
||||||
// CONCATENATED MODULE: ./src/App.vue?vue&type=template&id=3ee6bce0&
|
// CONCATENATED MODULE: ./src/App.vue?vue&type=template&id=18f38531&
|
||||||
|
|
||||||
// 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&
|
// 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&
|
||||||
//
|
//
|
||||||
@@ -216,78 +216,100 @@ var staticRenderFns = []
|
|||||||
//
|
//
|
||||||
//
|
//
|
||||||
//
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
|
||||||
let listES = null;
|
let listES = null;
|
||||||
/* harmony default export */ var Appvue_type_script_lang_js_ = ({
|
/* harmony default export */ var Appvue_type_script_lang_js_ = ({
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
currentStream: null,
|
currentStream: null,
|
||||||
Streams: null,
|
Streams: null,
|
||||||
remoteAddr: "",
|
remoteAddr: "",
|
||||||
streamPath: "",
|
streamPath: "",
|
||||||
openPull: false,
|
openPull: false,
|
||||||
columns: [
|
columns: [
|
||||||
"StreamPath",
|
"StreamPath",
|
||||||
"开始时间",
|
"开始时间",
|
||||||
"缓冲",
|
"总接收",
|
||||||
"同步数",
|
"总发送",
|
||||||
"操作"
|
"操作"
|
||||||
].map(title => ({ title }))
|
].map(title => ({ title }))
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
fetchlist() {
|
fetchlist() {
|
||||||
listES = new EventSource(this.apiHost + "/rtsp/list");
|
listES = new EventSource(this.apiHost + "/rtsp/list");
|
||||||
listES.onmessage = evt => {
|
listES.onmessage = evt => {
|
||||||
if (!evt.data) return;
|
if (!evt.data) return;
|
||||||
this.Streams = JSON.parse(evt.data) || [];
|
this.Streams = JSON.parse(evt.data) || [];
|
||||||
this.Streams.sort((a, b) =>
|
this.Streams.sort((a, b) =>
|
||||||
a.StreamInfo.StreamPath > b.StreamInfo.StreamPath ? 1 : -1
|
a.StreamInfo.StreamPath > b.StreamInfo.StreamPath ? 1 : -1
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
},
|
|
||||||
showHeader(item) {
|
|
||||||
this.$Modal.info({
|
|
||||||
title: "RTSP Header",
|
|
||||||
width: "1000px",
|
|
||||||
scrollable: true,
|
|
||||||
content: item.Header
|
|
||||||
});
|
|
||||||
},
|
|
||||||
addPull() {
|
|
||||||
this.openPull = false;
|
|
||||||
this.ajax
|
|
||||||
.getJSON(this.apiHost + "/rtsp/pull", {
|
|
||||||
target: this.remoteAddr,
|
|
||||||
streamPath: this.streamPath
|
|
||||||
})
|
|
||||||
.then(x => {
|
|
||||||
if (x.code == 0) {
|
|
||||||
this.$toast.success("已启动拉流");
|
|
||||||
} else {
|
|
||||||
this.$toast.error(x.msg);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
mounted() {
|
showHeader(item) {
|
||||||
this.fetchlist();
|
this.$Modal.info({
|
||||||
let _this = this;
|
title: "RTSP Header",
|
||||||
this.$parent.titleOps = [
|
width: "1000px",
|
||||||
{
|
scrollable: true,
|
||||||
template: '<m-button @click="onClick">拉流转发</m-button>',
|
content: item.Header
|
||||||
methods: {
|
});
|
||||||
onClick() {
|
|
||||||
_this.openPull = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
];
|
|
||||||
},
|
},
|
||||||
destroyed() {
|
addPull() {
|
||||||
listES.close();
|
this.openPull = false;
|
||||||
|
this.ajax
|
||||||
|
.getJSON(this.apiHost + "/rtsp/pull", {
|
||||||
|
target: this.remoteAddr,
|
||||||
|
streamPath: this.streamPath
|
||||||
|
})
|
||||||
|
.then(x => {
|
||||||
|
if (x.code == 0) {
|
||||||
|
this.$toast.success("已启动拉流");
|
||||||
|
} else {
|
||||||
|
this.$toast.error(x.msg);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
stop(item) {
|
||||||
|
this.ajax
|
||||||
|
.get(this.apiHost + "/api/stop", {
|
||||||
|
stream: this.streamPath
|
||||||
|
})
|
||||||
|
.then(x => {
|
||||||
|
if (x == "success") {
|
||||||
|
this.$toast.success("已停止拉流");
|
||||||
|
} else {
|
||||||
|
this.$toast.error(x.msg);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
this.fetchlist();
|
||||||
|
let _this = this;
|
||||||
|
this.$parent.titleOps = [
|
||||||
|
{
|
||||||
|
template: '<m-button @click="onClick">拉流转发</m-button>',
|
||||||
|
methods: {
|
||||||
|
onClick() {
|
||||||
|
_this.openPull = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
];
|
||||||
|
},
|
||||||
|
destroyed() {
|
||||||
|
listES.close();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// CONCATENATED MODULE: ./src/App.vue?vue&type=script&lang=js&
|
// CONCATENATED MODULE: ./src/App.vue?vue&type=script&lang=js&
|
||||||
|
2
ui/dist/plugin-rtsp.umd.js.map
vendored
2
ui/dist/plugin-rtsp.umd.js.map
vendored
File diff suppressed because one or more lines are too long
2
ui/dist/plugin-rtsp.umd.min.js
vendored
2
ui/dist/plugin-rtsp.umd.min.js
vendored
@@ -1,2 +1,2 @@
|
|||||||
(function(t,e){"object"===typeof exports&&"object"===typeof module?module.exports=e():"function"===typeof define&&define.amd?define([],e):"object"===typeof exports?exports["plugin-rtsp"]=e():t["plugin-rtsp"]=e()})("undefined"!==typeof self?self:this,(function(){return function(t){var e={};function r(n){if(e[n])return e[n].exports;var o=e[n]={i:n,l:!1,exports:{}};return t[n].call(o.exports,o,o.exports,r),o.l=!0,o.exports}return r.m=t,r.c=e,r.d=function(t,e,n){r.o(t,e)||Object.defineProperty(t,e,{enumerable:!0,get:n})},r.r=function(t){"undefined"!==typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})},r.t=function(t,e){if(1&e&&(t=r(t)),8&e)return t;if(4&e&&"object"===typeof t&&t&&t.__esModule)return t;var n=Object.create(null);if(r.r(n),Object.defineProperty(n,"default",{enumerable:!0,value:t}),2&e&&"string"!=typeof t)for(var o in t)r.d(n,o,function(e){return t[e]}.bind(null,o));return n},r.n=function(t){var e=t&&t.__esModule?function(){return t["default"]}:function(){return t};return r.d(e,"a",e),e},r.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},r.p="",r(r.s="fb15")}({"034f":function(t,e,r){"use strict";var n=r("85ec"),o=r.n(n);o.a},"85ec":function(t,e,r){},f6fd:function(t,e){(function(t){var e="currentScript",r=t.getElementsByTagName("script");e in t||Object.defineProperty(t,e,{get:function(){try{throw new Error}catch(n){var t,e=(/.*at [^\(]*\((.*):.+:.+\)$/gi.exec(n.stack)||[!1])[1];for(t in r)if(r[t].src==e||"interactive"==r[t].readyState)return r[t];return null}}})})(document)},fb15:function(t,e,r){"use strict";var n;(r.r(e),"undefined"!==typeof window)&&(r("f6fd"),(n=window.document.currentScript)&&(n=n.src.match(/(.+\/)[^/]+\.js(\?.*)?$/))&&(r.p=n[1]));var o=function(){var t=this,e=t.$createElement,r=t._self._c||e;return r("div",[r("mu-data-table",{attrs:{data:t.Streams,columns:t.columns},scopedSlots:t._u([{key:"default",fn:function(e){var n=e.row;return[r("td",[t._v(t._s(n.StreamInfo.StreamPath))]),r("td",[r("StartTime",{attrs:{value:n.StreamInfo.StartTime}})],1),r("td",[r("Progress",{attrs:{"stroke-width":20,percent:Math.ceil(n.BufferRate),"text-inside":""}})],1),r("td",[t._v(t._s(n.SyncCount))]),r("td",[r("mu-button",{attrs:{flat:""},on:{click:function(e){return t.showHeader(n)}}},[t._v("头信息")])],1)]}}])}),r("mu-dialog",{attrs:{title:"拉流转发",width:"360",open:t.openPull},on:{"update:open":function(e){t.openPull=e}}},[r("mu-text-field",{attrs:{label:"rtsp url","label-float":"","help-text":"Please enter URL of rtsp..."},model:{value:t.remoteAddr,callback:function(e){t.remoteAddr=e},expression:"remoteAddr"}}),r("mu-text-field",{attrs:{label:"streamPath","label-float":"","help-text":"Please enter streamPath to publish."},model:{value:t.streamPath,callback:function(e){t.streamPath=e},expression:"streamPath"}}),r("mu-button",{attrs:{slot:"actions",flat:"",color:"primary"},on:{click:t.addPull},slot:"actions"},[t._v("确定")])],1)],1)},a=[];let s=null;var i={data(){return{currentStream:null,Streams:null,remoteAddr:"",streamPath:"",openPull:!1,columns:["StreamPath","开始时间","缓冲","同步数","操作"].map(t=>({title:t}))}},methods:{fetchlist(){s=new EventSource(this.apiHost+"/rtsp/list"),s.onmessage=t=>{t.data&&(this.Streams=JSON.parse(t.data)||[],this.Streams.sort((t,e)=>t.StreamInfo.StreamPath>e.StreamInfo.StreamPath?1:-1))}},showHeader(t){this.$Modal.info({title:"RTSP Header",width:"1000px",scrollable:!0,content:t.Header})},addPull(){this.openPull=!1,this.ajax.getJSON(this.apiHost+"/rtsp/pull",{target:this.remoteAddr,streamPath:this.streamPath}).then(t=>{0==t.code?this.$toast.success("已启动拉流"):this.$toast.error(t.msg)})}},mounted(){this.fetchlist();let t=this;this.$parent.titleOps=[{template:'<m-button @click="onClick">拉流转发</m-button>',methods:{onClick(){t.openPull=!0}}}]},destroyed(){s.close()}},l=i;r("034f");function u(t,e,r,n,o,a,s,i){var l,u="function"===typeof t?t.options:t;if(e&&(u.render=e,u.staticRenderFns=r,u._compiled=!0),n&&(u.functional=!0),a&&(u._scopeId="data-v-"+a),s?(l=function(t){t=t||this.$vnode&&this.$vnode.ssrContext||this.parent&&this.parent.$vnode&&this.parent.$vnode.ssrContext,t||"undefined"===typeof __VUE_SSR_CONTEXT__||(t=__VUE_SSR_CONTEXT__),o&&o.call(this,t),t&&t._registeredComponents&&t._registeredComponents.add(s)},u._ssrRegister=l):o&&(l=i?function(){o.call(this,this.$root.$options.shadowRoot)}:o),l)if(u.functional){u._injectStyles=l;var c=u.render;u.render=function(t,e){return l.call(e),c(t,e)}}else{var d=u.beforeCreate;u.beforeCreate=d?[].concat(d,l):[l]}return{exports:t,options:u}}var c=u(l,o,a,!1,null,null,null),d=c.exports;e["default"]=d}})["default"]}));
|
(function(t,e){"object"===typeof exports&&"object"===typeof module?module.exports=e():"function"===typeof define&&define.amd?define([],e):"object"===typeof exports?exports["plugin-rtsp"]=e():t["plugin-rtsp"]=e()})("undefined"!==typeof self?self:this,(function(){return function(t){var e={};function r(n){if(e[n])return e[n].exports;var o=e[n]={i:n,l:!1,exports:{}};return t[n].call(o.exports,o,o.exports,r),o.l=!0,o.exports}return r.m=t,r.c=e,r.d=function(t,e,n){r.o(t,e)||Object.defineProperty(t,e,{enumerable:!0,get:n})},r.r=function(t){"undefined"!==typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})},r.t=function(t,e){if(1&e&&(t=r(t)),8&e)return t;if(4&e&&"object"===typeof t&&t&&t.__esModule)return t;var n=Object.create(null);if(r.r(n),Object.defineProperty(n,"default",{enumerable:!0,value:t}),2&e&&"string"!=typeof t)for(var o in t)r.d(n,o,function(e){return t[e]}.bind(null,o));return n},r.n=function(t){var e=t&&t.__esModule?function(){return t["default"]}:function(){return t};return r.d(e,"a",e),e},r.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},r.p="",r(r.s="fb15")}({"034f":function(t,e,r){"use strict";var n=r("85ec"),o=r.n(n);o.a},"85ec":function(t,e,r){},f6fd:function(t,e){(function(t){var e="currentScript",r=t.getElementsByTagName("script");e in t||Object.defineProperty(t,e,{get:function(){try{throw new Error}catch(n){var t,e=(/.*at [^\(]*\((.*):.+:.+\)$/gi.exec(n.stack)||[!1])[1];for(t in r)if(r[t].src==e||"interactive"==r[t].readyState)return r[t];return null}}})})(document)},fb15:function(t,e,r){"use strict";var n;(r.r(e),"undefined"!==typeof window)&&(r("f6fd"),(n=window.document.currentScript)&&(n=n.src.match(/(.+\/)[^/]+\.js(\?.*)?$/))&&(r.p=n[1]));var o=function(){var t=this,e=t.$createElement,r=t._self._c||e;return r("div",[r("mu-data-table",{attrs:{data:t.Streams,columns:t.columns},scopedSlots:t._u([{key:"default",fn:function(e){var n=e.row;return[r("td",[t._v(t._s(n.StreamInfo.StreamPath))]),r("td",[r("StartTime",{attrs:{value:n.StreamInfo.StartTime}})],1),r("td",[t._v(t._s(n.InBytes))]),r("td",[t._v(t._s(n.OutBytes))]),r("td",[r("mu-button",{attrs:{flat:""},on:{click:function(e){return t.showHeader(n)}}},[t._v("头信息")]),r("mu-button",{attrs:{flat:""},on:{click:function(e){return t.stop(n)}}},[t._v("中止")])],1)]}}])}),r("mu-dialog",{attrs:{title:"拉流转发",width:"360",open:t.openPull},on:{"update:open":function(e){t.openPull=e}}},[r("mu-text-field",{attrs:{label:"rtsp url","label-float":"","help-text":"Please enter URL of rtsp..."},model:{value:t.remoteAddr,callback:function(e){t.remoteAddr=e},expression:"remoteAddr"}}),r("mu-text-field",{attrs:{label:"streamPath","label-float":"","help-text":"Please enter streamPath to publish."},model:{value:t.streamPath,callback:function(e){t.streamPath=e},expression:"streamPath"}}),r("mu-button",{attrs:{slot:"actions",flat:"",color:"primary"},on:{click:t.addPull},slot:"actions"},[t._v("确定")])],1)],1)},a=[];let s=null;var i={data(){return{currentStream:null,Streams:null,remoteAddr:"",streamPath:"",openPull:!1,columns:["StreamPath","开始时间","总接收","总发送","操作"].map(t=>({title:t}))}},methods:{fetchlist(){s=new EventSource(this.apiHost+"/rtsp/list"),s.onmessage=t=>{t.data&&(this.Streams=JSON.parse(t.data)||[],this.Streams.sort((t,e)=>t.StreamInfo.StreamPath>e.StreamInfo.StreamPath?1:-1))}},showHeader(t){this.$Modal.info({title:"RTSP Header",width:"1000px",scrollable:!0,content:t.Header})},addPull(){this.openPull=!1,this.ajax.getJSON(this.apiHost+"/rtsp/pull",{target:this.remoteAddr,streamPath:this.streamPath}).then(t=>{0==t.code?this.$toast.success("已启动拉流"):this.$toast.error(t.msg)})},stop(t){this.ajax.get(this.apiHost+"/api/stop",{stream:this.streamPath}).then(t=>{"success"==t?this.$toast.success("已停止拉流"):this.$toast.error(t.msg)})}},mounted(){this.fetchlist();let t=this;this.$parent.titleOps=[{template:'<m-button @click="onClick">拉流转发</m-button>',methods:{onClick(){t.openPull=!0}}}]},destroyed(){s.close()}},l=i;r("034f");function u(t,e,r,n,o,a,s,i){var l,u="function"===typeof t?t.options:t;if(e&&(u.render=e,u.staticRenderFns=r,u._compiled=!0),n&&(u.functional=!0),a&&(u._scopeId="data-v-"+a),s?(l=function(t){t=t||this.$vnode&&this.$vnode.ssrContext||this.parent&&this.parent.$vnode&&this.parent.$vnode.ssrContext,t||"undefined"===typeof __VUE_SSR_CONTEXT__||(t=__VUE_SSR_CONTEXT__),o&&o.call(this,t),t&&t._registeredComponents&&t._registeredComponents.add(s)},u._ssrRegister=l):o&&(l=i?function(){o.call(this,this.$root.$options.shadowRoot)}:o),l)if(u.functional){u._injectStyles=l;var c=u.render;u.render=function(t,e){return l.call(e),c(t,e)}}else{var d=u.beforeCreate;u.beforeCreate=d?[].concat(d,l):[l]}return{exports:t,options:u}}var c=u(l,o,a,!1,null,null,null),d=c.exports;e["default"]=d}})["default"]}));
|
||||||
//# sourceMappingURL=plugin-rtsp.umd.min.js.map
|
//# sourceMappingURL=plugin-rtsp.umd.min.js.map
|
2
ui/dist/plugin-rtsp.umd.min.js.map
vendored
2
ui/dist/plugin-rtsp.umd.min.js.map
vendored
File diff suppressed because one or more lines are too long
222
ui/src/App.vue
222
ui/src/App.vue
@@ -1,125 +1,147 @@
|
|||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<mu-data-table :data="Streams" :columns="columns">
|
<mu-data-table :data="Streams" :columns="columns">
|
||||||
<template #default="{row:item}">
|
<template #default="{row:item}">
|
||||||
<td>{{item.StreamInfo.StreamPath}}</td>
|
<td>{{item.StreamInfo.StreamPath}}</td>
|
||||||
<td>
|
<td>
|
||||||
<StartTime :value="item.StreamInfo.StartTime"></StartTime>
|
<StartTime :value="item.StreamInfo.StartTime"></StartTime>
|
||||||
</td>
|
</td>
|
||||||
<td><Progress :stroke-width="20" :percent="Math.ceil(item.BufferRate)" text-inside /></td>
|
<td>{{item.InBytes}}</td>
|
||||||
<td>{{item.SyncCount}}</td>
|
<td>{{item.OutBytes}}</td>
|
||||||
<td>
|
<td>
|
||||||
<mu-button flat @click="showHeader(item)">头信息</mu-button>
|
<mu-button flat @click="showHeader(item)">头信息</mu-button>
|
||||||
</td>
|
<mu-button flat @click="stop(item)">中止</mu-button>
|
||||||
</template>
|
</td>
|
||||||
</mu-data-table>
|
</template>
|
||||||
<mu-dialog title="拉流转发" width="360" :open.sync="openPull">
|
</mu-data-table>
|
||||||
<mu-text-field v-model="remoteAddr" label="rtsp url" label-float help-text="Please enter URL of rtsp...">
|
<mu-dialog title="拉流转发" width="360" :open.sync="openPull">
|
||||||
</mu-text-field>
|
<mu-text-field
|
||||||
<mu-text-field v-model="streamPath" label="streamPath" label-float
|
v-model="remoteAddr"
|
||||||
help-text="Please enter streamPath to publish."></mu-text-field>
|
label="rtsp url"
|
||||||
<mu-button slot="actions" flat color="primary" @click="addPull">确定</mu-button>
|
label-float
|
||||||
</mu-dialog>
|
help-text="Please enter URL of rtsp..."
|
||||||
</div>
|
></mu-text-field>
|
||||||
|
<mu-text-field
|
||||||
|
v-model="streamPath"
|
||||||
|
label="streamPath"
|
||||||
|
label-float
|
||||||
|
help-text="Please enter streamPath to publish."
|
||||||
|
></mu-text-field>
|
||||||
|
<mu-button slot="actions" flat color="primary" @click="addPull">确定</mu-button>
|
||||||
|
</mu-dialog>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
let listES = null;
|
let listES = null;
|
||||||
export default {
|
export default {
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
currentStream: null,
|
currentStream: null,
|
||||||
Streams: null,
|
Streams: null,
|
||||||
remoteAddr: "",
|
remoteAddr: "",
|
||||||
streamPath: "",
|
streamPath: "",
|
||||||
openPull: false,
|
openPull: false,
|
||||||
columns: [
|
columns: [
|
||||||
"StreamPath",
|
"StreamPath",
|
||||||
"开始时间",
|
"开始时间",
|
||||||
"缓冲",
|
"总接收",
|
||||||
"同步数",
|
"总发送",
|
||||||
"操作"
|
"操作"
|
||||||
].map(title => ({ title }))
|
].map(title => ({ title }))
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
fetchlist() {
|
fetchlist() {
|
||||||
listES = new EventSource(this.apiHost + "/rtsp/list");
|
listES = new EventSource(this.apiHost + "/rtsp/list");
|
||||||
listES.onmessage = evt => {
|
listES.onmessage = evt => {
|
||||||
if (!evt.data) return;
|
if (!evt.data) return;
|
||||||
this.Streams = JSON.parse(evt.data) || [];
|
this.Streams = JSON.parse(evt.data) || [];
|
||||||
this.Streams.sort((a, b) =>
|
this.Streams.sort((a, b) =>
|
||||||
a.StreamInfo.StreamPath > b.StreamInfo.StreamPath ? 1 : -1
|
a.StreamInfo.StreamPath > b.StreamInfo.StreamPath ? 1 : -1
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
},
|
|
||||||
showHeader(item) {
|
|
||||||
this.$Modal.info({
|
|
||||||
title: "RTSP Header",
|
|
||||||
width: "1000px",
|
|
||||||
scrollable: true,
|
|
||||||
content: item.Header
|
|
||||||
});
|
|
||||||
},
|
|
||||||
addPull() {
|
|
||||||
this.openPull = false;
|
|
||||||
this.ajax
|
|
||||||
.getJSON(this.apiHost + "/rtsp/pull", {
|
|
||||||
target: this.remoteAddr,
|
|
||||||
streamPath: this.streamPath
|
|
||||||
})
|
|
||||||
.then(x => {
|
|
||||||
if (x.code == 0) {
|
|
||||||
this.$toast.success("已启动拉流");
|
|
||||||
} else {
|
|
||||||
this.$toast.error(x.msg);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
mounted() {
|
showHeader(item) {
|
||||||
this.fetchlist();
|
this.$Modal.info({
|
||||||
let _this = this;
|
title: "RTSP Header",
|
||||||
this.$parent.titleOps = [
|
width: "1000px",
|
||||||
{
|
scrollable: true,
|
||||||
template: '<m-button @click="onClick">拉流转发</m-button>',
|
content: item.Header
|
||||||
methods: {
|
});
|
||||||
onClick() {
|
|
||||||
_this.openPull = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
];
|
|
||||||
},
|
},
|
||||||
destroyed() {
|
addPull() {
|
||||||
listES.close();
|
this.openPull = false;
|
||||||
|
this.ajax
|
||||||
|
.getJSON(this.apiHost + "/rtsp/pull", {
|
||||||
|
target: this.remoteAddr,
|
||||||
|
streamPath: this.streamPath
|
||||||
|
})
|
||||||
|
.then(x => {
|
||||||
|
if (x.code == 0) {
|
||||||
|
this.$toast.success("已启动拉流");
|
||||||
|
} else {
|
||||||
|
this.$toast.error(x.msg);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
stop(item) {
|
||||||
|
this.ajax
|
||||||
|
.get(this.apiHost + "/api/stop", {
|
||||||
|
stream: item.StreamInfo.StreamPath
|
||||||
|
})
|
||||||
|
.then(x => {
|
||||||
|
if (x == "success") {
|
||||||
|
this.$toast.success("已停止拉流");
|
||||||
|
} else {
|
||||||
|
this.$toast.error(x.msg);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
this.fetchlist();
|
||||||
|
let _this = this;
|
||||||
|
this.$parent.titleOps = [
|
||||||
|
{
|
||||||
|
template: '<m-button @click="onClick">拉流转发</m-button>',
|
||||||
|
methods: {
|
||||||
|
onClick() {
|
||||||
|
_this.openPull = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
];
|
||||||
|
},
|
||||||
|
destroyed() {
|
||||||
|
listES.close();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
.empty {
|
.empty {
|
||||||
color: #eb5e46;
|
color: #eb5e46;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
min-height: 500px;
|
min-height: 500px;
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.layout {
|
.layout {
|
||||||
padding-bottom: 30px;
|
padding-bottom: 30px;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
}
|
}
|
||||||
.ts-info {
|
.ts-info {
|
||||||
width: 300px;
|
width: 300px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.hls-info {
|
.hls-info {
|
||||||
width: 350px;
|
width: 350px;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
Reference in New Issue
Block a user