feat: add subscriber type

This commit is contained in:
langhuihui
2024-12-18 13:23:10 +08:00
parent 0042568dff
commit 6037cbe18d
19 changed files with 1309 additions and 722 deletions

74
api.go
View File

@@ -48,7 +48,7 @@ func (s *Server) SysInfo(context.Context, *emptypb.Empty) (res *pb.SysInfoRespon
Data: &pb.SysInfoData{
Version: Version,
LocalIP: localIP,
PublicIP: util.GetPublicIP(localIP),
PublicIP: util.GetPublicIP(""),
StartTime: timestamppb.New(s.StartTime),
GoVersion: runtime.Version(),
Os: runtime.GOOS,
@@ -168,9 +168,23 @@ func (s *Server) getStreamInfo(pub *Publisher) (res *pb.StreamInfoResponse, err
}
func (s *Server) StreamInfo(ctx context.Context, req *pb.StreamSnapRequest) (res *pb.StreamInfoResponse, err error) {
recording := false
s.Records.Call(func() error {
for record := range s.Records.Range {
if record.StreamPath == req.StreamPath {
recording = true
break
}
}
return nil
})
s.Streams.Call(func() error {
if pub, ok := s.Streams.Get(req.StreamPath); ok {
res, err = s.getStreamInfo(pub)
if err != nil {
return err
}
res.Data.Recording = recording
} else {
err = pkg.ErrNotFound
}
@@ -233,10 +247,6 @@ func (s *Server) RestartTask(ctx context.Context, req *pb.RequestWithId64) (resp
}
func (s *Server) GetRecording(ctx context.Context, req *emptypb.Empty) (resp *pb.RecordingListResponse, err error) {
if s.DB == nil {
err = pkg.ErrNoDB
return
}
s.Records.Call(func() error {
resp = &pb.RecordingListResponse{}
for record := range s.Records.Range {
@@ -244,6 +254,7 @@ func (s *Server) GetRecording(ctx context.Context, req *emptypb.Empty) (resp *pb
StreamPath: record.StreamPath,
StartTime: timestamppb.New(record.StartTime),
Type: reflect.TypeOf(record.recorder).String(),
Pointer: uint64(uintptr(unsafe.Pointer(record.GetTask()))),
})
}
return nil
@@ -345,7 +356,14 @@ func (s *Server) api_VideoTrack_SSE(rw http.ResponseWriter, r *http.Request) {
if r.URL.RawQuery != "" {
streamPath += "?" + r.URL.RawQuery
}
suber, err := s.Subscribe(r.Context(), streamPath)
suber, err := s.SubscribeWithConfig(r.Context(), streamPath, config.Subscribe{
SubVideo: true,
})
if err != nil {
http.Error(rw, err.Error(), http.StatusBadRequest)
return
}
suber.Type = SubscribeTypeAPI
sse := util.NewSSE(rw, r.Context())
PlayBlock(suber, (func(frame *pkg.AVFrame) (err error))(nil), func(frame *pkg.AVFrame) (err error) {
var snap pb.TrackSnapShot
@@ -369,6 +387,42 @@ func (s *Server) api_VideoTrack_SSE(rw http.ResponseWriter, r *http.Request) {
}
}
func (s *Server) api_AudioTrack_SSE(rw http.ResponseWriter, r *http.Request) {
streamPath := r.PathValue("streamPath")
if r.URL.RawQuery != "" {
streamPath += "?" + r.URL.RawQuery
}
suber, err := s.SubscribeWithConfig(r.Context(), streamPath, config.Subscribe{
SubAudio: true,
})
if err != nil {
http.Error(rw, err.Error(), http.StatusBadRequest)
return
}
suber.Type = SubscribeTypeAPI
sse := util.NewSSE(rw, r.Context())
PlayBlock(suber, func(frame *pkg.AVFrame) (err error) {
var snap pb.TrackSnapShot
snap.Sequence = frame.Sequence
snap.Timestamp = uint32(frame.Timestamp / time.Millisecond)
snap.WriteTime = timestamppb.New(frame.WriteTime)
snap.Wrap = make([]*pb.Wrap, len(frame.Wraps))
snap.KeyFrame = frame.IDR
for i, wrap := range frame.Wraps {
snap.Wrap[i] = &pb.Wrap{
Timestamp: uint32(wrap.GetTimestamp() / time.Millisecond),
Size: uint32(wrap.GetSize()),
Data: wrap.String(),
}
}
return sse.WriteJSON(&snap)
}, (func(frame *pkg.AVFrame) (err error))(nil))
if err != nil {
http.Error(rw, err.Error(), http.StatusBadRequest)
return
}
}
func (s *Server) VideoTrackSnap(ctx context.Context, req *pb.StreamSnapRequest) (res *pb.TrackSnapShotResponse, err error) {
s.Streams.Call(func() error {
if pub, ok := s.Streams.Get(req.StreamPath); ok && pub.HasVideoTrack() {
@@ -510,6 +564,13 @@ func (s *Server) StopPublish(ctx context.Context, req *pb.StreamSnapRequest) (re
// /api/stream/list
func (s *Server) StreamList(_ context.Context, req *pb.StreamListRequest) (res *pb.StreamListResponse, err error) {
recordingSet := make(map[string]struct{})
s.Records.Call(func() error {
for record := range s.Records.Range {
recordingSet[record.StreamPath] = struct{}{}
}
return nil
})
s.Streams.Call(func() error {
var streams []*pb.StreamInfo
for publisher := range s.Streams.Range {
@@ -517,6 +578,7 @@ func (s *Server) StreamList(_ context.Context, req *pb.StreamListRequest) (res *
if err != nil {
continue
}
_, info.Data.Recording = recordingSet[info.Data.Path]
streams = append(streams, info.Data)
}
res = &pb.StreamListResponse{Data: streams, Total: int32(s.Streams.Length), PageNum: req.PageNum, PageSize: req.PageSize}

View File

@@ -7,10 +7,13 @@ srt:
listenaddr: :6000
passphrase: foobarfoobar
gb28181:
enable: false
autoinvite: true
sip:
listenaddr:
- udp::5060
# pull:
# live/test: dump/34020000001320000001
onsub:
pull:
.* : $0

File diff suppressed because it is too large Load Diff

View File

@@ -381,6 +381,7 @@ message StreamInfo {
float speed = 12;
google.protobuf.Duration bufferTime = 13;
bool stopOnIdle = 14;
bool recording = 15;
}
message Wrap {
@@ -578,6 +579,7 @@ message Recording {
string streamPath = 1;
google.protobuf.Timestamp startTime = 2;
string type = 3;
uint64 pointer = 4;
}
message RecordingListResponse {

View File

@@ -54,7 +54,6 @@ type (
WaitTimeout time.Duration `default:"10s" desc:"等待流超时时间"` // 等待流超时
WriteBufferSize int `desc:"写缓冲大小"` // 写缓冲大小
Key string `desc:"订阅鉴权key"` // 订阅鉴权key
Internal bool `default:"false" desc:"是否内部订阅"` // 是否内部订阅
}
HTTPValus map[string][]string
Pull struct {

View File

@@ -5,6 +5,7 @@ import "errors"
var (
ErrNotFound = errors.New("not found")
ErrStreamExist = errors.New("stream exist")
ErrRecordExists = errors.New("record exists")
ErrKick = errors.New("kick")
ErrDiscard = errors.New("discard")
ErrPublishTimeout = errors.New("publish timeout")

View File

@@ -279,12 +279,14 @@ var ipReg = regexp.MustCompile(`^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(2
var privateIPReg = regexp.MustCompile(`^((10|192\.168|172\.(1[6-9]|2[0-9]|3[0-1]))\.){3}(10|192\.168|172\.(1[6-9]|2[0-9]|3[0-1]))$`)
var routes map[string]string
var PublicIP string
func IsPrivateIP(ip string) bool {
return privateIPReg.MatchString(ip)
}
func initRoutes() {
PublicIP = myip.ExternalIP()
for k, v := range myip.LocalAndInternalIPs() {
routes[k] = v
if lastdot := strings.LastIndex(k, "."); lastdot >= 0 {
@@ -304,6 +306,9 @@ func init() {
func GetPublicIP(ip string) string {
initRoutesWait.Wait()
if ip == "" {
return PublicIP
}
if publicIP, ok := routes[ip]; ok {
return publicIP
}

View File

@@ -3,6 +3,7 @@ package m7s
import (
"bytes"
"context"
"crypto/md5"
"encoding/json"
"fmt"
"net"
@@ -12,6 +13,7 @@ import (
"path/filepath"
"reflect"
"runtime"
"strconv"
"strings"
"time"
@@ -495,6 +497,24 @@ func (p *Plugin) OnPublish(pub *Publisher) {
}
}
}
func (p *Plugin) auth(streamPath string, key string, secret string, expire string) (err error) {
if unixTime, err := strconv.ParseInt(expire, 16, 64); err != nil || time.Now().Unix() > unixTime {
return fmt.Errorf("auth failed expired")
}
if len(secret) != 32 {
return fmt.Errorf("auth failed secret length must be 32")
}
trueSecret := md5.Sum([]byte(key + streamPath + expire))
for i := 0; i < 16; i++ {
hex, err := strconv.ParseInt(secret[i<<1:(i<<1)+2], 16, 16)
if trueSecret[i] != byte(hex) || err != nil {
return fmt.Errorf("auth failed invalid secret")
}
}
return nil
}
func (p *Plugin) OnSubscribe(streamPath string, args url.Values) {
// var avoidTrans bool
//AVOID:
@@ -544,6 +564,11 @@ func (p *Plugin) PublishWithConfig(ctx context.Context, streamPath string, conf
p.Warn("auth failed", "error", err)
return
}
} else if conf.Key != "" {
if err = p.auth(streamPath, conf.Key, publisher.Args.Get("secret"), publisher.Args.Get("expire")); err != nil {
p.Warn("auth failed", "error", err)
return
}
}
}
err = p.Server.Streams.AddTask(publisher, ctx).WaitStarted()
@@ -566,6 +591,11 @@ func (p *Plugin) SubscribeWithConfig(ctx context.Context, streamPath string, con
p.Warn("auth failed", "error", err)
return
}
} else if conf.Key != "" {
if err = p.auth(streamPath, conf.Key, subscriber.Args.Get("secret"), subscriber.Args.Get("expire")); err != nil {
p.Warn("auth failed", "error", err)
return
}
}
}
err = p.Server.Streams.AddTask(subscriber, ctx).WaitStarted()
@@ -597,10 +627,11 @@ func (p *Plugin) Push(streamPath string, conf config.Push, subConf *config.Subsc
pusher.GetPushJob().Init(pusher, p, streamPath, conf, subConf)
}
func (p *Plugin) Record(pub *Publisher, conf config.Record, subConf *config.Subscribe) {
func (p *Plugin) Record(pub *Publisher, conf config.Record, subConf *config.Subscribe) *RecordJob {
recorder := p.Meta.Recorder()
job := recorder.GetRecordJob().Init(recorder, p, pub.StreamPath, conf, subConf)
job.Depend(pub)
return job
}
func (p *Plugin) Transform(pub *Publisher, conf config.Transform) {

View File

@@ -10,6 +10,7 @@ import (
"path/filepath"
"strings"
"time"
"unsafe"
"github.com/mcuadros/go-defaults"
"m7s.live/v5/pkg/config"
@@ -294,33 +295,60 @@ func (p *MP4Plugin) download(w http.ResponseWriter, r *http.Request) {
}
}
func (p *MP4Plugin) StartRecord(ctx context.Context, req *pb.ReqStartRecord) (res *pb.ResponseStartRecord, err error) {
var recordExists bool
res = &pb.ResponseStartRecord{}
p.Server.Records.Call(func() error {
_, recordExists = p.Server.Records.Find(func(job *m7s.RecordJob) bool {
return job.StreamPath == req.StreamPath && job.FilePath == req.FilePath
})
return nil
})
if recordExists {
err = pkg.ErrRecordExists
return
}
p.Server.Streams.Call(func() error {
if stream, ok := p.Server.Streams.Get(req.StreamPath); ok {
recordConf := config.Record{
Append: false,
Fragment: req.Fragment.AsDuration(),
FilePath: req.FilePath,
}
job := p.Record(stream, recordConf, nil)
res.Data = uint64(uintptr(unsafe.Pointer(job.GetTask())))
}
return nil
})
return
}
func (p *MP4Plugin) EventStart(ctx context.Context, req *pb.ReqEventRecord) (res *pb.ResponseEventRecord, err error) {
beforeDuration := p.BeforeDuration
afterDuration := p.AfterDuration
res = &pb.ResponseEventRecord{}
if req.BeforeDuration != "" {
beforeDuration, err = time.ParseDuration(req.BeforeDuration)
if err != nil {
p.Info("error", err)
p.Error("EventStart", "error", err)
}
}
if req.AfterDuration != "" {
afterDuration, err = time.ParseDuration(req.AfterDuration)
if err != nil {
p.Info("error", err)
p.Error("EventStart", "error", err)
}
}
recorder := p.Meta.Recorder()
recorderJobs := p.Server.Records
var tmpJob *m7s.RecordJob
if recorderJobs.Length > 0 {
for job := range recorderJobs.Range {
if job.StreamPath == req.StreamPath {
tmpJob = job
}
}
}
p.Server.Records.Call(func() error {
tmpJob, _ = p.Server.Records.Find(func(job *m7s.RecordJob) bool {
return job.StreamPath == req.StreamPath
})
return nil
})
if tmpJob == nil { //为空表示没有正在进行的录制,也就是没有自动录像,则进行正常的事件录像
p.Server.Streams.Call(func() error {
if stream, ok := p.Server.Streams.Get(req.StreamPath); ok {
recordConf := config.Record{
Append: false,
@@ -334,13 +362,14 @@ func (p *MP4Plugin) EventStart(ctx context.Context, req *pb.ReqEventRecord) (res
recordJob.EventDesc = req.EventDesc
recordJob.AfterDuration = afterDuration
recordJob.BeforeDuration = beforeDuration
recordJob.RecordMode = "1"
recordJob.RecordMode = m7s.RecordModeEvent
var subconfig config.Subscribe
defaults.SetDefaults(&subconfig)
subconfig.BufferTime = beforeDuration
job := recorder.GetRecordJob().Init(recorder, &p.Plugin, stream.StreamPath, recordConf, &subconfig)
job.Depend(stream)
p.Record(stream, recordConf, &subconfig)
}
return nil
})
} else {
if tmpJob.AfterDuration != 0 { //当前有事件录像正在录制,则更新该录像的结束时间
tmpJob.AfterDuration = time.Duration(tmpJob.Subscriber.VideoReader.AbsTime)*time.Millisecond + afterDuration
@@ -351,7 +380,7 @@ func (p *MP4Plugin) EventStart(ctx context.Context, req *pb.ReqEventRecord) (res
EventLevel: req.EventLevel,
EventDesc: req.EventDesc,
EventName: req.EventName,
RecordMode: "1",
RecordMode: m7s.RecordModeEvent,
BeforeDuration: beforeDuration,
AfterDuration: afterDuration,
}

View File

@@ -1,7 +1,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.35.2
// protoc v5.28.3
// protoc-gen-go v1.28.1
// protoc v3.19.1
// source: mp4.proto
package pb
@@ -10,6 +10,7 @@ import (
_ "google.golang.org/genproto/googleapis/api/annotations"
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
durationpb "google.golang.org/protobuf/types/known/durationpb"
emptypb "google.golang.org/protobuf/types/known/emptypb"
timestamppb "google.golang.org/protobuf/types/known/timestamppb"
reflect "reflect"
@@ -39,9 +40,11 @@ type ReqRecordList struct {
func (x *ReqRecordList) Reset() {
*x = ReqRecordList{}
if protoimpl.UnsafeEnabled {
mi := &file_mp4_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *ReqRecordList) String() string {
@@ -52,7 +55,7 @@ func (*ReqRecordList) ProtoMessage() {}
func (x *ReqRecordList) ProtoReflect() protoreflect.Message {
mi := &file_mp4_proto_msgTypes[0]
if x != nil {
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@@ -130,9 +133,11 @@ type RecordFile struct {
func (x *RecordFile) Reset() {
*x = RecordFile{}
if protoimpl.UnsafeEnabled {
mi := &file_mp4_proto_msgTypes[1]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *RecordFile) String() string {
@@ -143,7 +148,7 @@ func (*RecordFile) ProtoMessage() {}
func (x *RecordFile) ProtoReflect() protoreflect.Message {
mi := &file_mp4_proto_msgTypes[1]
if x != nil {
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@@ -208,9 +213,11 @@ type ResponseList struct {
func (x *ResponseList) Reset() {
*x = ResponseList{}
if protoimpl.UnsafeEnabled {
mi := &file_mp4_proto_msgTypes[2]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *ResponseList) String() string {
@@ -221,7 +228,7 @@ func (*ResponseList) ProtoMessage() {}
func (x *ResponseList) ProtoReflect() protoreflect.Message {
mi := &file_mp4_proto_msgTypes[2]
if x != nil {
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@@ -291,9 +298,11 @@ type Catalog struct {
func (x *Catalog) Reset() {
*x = Catalog{}
if protoimpl.UnsafeEnabled {
mi := &file_mp4_proto_msgTypes[3]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *Catalog) String() string {
@@ -304,7 +313,7 @@ func (*Catalog) ProtoMessage() {}
func (x *Catalog) ProtoReflect() protoreflect.Message {
mi := &file_mp4_proto_msgTypes[3]
if x != nil {
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@@ -359,9 +368,11 @@ type ResponseCatalog struct {
func (x *ResponseCatalog) Reset() {
*x = ResponseCatalog{}
if protoimpl.UnsafeEnabled {
mi := &file_mp4_proto_msgTypes[4]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *ResponseCatalog) String() string {
@@ -372,7 +383,7 @@ func (*ResponseCatalog) ProtoMessage() {}
func (x *ResponseCatalog) ProtoReflect() protoreflect.Message {
mi := &file_mp4_proto_msgTypes[4]
if x != nil {
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@@ -422,9 +433,11 @@ type ReqRecordDelete struct {
func (x *ReqRecordDelete) Reset() {
*x = ReqRecordDelete{}
if protoimpl.UnsafeEnabled {
mi := &file_mp4_proto_msgTypes[5]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *ReqRecordDelete) String() string {
@@ -435,7 +448,7 @@ func (*ReqRecordDelete) ProtoMessage() {}
func (x *ReqRecordDelete) ProtoReflect() protoreflect.Message {
mi := &file_mp4_proto_msgTypes[5]
if x != nil {
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@@ -497,9 +510,11 @@ type ResponseDelete struct {
func (x *ResponseDelete) Reset() {
*x = ResponseDelete{}
if protoimpl.UnsafeEnabled {
mi := &file_mp4_proto_msgTypes[6]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *ResponseDelete) String() string {
@@ -510,7 +525,7 @@ func (*ResponseDelete) ProtoMessage() {}
func (x *ResponseDelete) ProtoReflect() protoreflect.Message {
mi := &file_mp4_proto_msgTypes[6]
if x != nil {
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@@ -553,7 +568,7 @@ type ReqEventRecord struct {
StreamPath string `protobuf:"bytes,1,opt,name=streamPath,proto3" json:"streamPath,omitempty"`
EventId string `protobuf:"bytes,2,opt,name=eventId,proto3" json:"eventId,omitempty"`
RecordMode string `protobuf:"bytes,3,opt,name=recordMode,proto3" json:"recordMode,omitempty"` //0=连续录像模式,1=事件录像模式
RecordMode string `protobuf:"bytes,3,opt,name=recordMode,proto3" json:"recordMode,omitempty"` //auto=连续录像模式,event=事件录像模式
EventName string `protobuf:"bytes,4,opt,name=eventName,proto3" json:"eventName,omitempty"`
BeforeDuration string `protobuf:"bytes,5,opt,name=beforeDuration,proto3" json:"beforeDuration,omitempty"`
AfterDuration string `protobuf:"bytes,6,opt,name=afterDuration,proto3" json:"afterDuration,omitempty"`
@@ -564,9 +579,11 @@ type ReqEventRecord struct {
func (x *ReqEventRecord) Reset() {
*x = ReqEventRecord{}
if protoimpl.UnsafeEnabled {
mi := &file_mp4_proto_msgTypes[7]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *ReqEventRecord) String() string {
@@ -577,7 +594,7 @@ func (*ReqEventRecord) ProtoMessage() {}
func (x *ReqEventRecord) ProtoReflect() protoreflect.Message {
mi := &file_mp4_proto_msgTypes[7]
if x != nil {
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@@ -662,14 +679,16 @@ type ResponseEventRecord struct {
Code int32 `protobuf:"varint,1,opt,name=code,proto3" json:"code,omitempty"`
Message string `protobuf:"bytes,2,opt,name=message,proto3" json:"message,omitempty"`
Id uint32 `protobuf:"varint,3,opt,name=id,proto3" json:"id,omitempty"`
Data uint32 `protobuf:"varint,3,opt,name=data,proto3" json:"data,omitempty"`
}
func (x *ResponseEventRecord) Reset() {
*x = ResponseEventRecord{}
if protoimpl.UnsafeEnabled {
mi := &file_mp4_proto_msgTypes[8]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *ResponseEventRecord) String() string {
@@ -680,7 +699,7 @@ func (*ResponseEventRecord) ProtoMessage() {}
func (x *ResponseEventRecord) ProtoReflect() protoreflect.Message {
mi := &file_mp4_proto_msgTypes[8]
if x != nil {
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@@ -709,9 +728,135 @@ func (x *ResponseEventRecord) GetMessage() string {
return ""
}
func (x *ResponseEventRecord) GetId() uint32 {
func (x *ResponseEventRecord) GetData() uint32 {
if x != nil {
return x.Id
return x.Data
}
return 0
}
type ReqStartRecord struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
StreamPath string `protobuf:"bytes,1,opt,name=streamPath,proto3" json:"streamPath,omitempty"`
Fragment *durationpb.Duration `protobuf:"bytes,2,opt,name=fragment,proto3" json:"fragment,omitempty"`
FilePath string `protobuf:"bytes,3,opt,name=filePath,proto3" json:"filePath,omitempty"`
}
func (x *ReqStartRecord) Reset() {
*x = ReqStartRecord{}
if protoimpl.UnsafeEnabled {
mi := &file_mp4_proto_msgTypes[9]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *ReqStartRecord) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*ReqStartRecord) ProtoMessage() {}
func (x *ReqStartRecord) ProtoReflect() protoreflect.Message {
mi := &file_mp4_proto_msgTypes[9]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use ReqStartRecord.ProtoReflect.Descriptor instead.
func (*ReqStartRecord) Descriptor() ([]byte, []int) {
return file_mp4_proto_rawDescGZIP(), []int{9}
}
func (x *ReqStartRecord) GetStreamPath() string {
if x != nil {
return x.StreamPath
}
return ""
}
func (x *ReqStartRecord) GetFragment() *durationpb.Duration {
if x != nil {
return x.Fragment
}
return nil
}
func (x *ReqStartRecord) GetFilePath() string {
if x != nil {
return x.FilePath
}
return ""
}
type ResponseStartRecord struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Code int32 `protobuf:"varint,1,opt,name=code,proto3" json:"code,omitempty"`
Message string `protobuf:"bytes,2,opt,name=message,proto3" json:"message,omitempty"`
Data uint64 `protobuf:"varint,3,opt,name=data,proto3" json:"data,omitempty"`
}
func (x *ResponseStartRecord) Reset() {
*x = ResponseStartRecord{}
if protoimpl.UnsafeEnabled {
mi := &file_mp4_proto_msgTypes[10]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *ResponseStartRecord) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*ResponseStartRecord) ProtoMessage() {}
func (x *ResponseStartRecord) ProtoReflect() protoreflect.Message {
mi := &file_mp4_proto_msgTypes[10]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use ResponseStartRecord.ProtoReflect.Descriptor instead.
func (*ResponseStartRecord) Descriptor() ([]byte, []int) {
return file_mp4_proto_rawDescGZIP(), []int{10}
}
func (x *ResponseStartRecord) GetCode() int32 {
if x != nil {
return x.Code
}
return 0
}
func (x *ResponseStartRecord) GetMessage() string {
if x != nil {
return x.Message
}
return ""
}
func (x *ResponseStartRecord) GetData() uint64 {
if x != nil {
return x.Data
}
return 0
}
@@ -725,7 +870,9 @@ var file_mp4_proto_rawDesc = []byte{
0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f,
0x65, 0x6d, 0x70, 0x74, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1f, 0x67, 0x6f, 0x6f,
0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x74, 0x69, 0x6d,
0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xc3, 0x01, 0x0a,
0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1e, 0x67, 0x6f,
0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x64, 0x75,
0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xc3, 0x01, 0x0a,
0x0d, 0x52, 0x65, 0x71, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x1e,
0x0a, 0x0a, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x50, 0x61, 0x74, 0x68, 0x18, 0x01, 0x20, 0x01,
0x28, 0x09, 0x52, 0x0a, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x50, 0x61, 0x74, 0x68, 0x12, 0x14,
@@ -814,38 +961,57 @@ var file_mp4_proto_rawDesc = []byte{
0x65, 0x76, 0x65, 0x6e, 0x74, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09,
0x52, 0x0a, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x12, 0x1a, 0x0a, 0x08,
0x66, 0x72, 0x61, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08,
0x66, 0x72, 0x61, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x22, 0x53, 0x0a, 0x13, 0x52, 0x65, 0x73, 0x70,
0x66, 0x72, 0x61, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x22, 0x57, 0x0a, 0x13, 0x52, 0x65, 0x73, 0x70,
0x6f, 0x6e, 0x73, 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x12,
0x12, 0x0a, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x04, 0x63,
0x6f, 0x64, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x02,
0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x0e, 0x0a,
0x02, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x02, 0x69, 0x64, 0x32, 0xed, 0x02,
0x0a, 0x03, 0x61, 0x70, 0x69, 0x12, 0x54, 0x0a, 0x04, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x12, 0x2e,
0x6d, 0x70, 0x34, 0x2e, 0x52, 0x65, 0x71, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x4c, 0x69, 0x73,
0x74, 0x1a, 0x11, 0x2e, 0x6d, 0x70, 0x34, 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
0x4c, 0x69, 0x73, 0x74, 0x22, 0x25, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1f, 0x12, 0x1d, 0x2f, 0x6d,
0x70, 0x34, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x6c, 0x69, 0x73, 0x74, 0x2f, 0x7b, 0x73, 0x74, 0x72,
0x65, 0x61, 0x6d, 0x50, 0x61, 0x74, 0x68, 0x3d, 0x2a, 0x2a, 0x7d, 0x12, 0x51, 0x0a, 0x07, 0x43,
0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e,
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x14,
0x2e, 0x6d, 0x70, 0x34, 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x43, 0x61, 0x74,
0x61, 0x6c, 0x6f, 0x67, 0x22, 0x18, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x12, 0x12, 0x10, 0x2f, 0x6d,
0x70, 0x34, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x12, 0x5f,
0x0a, 0x06, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x12, 0x14, 0x2e, 0x6d, 0x70, 0x34, 0x2e, 0x52,
0x65, 0x71, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x1a, 0x13,
0x2e, 0x6d, 0x70, 0x34, 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x44, 0x65, 0x6c,
0x65, 0x74, 0x65, 0x22, 0x2a, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x24, 0x3a, 0x01, 0x2a, 0x22, 0x1f,
0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x12, 0x0a,
0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x04, 0x64, 0x61, 0x74,
0x61, 0x22, 0x83, 0x01, 0x0a, 0x0e, 0x52, 0x65, 0x71, 0x53, 0x74, 0x61, 0x72, 0x74, 0x52, 0x65,
0x63, 0x6f, 0x72, 0x64, 0x12, 0x1e, 0x0a, 0x0a, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x50, 0x61,
0x74, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d,
0x50, 0x61, 0x74, 0x68, 0x12, 0x35, 0x0a, 0x08, 0x66, 0x72, 0x61, 0x67, 0x6d, 0x65, 0x6e, 0x74,
0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e,
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f,
0x6e, 0x52, 0x08, 0x66, 0x72, 0x61, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x66,
0x69, 0x6c, 0x65, 0x50, 0x61, 0x74, 0x68, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x66,
0x69, 0x6c, 0x65, 0x50, 0x61, 0x74, 0x68, 0x22, 0x57, 0x0a, 0x13, 0x52, 0x65, 0x73, 0x70, 0x6f,
0x6e, 0x73, 0x65, 0x53, 0x74, 0x61, 0x72, 0x74, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x12, 0x12,
0x0a, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x04, 0x63, 0x6f,
0x64, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x02, 0x20,
0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x12, 0x0a, 0x04,
0x64, 0x61, 0x74, 0x61, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61,
0x32, 0xc6, 0x03, 0x0a, 0x03, 0x61, 0x70, 0x69, 0x12, 0x54, 0x0a, 0x04, 0x4c, 0x69, 0x73, 0x74,
0x12, 0x12, 0x2e, 0x6d, 0x70, 0x34, 0x2e, 0x52, 0x65, 0x71, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64,
0x4c, 0x69, 0x73, 0x74, 0x1a, 0x11, 0x2e, 0x6d, 0x70, 0x34, 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f,
0x6e, 0x73, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x22, 0x25, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1f, 0x12,
0x1d, 0x2f, 0x6d, 0x70, 0x34, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x6c, 0x69, 0x73, 0x74, 0x2f, 0x7b,
0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x50, 0x61, 0x74, 0x68, 0x3d, 0x2a, 0x2a, 0x7d, 0x12, 0x51,
0x0a, 0x07, 0x43, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67,
0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74,
0x79, 0x1a, 0x14, 0x2e, 0x6d, 0x70, 0x34, 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
0x43, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x22, 0x18, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x12, 0x12,
0x10, 0x2f, 0x6d, 0x70, 0x34, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f,
0x67, 0x12, 0x5f, 0x0a, 0x06, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x12, 0x14, 0x2e, 0x6d, 0x70,
0x34, 0x2e, 0x52, 0x65, 0x71, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x44, 0x65, 0x6c, 0x65, 0x74,
0x65, 0x1a, 0x13, 0x2e, 0x6d, 0x70, 0x34, 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x22, 0x2a, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x24, 0x22, 0x1f,
0x2f, 0x6d, 0x70, 0x34, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x64, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x2f,
0x7b, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x50, 0x61, 0x74, 0x68, 0x3d, 0x2a, 0x2a, 0x7d, 0x12,
0x5c, 0x0a, 0x0a, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x53, 0x74, 0x61, 0x72, 0x74, 0x12, 0x13, 0x2e,
0x6d, 0x70, 0x34, 0x2e, 0x52, 0x65, 0x71, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x63, 0x6f,
0x72, 0x64, 0x1a, 0x18, 0x2e, 0x6d, 0x70, 0x34, 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x22, 0x1f, 0x82, 0xd3,
0xe4, 0x93, 0x02, 0x19, 0x3a, 0x01, 0x2a, 0x22, 0x14, 0x2f, 0x6d, 0x70, 0x34, 0x2f, 0x61, 0x70,
0x69, 0x2f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x2f, 0x73, 0x74, 0x61, 0x72, 0x74, 0x42, 0x1b, 0x5a,
0x19, 0x6d, 0x37, 0x73, 0x2e, 0x6c, 0x69, 0x76, 0x65, 0x2f, 0x76, 0x35, 0x2f, 0x70, 0x6c, 0x75,
0x67, 0x69, 0x6e, 0x2f, 0x6d, 0x70, 0x34, 0x2f, 0x70, 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74,
0x6f, 0x33,
0x7b, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x50, 0x61, 0x74, 0x68, 0x3d, 0x2a, 0x2a, 0x7d, 0x3a,
0x01, 0x2a, 0x12, 0x5c, 0x0a, 0x0a, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x53, 0x74, 0x61, 0x72, 0x74,
0x12, 0x13, 0x2e, 0x6d, 0x70, 0x34, 0x2e, 0x52, 0x65, 0x71, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x52,
0x65, 0x63, 0x6f, 0x72, 0x64, 0x1a, 0x18, 0x2e, 0x6d, 0x70, 0x34, 0x2e, 0x52, 0x65, 0x73, 0x70,
0x6f, 0x6e, 0x73, 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x22,
0x1f, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x19, 0x22, 0x14, 0x2f, 0x6d, 0x70, 0x34, 0x2f, 0x61, 0x70,
0x69, 0x2f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x2f, 0x73, 0x74, 0x61, 0x72, 0x74, 0x3a, 0x01, 0x2a,
0x12, 0x57, 0x0a, 0x0b, 0x53, 0x74, 0x61, 0x72, 0x74, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x12,
0x13, 0x2e, 0x6d, 0x70, 0x34, 0x2e, 0x52, 0x65, 0x71, 0x53, 0x74, 0x61, 0x72, 0x74, 0x52, 0x65,
0x63, 0x6f, 0x72, 0x64, 0x1a, 0x18, 0x2e, 0x6d, 0x70, 0x34, 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f,
0x6e, 0x73, 0x65, 0x53, 0x74, 0x61, 0x72, 0x74, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x22, 0x19,
0x82, 0xd3, 0xe4, 0x93, 0x02, 0x13, 0x22, 0x0e, 0x2f, 0x6d, 0x70, 0x34, 0x2f, 0x61, 0x70, 0x69,
0x2f, 0x73, 0x74, 0x61, 0x72, 0x74, 0x3a, 0x01, 0x2a, 0x42, 0x1b, 0x5a, 0x19, 0x6d, 0x37, 0x73,
0x2e, 0x6c, 0x69, 0x76, 0x65, 0x2f, 0x76, 0x35, 0x2f, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2f,
0x6d, 0x70, 0x34, 0x2f, 0x70, 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}
var (
@@ -860,8 +1026,8 @@ func file_mp4_proto_rawDescGZIP() []byte {
return file_mp4_proto_rawDescData
}
var file_mp4_proto_msgTypes = make([]protoimpl.MessageInfo, 9)
var file_mp4_proto_goTypes = []any{
var file_mp4_proto_msgTypes = make([]protoimpl.MessageInfo, 11)
var file_mp4_proto_goTypes = []interface{}{
(*ReqRecordList)(nil), // 0: mp4.ReqRecordList
(*RecordFile)(nil), // 1: mp4.RecordFile
(*ResponseList)(nil), // 2: mp4.ResponseList
@@ -871,30 +1037,36 @@ var file_mp4_proto_goTypes = []any{
(*ResponseDelete)(nil), // 6: mp4.ResponseDelete
(*ReqEventRecord)(nil), // 7: mp4.ReqEventRecord
(*ResponseEventRecord)(nil), // 8: mp4.ResponseEventRecord
(*timestamppb.Timestamp)(nil), // 9: google.protobuf.Timestamp
(*emptypb.Empty)(nil), // 10: google.protobuf.Empty
(*ReqStartRecord)(nil), // 9: mp4.ReqStartRecord
(*ResponseStartRecord)(nil), // 10: mp4.ResponseStartRecord
(*timestamppb.Timestamp)(nil), // 11: google.protobuf.Timestamp
(*durationpb.Duration)(nil), // 12: google.protobuf.Duration
(*emptypb.Empty)(nil), // 13: google.protobuf.Empty
}
var file_mp4_proto_depIdxs = []int32{
9, // 0: mp4.RecordFile.startTime:type_name -> google.protobuf.Timestamp
9, // 1: mp4.RecordFile.endTime:type_name -> google.protobuf.Timestamp
11, // 0: mp4.RecordFile.startTime:type_name -> google.protobuf.Timestamp
11, // 1: mp4.RecordFile.endTime:type_name -> google.protobuf.Timestamp
1, // 2: mp4.ResponseList.data:type_name -> mp4.RecordFile
9, // 3: mp4.Catalog.startTime:type_name -> google.protobuf.Timestamp
9, // 4: mp4.Catalog.endTime:type_name -> google.protobuf.Timestamp
11, // 3: mp4.Catalog.startTime:type_name -> google.protobuf.Timestamp
11, // 4: mp4.Catalog.endTime:type_name -> google.protobuf.Timestamp
3, // 5: mp4.ResponseCatalog.data:type_name -> mp4.Catalog
1, // 6: mp4.ResponseDelete.data:type_name -> mp4.RecordFile
0, // 7: mp4.api.List:input_type -> mp4.ReqRecordList
10, // 8: mp4.api.Catalog:input_type -> google.protobuf.Empty
5, // 9: mp4.api.Delete:input_type -> mp4.ReqRecordDelete
7, // 10: mp4.api.EventStart:input_type -> mp4.ReqEventRecord
2, // 11: mp4.api.List:output_type -> mp4.ResponseList
4, // 12: mp4.api.Catalog:output_type -> mp4.ResponseCatalog
6, // 13: mp4.api.Delete:output_type -> mp4.ResponseDelete
8, // 14: mp4.api.EventStart:output_type -> mp4.ResponseEventRecord
11, // [11:15] is the sub-list for method output_type
7, // [7:11] is the sub-list for method input_type
7, // [7:7] is the sub-list for extension type_name
7, // [7:7] is the sub-list for extension extendee
0, // [0:7] is the sub-list for field type_name
12, // 7: mp4.ReqStartRecord.fragment:type_name -> google.protobuf.Duration
0, // 8: mp4.api.List:input_type -> mp4.ReqRecordList
13, // 9: mp4.api.Catalog:input_type -> google.protobuf.Empty
5, // 10: mp4.api.Delete:input_type -> mp4.ReqRecordDelete
7, // 11: mp4.api.EventStart:input_type -> mp4.ReqEventRecord
9, // 12: mp4.api.StartRecord:input_type -> mp4.ReqStartRecord
2, // 13: mp4.api.List:output_type -> mp4.ResponseList
4, // 14: mp4.api.Catalog:output_type -> mp4.ResponseCatalog
6, // 15: mp4.api.Delete:output_type -> mp4.ResponseDelete
8, // 16: mp4.api.EventStart:output_type -> mp4.ResponseEventRecord
10, // 17: mp4.api.StartRecord:output_type -> mp4.ResponseStartRecord
13, // [13:18] is the sub-list for method output_type
8, // [8:13] is the sub-list for method input_type
8, // [8:8] is the sub-list for extension type_name
8, // [8:8] is the sub-list for extension extendee
0, // [0:8] is the sub-list for field type_name
}
func init() { file_mp4_proto_init() }
@@ -902,13 +1074,147 @@ func file_mp4_proto_init() {
if File_mp4_proto != nil {
return
}
if !protoimpl.UnsafeEnabled {
file_mp4_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*ReqRecordList); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_mp4_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*RecordFile); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_mp4_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*ResponseList); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_mp4_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*Catalog); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_mp4_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*ResponseCatalog); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_mp4_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*ReqRecordDelete); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_mp4_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*ResponseDelete); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_mp4_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*ReqEventRecord); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_mp4_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*ResponseEventRecord); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_mp4_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*ReqStartRecord); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_mp4_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*ResponseStartRecord); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
}
type x struct{}
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_mp4_proto_rawDesc,
NumEnums: 0,
NumMessages: 9,
NumMessages: 11,
NumExtensions: 0,
NumServices: 1,
},

View File

@@ -206,11 +206,36 @@ func local_request_Api_EventStart_0(ctx context.Context, marshaler runtime.Marsh
}
func request_Api_StartRecord_0(ctx context.Context, marshaler runtime.Marshaler, client ApiClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq ReqStartRecord
var metadata runtime.ServerMetadata
if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && err != io.EOF {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
msg, err := client.StartRecord(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
return msg, metadata, err
}
func local_request_Api_StartRecord_0(ctx context.Context, marshaler runtime.Marshaler, server ApiServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq ReqStartRecord
var metadata runtime.ServerMetadata
if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && err != io.EOF {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
msg, err := server.StartRecord(ctx, &protoReq)
return msg, metadata, err
}
// RegisterApiHandlerServer registers the http handlers for service Api to "mux".
// UnaryRPC :call ApiServer directly.
// StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906.
// Note that using this registration option will cause many gRPC library features to stop working. Consider using RegisterApiHandlerFromEndpoint instead.
// GRPC interceptors will not work for this type of registration. To use interceptors, you must use the "runtime.WithMiddlewares" option in the "runtime.NewServeMux" call.
func RegisterApiHandlerServer(ctx context.Context, mux *runtime.ServeMux, server ApiServer) error {
mux.Handle("GET", pattern_Api_List_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
@@ -313,27 +338,52 @@ func RegisterApiHandlerServer(ctx context.Context, mux *runtime.ServeMux, server
})
mux.Handle("POST", pattern_Api_StartRecord_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
var stream runtime.ServerTransportStream
ctx = grpc.NewContextWithServerTransportStream(ctx, &stream)
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
var err error
var annotatedContext context.Context
annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/mp4.Api/StartRecord", runtime.WithHTTPPathPattern("/mp4/api/start"))
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := local_request_Api_StartRecord_0(annotatedContext, inboundMarshaler, server, req, pathParams)
md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer())
annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md)
if err != nil {
runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
return
}
forward_Api_StartRecord_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
})
return nil
}
// RegisterApiHandlerFromEndpoint is same as RegisterApiHandler but
// automatically dials to "endpoint" and closes the connection when "ctx" gets done.
func RegisterApiHandlerFromEndpoint(ctx context.Context, mux *runtime.ServeMux, endpoint string, opts []grpc.DialOption) (err error) {
conn, err := grpc.NewClient(endpoint, opts...)
conn, err := grpc.DialContext(ctx, endpoint, opts...)
if err != nil {
return err
}
defer func() {
if err != nil {
if cerr := conn.Close(); cerr != nil {
grpclog.Errorf("Failed to close conn to %s: %v", endpoint, cerr)
grpclog.Infof("Failed to close conn to %s: %v", endpoint, cerr)
}
return
}
go func() {
<-ctx.Done()
if cerr := conn.Close(); cerr != nil {
grpclog.Errorf("Failed to close conn to %s: %v", endpoint, cerr)
grpclog.Infof("Failed to close conn to %s: %v", endpoint, cerr)
}
}()
}()
@@ -351,7 +401,7 @@ func RegisterApiHandler(ctx context.Context, mux *runtime.ServeMux, conn *grpc.C
// to "mux". The handlers forward requests to the grpc endpoint over the given implementation of "ApiClient".
// Note: the gRPC framework executes interceptors within the gRPC handler. If the passed in "ApiClient"
// doesn't go through the normal gRPC flow (creating a gRPC client etc.) then it will be up to the passed in
// "ApiClient" to call the correct interceptors. This client ignores the HTTP middlewares.
// "ApiClient" to call the correct interceptors.
func RegisterApiHandlerClient(ctx context.Context, mux *runtime.ServeMux, client ApiClient) error {
mux.Handle("GET", pattern_Api_List_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
@@ -442,6 +492,28 @@ func RegisterApiHandlerClient(ctx context.Context, mux *runtime.ServeMux, client
})
mux.Handle("POST", pattern_Api_StartRecord_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
var err error
var annotatedContext context.Context
annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/mp4.Api/StartRecord", runtime.WithHTTPPathPattern("/mp4/api/start"))
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := request_Api_StartRecord_0(annotatedContext, inboundMarshaler, client, req, pathParams)
annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md)
if err != nil {
runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
return
}
forward_Api_StartRecord_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
})
return nil
}
@@ -453,6 +525,8 @@ var (
pattern_Api_Delete_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 3, 0, 4, 1, 5, 3}, []string{"mp4", "api", "delete", "streamPath"}, ""))
pattern_Api_EventStart_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"mp4", "api", "event", "start"}, ""))
pattern_Api_StartRecord_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"mp4", "api", "start"}, ""))
)
var (
@@ -463,4 +537,6 @@ var (
forward_Api_Delete_0 = runtime.ForwardResponseMessage
forward_Api_EventStart_0 = runtime.ForwardResponseMessage
forward_Api_StartRecord_0 = runtime.ForwardResponseMessage
)

View File

@@ -2,6 +2,7 @@ syntax = "proto3";
import "google/api/annotations.proto";
import "google/protobuf/empty.proto";
import "google/protobuf/timestamp.proto";
import "google/protobuf/duration.proto";
package mp4;
option go_package="m7s.live/v5/plugin/mp4/pb";
@@ -28,6 +29,12 @@ service api {
body: "*"
};
}
rpc StartRecord (ReqStartRecord) returns (ResponseStartRecord) {
option (google.api.http) = {
post: "/mp4/api/start"
body: "*"
};
}
}
message ReqRecordList {
@@ -87,7 +94,7 @@ message ResponseDelete {
message ReqEventRecord {
string streamPath = 1;
string eventId = 2;
string recordMode = 3;//0=连续录像模式,1=事件录像模式
string recordMode = 3;//auto=连续录像模式,event=事件录像模式
string eventName = 4;
string beforeDuration = 5;
string afterDuration = 6;
@@ -99,5 +106,17 @@ message ReqEventRecord {
message ResponseEventRecord {
int32 code = 1;
string message = 2;
uint32 id = 3;
uint32 data = 3;
}
message ReqStartRecord {
string streamPath = 1;
google.protobuf.Duration fragment = 2;
string filePath = 3;
}
message ResponseStartRecord {
int32 code = 1;
string message = 2;
uint64 data = 3;
}

View File

@@ -1,7 +1,7 @@
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
// versions:
// - protoc-gen-go-grpc v1.5.1
// - protoc v5.28.3
// - protoc-gen-go-grpc v1.2.0
// - protoc v3.19.1
// source: mp4.proto
package pb
@@ -16,15 +16,8 @@ import (
// This is a compile-time assertion to ensure that this generated file
// is compatible with the grpc package it is being compiled against.
// Requires gRPC-Go v1.64.0 or later.
const _ = grpc.SupportPackageIsVersion9
const (
Api_List_FullMethodName = "/mp4.api/List"
Api_Catalog_FullMethodName = "/mp4.api/Catalog"
Api_Delete_FullMethodName = "/mp4.api/Delete"
Api_EventStart_FullMethodName = "/mp4.api/EventStart"
)
// Requires gRPC-Go v1.32.0 or later.
const _ = grpc.SupportPackageIsVersion7
// ApiClient is the client API for Api service.
//
@@ -34,6 +27,7 @@ type ApiClient interface {
Catalog(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*ResponseCatalog, error)
Delete(ctx context.Context, in *ReqRecordDelete, opts ...grpc.CallOption) (*ResponseDelete, error)
EventStart(ctx context.Context, in *ReqEventRecord, opts ...grpc.CallOption) (*ResponseEventRecord, error)
StartRecord(ctx context.Context, in *ReqStartRecord, opts ...grpc.CallOption) (*ResponseStartRecord, error)
}
type apiClient struct {
@@ -45,9 +39,8 @@ func NewApiClient(cc grpc.ClientConnInterface) ApiClient {
}
func (c *apiClient) List(ctx context.Context, in *ReqRecordList, opts ...grpc.CallOption) (*ResponseList, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(ResponseList)
err := c.cc.Invoke(ctx, Api_List_FullMethodName, in, out, cOpts...)
err := c.cc.Invoke(ctx, "/mp4.api/List", in, out, opts...)
if err != nil {
return nil, err
}
@@ -55,9 +48,8 @@ func (c *apiClient) List(ctx context.Context, in *ReqRecordList, opts ...grpc.Ca
}
func (c *apiClient) Catalog(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*ResponseCatalog, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(ResponseCatalog)
err := c.cc.Invoke(ctx, Api_Catalog_FullMethodName, in, out, cOpts...)
err := c.cc.Invoke(ctx, "/mp4.api/Catalog", in, out, opts...)
if err != nil {
return nil, err
}
@@ -65,9 +57,8 @@ func (c *apiClient) Catalog(ctx context.Context, in *emptypb.Empty, opts ...grpc
}
func (c *apiClient) Delete(ctx context.Context, in *ReqRecordDelete, opts ...grpc.CallOption) (*ResponseDelete, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(ResponseDelete)
err := c.cc.Invoke(ctx, Api_Delete_FullMethodName, in, out, cOpts...)
err := c.cc.Invoke(ctx, "/mp4.api/Delete", in, out, opts...)
if err != nil {
return nil, err
}
@@ -75,9 +66,17 @@ func (c *apiClient) Delete(ctx context.Context, in *ReqRecordDelete, opts ...grp
}
func (c *apiClient) EventStart(ctx context.Context, in *ReqEventRecord, opts ...grpc.CallOption) (*ResponseEventRecord, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(ResponseEventRecord)
err := c.cc.Invoke(ctx, Api_EventStart_FullMethodName, in, out, cOpts...)
err := c.cc.Invoke(ctx, "/mp4.api/EventStart", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *apiClient) StartRecord(ctx context.Context, in *ReqStartRecord, opts ...grpc.CallOption) (*ResponseStartRecord, error) {
out := new(ResponseStartRecord)
err := c.cc.Invoke(ctx, "/mp4.api/StartRecord", in, out, opts...)
if err != nil {
return nil, err
}
@@ -86,21 +85,19 @@ func (c *apiClient) EventStart(ctx context.Context, in *ReqEventRecord, opts ...
// ApiServer is the server API for Api service.
// All implementations must embed UnimplementedApiServer
// for forward compatibility.
// for forward compatibility
type ApiServer interface {
List(context.Context, *ReqRecordList) (*ResponseList, error)
Catalog(context.Context, *emptypb.Empty) (*ResponseCatalog, error)
Delete(context.Context, *ReqRecordDelete) (*ResponseDelete, error)
EventStart(context.Context, *ReqEventRecord) (*ResponseEventRecord, error)
StartRecord(context.Context, *ReqStartRecord) (*ResponseStartRecord, error)
mustEmbedUnimplementedApiServer()
}
// UnimplementedApiServer must be embedded to have
// forward compatible implementations.
//
// NOTE: this should be embedded by value instead of pointer to avoid a nil
// pointer dereference when methods are called.
type UnimplementedApiServer struct{}
// UnimplementedApiServer must be embedded to have forward compatible implementations.
type UnimplementedApiServer struct {
}
func (UnimplementedApiServer) List(context.Context, *ReqRecordList) (*ResponseList, error) {
return nil, status.Errorf(codes.Unimplemented, "method List not implemented")
@@ -114,8 +111,10 @@ func (UnimplementedApiServer) Delete(context.Context, *ReqRecordDelete) (*Respon
func (UnimplementedApiServer) EventStart(context.Context, *ReqEventRecord) (*ResponseEventRecord, error) {
return nil, status.Errorf(codes.Unimplemented, "method EventStart not implemented")
}
func (UnimplementedApiServer) StartRecord(context.Context, *ReqStartRecord) (*ResponseStartRecord, error) {
return nil, status.Errorf(codes.Unimplemented, "method StartRecord not implemented")
}
func (UnimplementedApiServer) mustEmbedUnimplementedApiServer() {}
func (UnimplementedApiServer) testEmbeddedByValue() {}
// UnsafeApiServer may be embedded to opt out of forward compatibility for this service.
// Use of this interface is not recommended, as added methods to ApiServer will
@@ -125,13 +124,6 @@ type UnsafeApiServer interface {
}
func RegisterApiServer(s grpc.ServiceRegistrar, srv ApiServer) {
// If the following call pancis, it indicates UnimplementedApiServer was
// embedded by pointer and is nil. This will cause panics if an
// unimplemented method is ever invoked, so we test this at initialization
// time to prevent it from happening at runtime later due to I/O.
if t, ok := srv.(interface{ testEmbeddedByValue() }); ok {
t.testEmbeddedByValue()
}
s.RegisterService(&Api_ServiceDesc, srv)
}
@@ -145,7 +137,7 @@ func _Api_List_Handler(srv interface{}, ctx context.Context, dec func(interface{
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: Api_List_FullMethodName,
FullMethod: "/mp4.api/List",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(ApiServer).List(ctx, req.(*ReqRecordList))
@@ -163,7 +155,7 @@ func _Api_Catalog_Handler(srv interface{}, ctx context.Context, dec func(interfa
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: Api_Catalog_FullMethodName,
FullMethod: "/mp4.api/Catalog",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(ApiServer).Catalog(ctx, req.(*emptypb.Empty))
@@ -181,7 +173,7 @@ func _Api_Delete_Handler(srv interface{}, ctx context.Context, dec func(interfac
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: Api_Delete_FullMethodName,
FullMethod: "/mp4.api/Delete",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(ApiServer).Delete(ctx, req.(*ReqRecordDelete))
@@ -199,7 +191,7 @@ func _Api_EventStart_Handler(srv interface{}, ctx context.Context, dec func(inte
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: Api_EventStart_FullMethodName,
FullMethod: "/mp4.api/EventStart",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(ApiServer).EventStart(ctx, req.(*ReqEventRecord))
@@ -207,6 +199,24 @@ func _Api_EventStart_Handler(srv interface{}, ctx context.Context, dec func(inte
return interceptor(ctx, in, info, handler)
}
func _Api_StartRecord_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(ReqStartRecord)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(ApiServer).StartRecord(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/mp4.api/StartRecord",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(ApiServer).StartRecord(ctx, req.(*ReqStartRecord))
}
return interceptor(ctx, in, info, handler)
}
// Api_ServiceDesc is the grpc.ServiceDesc for Api service.
// It's only intended for direct use with grpc.RegisterService,
// and not to be introspected or modified (even as a copy)
@@ -230,6 +240,10 @@ var Api_ServiceDesc = grpc.ServiceDesc{
MethodName: "EventStart",
Handler: _Api_EventStart_Handler,
},
{
MethodName: "StartRecord",
Handler: _Api_StartRecord_Handler,
},
},
Streams: []grpc.StreamDesc{},
Metadata: "mp4.proto",

View File

@@ -635,7 +635,7 @@ func (p *Publisher) Dispose() {
func (p *Publisher) TransferSubscribers(newPublisher *Publisher) {
for subscriber := range p.SubscriberRange {
if subscriber.Internal {
if subscriber.Type != SubscribeTypeServer {
continue
}
newPublisher.AddSubscriber(subscriber)

View File

@@ -49,7 +49,7 @@ func (p *PushJob) Subscribe() (err error) {
p.Subscriber, err = p.Plugin.Subscribe(p.pusher.GetTask().Context, p.StreamPath)
}
if p.Subscriber != nil {
p.Subscriber.Internal = true
p.Subscriber.Type = SubscribeTypePush
}
return
}

View File

@@ -12,7 +12,13 @@ import (
"m7s.live/v5/pkg"
)
const (
RecordModeAuto RecordMode = "auto"
RecordModeEvent RecordMode = "event"
)
type (
RecordMode = string
IRecorder interface {
task.ITask
GetRecordJob() *RecordJob
@@ -29,7 +35,7 @@ type (
FilePath string
recorder IRecorder
EventId string `json:"eventId" desc:"事件编号"`
RecordMode string `json:"recordMode" desc:"事件类型,0=连续录像模式,1=事件录像模式"`
RecordMode RecordMode `json:"recordMode" desc:"事件类型,auto=连续录像模式,event=事件录像模式"`
BeforeDuration time.Duration `json:"beforeDuration" desc:"事件前缓存时长"`
AfterDuration time.Duration `json:"afterDuration" desc:"事件后缓存时长"`
EventDesc string `json:"eventDesc" desc:"事件描述"`
@@ -44,7 +50,7 @@ type (
ID uint `gorm:"primarykey"`
StartTime, EndTime time.Time `gorm:"default:'1970-01-01 00:00:00'"`
EventId string `json:"eventId" desc:"事件编号" gorm:"type:varchar(255);comment:事件编号"`
RecordMode string `json:"recordMode" desc:"事件类型,0=连续录像模式,1=事件录像模式" gorm:"type:varchar(255);comment:事件类型,0=连续录像模式,1=事件录像模式;default:'0'"`
RecordMode RecordMode `json:"recordMode" desc:"事件类型,auto=连续录像模式,event=事件录像模式" gorm:"type:varchar(255);comment:事件类型,auto=连续录像模式,event=事件录像模式;default:'auto'"`
EventName string `json:"eventName" desc:"事件名称" gorm:"type:varchar(255);comment:事件名称"`
BeforeDuration time.Duration `json:"beforeDuration" desc:"事件前缓存时长" gorm:"type:BIGINT;comment:事件前缓存时长;default:30000000000"`
AfterDuration time.Duration `json:"afterDuration" desc:"事件后缓存时长" gorm:"type:BIGINT;comment:事件后缓存时长;default:30000000000"`
@@ -78,7 +84,7 @@ func (p *RecordJob) Subscribe() (err error) {
p.Subscriber, err = p.Plugin.Subscribe(p.recorder.GetTask().Context, p.StreamPath)
}
if p.Subscriber != nil {
p.Subscriber.Internal = true
p.Subscriber.Type = SubscribeTypeVod
}
return
}

View File

@@ -43,7 +43,7 @@ var (
MergeConfigs = [...]string{"Publish", "Subscribe", "HTTP", "PublicIP", "PublicIPv6", "LogLevel", "EnableAuth", "DB"}
ExecPath = os.Args[0]
ExecDir = filepath.Dir(ExecPath)
serverMeta = PluginMeta{
ServerMeta = PluginMeta{
Name: "Global",
Version: Version,
}
@@ -113,7 +113,7 @@ func NewServer(conf any) (s *Server) {
disabledPlugins: make([]*Plugin, 0),
}
s.ID = task.GetNextTaskID()
s.Meta = &serverMeta
s.Meta = &ServerMeta
s.SetDescriptions(task.Description{
"version": Version,
"goVersion": sysruntime.Version(),
@@ -138,8 +138,8 @@ func exit() {
meta.OnExit()
}
}
if serverMeta.OnExit != nil {
serverMeta.OnExit()
if ServerMeta.OnExit != nil {
ServerMeta.OnExit()
}
os.Exit(0)
}
@@ -241,6 +241,7 @@ func (s *Server) Start() (err error) {
"/api/config/json/{name}": s.api_Config_JSON_,
"/api/stream/annexb/{streamPath...}": s.api_Stream_AnnexB_,
"/api/videotrack/sse/{streamPath...}": s.api_VideoTrack_SSE,
"/api/audiotrack/sse/{streamPath...}": s.api_AudioTrack_SSE,
})
if s.config.DSN != "" {
if factory, ok := db.Factory[s.config.DBType]; ok {

View File

@@ -23,6 +23,15 @@ import (
var AVFrameType = reflect.TypeOf((*AVFrame)(nil))
var Owner task.TaskContextKey = "owner"
const (
SubscribeTypePush = "push"
SubscribeTypeServer = "server"
SubscribeTypeVod = "vod"
SubscribeTypeTransform = "transform"
SubscribeTypeReplay = "replay"
SubscribeTypeAPI = "api"
)
type PubSubBase struct {
task.Job
Plugin *Plugin
@@ -75,6 +84,7 @@ func createSubscriber(p *Plugin, streamPath string, conf config.Subscribe) *Subs
subscriber := &Subscriber{Subscribe: conf, waitPublishDone: make(chan struct{})}
subscriber.ID = task.GetNextTaskID()
subscriber.Plugin = p
subscriber.Type = SubscribeTypeServer
subscriber.Logger = p.Logger.With("streamPath", streamPath, "sId", subscriber.ID)
subscriber.Init(streamPath, &subscriber.Subscribe)
if subscriber.Subscribe.BufferTime > 0 {
@@ -356,10 +366,10 @@ func (handler *SubscribeHandler[A, V]) Run() (err error) {
handler.startAudioTs, handler.startVideoTs = s.StartAudioTS, s.StartVideoTS
var initState = 0
handler.p = s.Publisher
if s.SubAudio {
if s.SubAudio && handler.OnAudio != nil {
handler.dataTypeAudio = reflect.TypeOf(handler.OnAudio).In(0)
}
if s.SubVideo {
if s.SubVideo && handler.OnVideo != nil {
handler.dataTypeVideo = reflect.TypeOf(handler.OnVideo).In(0)
}
handler.createReaders()
@@ -394,9 +404,11 @@ func (handler *SubscribeHandler[A, V]) Run() (err error) {
vr.LastCodecCtx = vr.Track.ICodecCtx
if seqFrame := vr.Track.SequenceFrame; seqFrame != nil {
s.Debug("video codec changed", "data", seqFrame.String())
if handler.vwi >= 0 {
err = handler.OnVideo(seqFrame.(V))
}
}
}
if ar != nil {
if handler.audioFrame != nil {
if util.Conditional(s.SyncMode == 0, handler.videoFrame.Timestamp > handler.audioFrame.Timestamp, handler.videoFrame.WriteTime.After(handler.audioFrame.WriteTime)) {

View File

@@ -69,8 +69,9 @@ func (r *DefaultTransformer) GetTransformJob() *TransformJob {
func (p *TransformJob) Subscribe() (err error) {
p.Subscriber, err = p.Plugin.Subscribe(p.Transformer, p.StreamPath)
p.Subscriber.Type = SubscribeTypeTransform
if err == nil {
p.Subscriber.Internal = true
p.Subscriber.Type = SubscribeTypeTransform
p.Transformer.Depend(p.Subscriber)
}
return