diff --git a/config/record.go b/config/record.go new file mode 100644 index 0000000..ff29a5d --- /dev/null +++ b/config/record.go @@ -0,0 +1,98 @@ +package config + +import ( + "io" + "os" + "path" + "path/filepath" + "regexp" + "strings" +) + +type FileWr interface { + io.Reader + io.Writer + io.Seeker + io.Closer +} +type VideoFileInfo struct { + Path string + Size int64 + Duration uint32 +} + +type Record struct { + Ext string //文件扩展名 + Path string //存储文件的目录 + AutoRecord bool + Filter string + filterReg *regexp.Regexp + CreateFileFn func(filename string, append bool) (FileWr, error) `yaml:"_"` + GetDurationFn func(file io.ReadSeeker) uint32 `yaml:"_"` +} + +func (r *Record) NeedRecord(streamPath string) bool { + return r.AutoRecord && (r.filterReg == nil || r.filterReg.MatchString(streamPath)) +} + +func (r *Record) Init() { + os.MkdirAll(r.Path, 0755) + if r.Filter != "" { + r.filterReg = regexp.MustCompile(r.Filter) + } + r.CreateFileFn = func(filename string, append bool) (file FileWr, err error) { + filePath := filepath.Join(r.Path, filename) + flag := os.O_CREATE + if append { + flag = flag | os.O_RDWR | os.O_APPEND + } else { + flag = flag | os.O_TRUNC | os.O_WRONLY + } + if err = os.MkdirAll(filepath.Dir(filePath), 0755); err != nil { + return file, err + } + file, err = os.OpenFile(filePath, flag, 0755) + return + } +} + +func (r *Record) Tree(dstPath string, level int) (files []*VideoFileInfo, err error) { + var dstF *os.File + dstF, err = os.Open(dstPath) + if err != nil { + return + } + defer dstF.Close() + fileInfo, err := dstF.Stat() + if err != nil { + return + } + if !fileInfo.IsDir() { //如果dstF是文件 + if path.Ext(fileInfo.Name()) == r.Ext { + p := strings.TrimPrefix(dstPath, r.Path) + p = strings.ReplaceAll(p, "\\", "/") + files = append(files, &VideoFileInfo{ + Path: strings.TrimPrefix(p, "/"), + Size: fileInfo.Size(), + Duration: r.GetDurationFn(dstF), + }) + } + return + } else { //如果dstF是文件夹 + var dir []os.FileInfo + dir, err = dstF.Readdir(0) //获取文件夹下各个文件或文件夹的fileInfo + if err != nil { + return + } + for _, fileInfo = range dir { + var _files []*VideoFileInfo + _files, err = r.Tree(filepath.Join(dstPath, fileInfo.Name()), level+1) + if err != nil { + return + } + files = append(files, _files...) + } + return + } + +} diff --git a/io.go b/io.go index 375a1e5..f69242c 100644 --- a/io.go +++ b/io.go @@ -34,6 +34,7 @@ type IO[C IOConfig, S IIO] struct { io.Closer `json:"-"` Args url.Values Config *C + Spesic S } func (io *IO[C, S]) IsClosed() bool { diff --git a/plugin.go b/plugin.go index 7c331d3..0324c16 100644 --- a/plugin.go +++ b/plugin.go @@ -188,7 +188,7 @@ func (opt *Plugin) Subscribe(streamPath string, sub ISubscriber) error { func (opt *Plugin) SubscribeBlock(streamPath string, sub ISubscriber) (err error) { if err = opt.Subscribe(streamPath, sub); err == nil { - sub.PlayBlock(sub) + sub.PlayBlock() } return } diff --git a/stream.go b/stream.go index 1f0fcc7..ef7f6c5 100644 --- a/stream.go +++ b/stream.go @@ -276,6 +276,7 @@ func (s *Stream) run() { } if s.action(ACTION_PUBLISH) { io := v.Value.getIO() + io.Spesic = v.Value io.Stream = s io.StartTime = time.Now() io.Logger = s.With(zap.String("type", io.Type)) @@ -298,6 +299,7 @@ func (s *Stream) run() { } suber := v.Value io := suber.getIO() + io.Spesic = suber s.Subscribers = append(s.Subscribers, suber) sbConfig := io.Config if wt := sbConfig.WaitTimeout.Duration(); wt > s.WaitTimeout { diff --git a/subscriber.go b/subscriber.go index 6430337..ec7a2ed 100644 --- a/subscriber.go +++ b/subscriber.go @@ -64,7 +64,7 @@ type ISubscriber interface { getIO() *IO[config.Subscribe, ISubscriber] GetConfig() *config.Subscribe IsPlaying() bool - PlayBlock(ISubscriber) + PlayBlock() Stop() } type TrackPlayer struct { @@ -197,7 +197,12 @@ func (s *Subscriber) Play(spesic ISubscriber) func() error { } //PlayBlock 阻塞式读取数据 -func (s *Subscriber) PlayBlock(spesic ISubscriber) { +func (s *Subscriber) PlayBlock() { + spesic := s.Spesic + if spesic == nil { + s.Error("play before subscribe") + return + } s.Info("playblock") var t time.Time var startTime time.Time //读到第一个关键帧的时间