You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
130 lines
3.3 KiB
Go
130 lines
3.3 KiB
Go
package main
|
|
|
|
import (
|
|
"fmt"
|
|
"github.com/deepch/vdk/format/mp4"
|
|
"github.com/gin-gonic/gin"
|
|
"github.com/sirupsen/logrus"
|
|
"os"
|
|
"time"
|
|
)
|
|
|
|
// HTTPAPIServerStreamSaveToMP4 func
|
|
func HTTPAPIServerStreamSaveToMP4(c *gin.Context) {
|
|
var err error
|
|
|
|
requestLogger := log.WithFields(logrus.Fields{
|
|
"module": "http_save_mp4",
|
|
"stream": c.Param("uuid"),
|
|
"channel": c.Param("channel"),
|
|
"func": "HTTPAPIServerStreamSaveToMP4",
|
|
})
|
|
|
|
defer func() {
|
|
if err != nil {
|
|
requestLogger.WithFields(logrus.Fields{
|
|
"call": "Close",
|
|
}).Errorln(err)
|
|
}
|
|
}()
|
|
|
|
if !Storage.StreamChannelExist(c.Param("uuid"), c.Param("channel")) {
|
|
requestLogger.WithFields(logrus.Fields{
|
|
"call": "StreamChannelExist",
|
|
}).Errorln(ErrorStreamNotFound.Error())
|
|
return
|
|
}
|
|
|
|
if !RemoteAuthorization("save", c.Param("uuid"), c.Param("channel"), c.Query("token"), c.ClientIP()) {
|
|
requestLogger.WithFields(logrus.Fields{
|
|
"call": "RemoteAuthorization",
|
|
}).Errorln(ErrorStreamUnauthorized.Error())
|
|
return
|
|
}
|
|
c.Writer.Write([]byte("await save started"))
|
|
go func() {
|
|
Storage.StreamChannelRun(c.Param("uuid"), c.Param("channel"))
|
|
cid, ch, _, err := Storage.ClientAdd(c.Param("uuid"), c.Param("channel"), MSE)
|
|
if err != nil {
|
|
requestLogger.WithFields(logrus.Fields{
|
|
"call": "ClientAdd",
|
|
}).Errorln(err.Error())
|
|
return
|
|
}
|
|
|
|
defer Storage.ClientDelete(c.Param("uuid"), cid, c.Param("channel"))
|
|
codecs, err := Storage.StreamChannelCodecs(c.Param("uuid"), c.Param("channel"))
|
|
if err != nil {
|
|
requestLogger.WithFields(logrus.Fields{
|
|
"call": "StreamCodecs",
|
|
}).Errorln(err.Error())
|
|
return
|
|
}
|
|
err = os.MkdirAll(fmt.Sprintf("save/%s/%s/", c.Param("uuid"), c.Param("channel")), 0755)
|
|
if err != nil {
|
|
requestLogger.WithFields(logrus.Fields{
|
|
"call": "MkdirAll",
|
|
}).Errorln(err.Error())
|
|
}
|
|
f, err := os.Create(fmt.Sprintf("save/%s/%s/%s.mp4", c.Param("uuid"), c.Param("channel"), time.Now().String()))
|
|
if err != nil {
|
|
requestLogger.WithFields(logrus.Fields{
|
|
"call": "Create",
|
|
}).Errorln(err.Error())
|
|
}
|
|
defer f.Close()
|
|
|
|
muxer := mp4.NewMuxer(f)
|
|
err = muxer.WriteHeader(codecs)
|
|
if err != nil {
|
|
requestLogger.WithFields(logrus.Fields{
|
|
"call": "WriteHeader",
|
|
}).Errorln(err.Error())
|
|
return
|
|
}
|
|
defer muxer.WriteTrailer()
|
|
|
|
var videoStart bool
|
|
controlExit := make(chan bool, 10)
|
|
dur, err := time.ParseDuration(c.Param("duration"))
|
|
if err != nil {
|
|
requestLogger.WithFields(logrus.Fields{
|
|
"call": "ParseDuration",
|
|
}).Errorln(err.Error())
|
|
}
|
|
saveLimit := time.NewTimer(dur)
|
|
noVideo := time.NewTimer(10 * time.Second)
|
|
defer log.Println("client exit")
|
|
for {
|
|
select {
|
|
case <-controlExit:
|
|
requestLogger.WithFields(logrus.Fields{
|
|
"call": "controlExit",
|
|
}).Errorln("Client Reader Exit")
|
|
return
|
|
case <-saveLimit.C:
|
|
requestLogger.WithFields(logrus.Fields{
|
|
"call": "saveLimit",
|
|
}).Errorln("Saved Limit End")
|
|
return
|
|
case <-noVideo.C:
|
|
requestLogger.WithFields(logrus.Fields{
|
|
"call": "ErrorStreamNoVideo",
|
|
}).Errorln(ErrorStreamNoVideo.Error())
|
|
return
|
|
case pck := <-ch:
|
|
if pck.IsKeyFrame {
|
|
noVideo.Reset(10 * time.Second)
|
|
videoStart = true
|
|
}
|
|
if !videoStart {
|
|
continue
|
|
}
|
|
if err = muxer.WritePacket(*pck); err != nil {
|
|
return
|
|
}
|
|
}
|
|
}
|
|
}()
|
|
}
|