diff --git a/apidocs/openapi.yaml b/apidocs/openapi.yaml index 878255ef..12e7afec 100644 --- a/apidocs/openapi.yaml +++ b/apidocs/openapi.yaml @@ -127,6 +127,8 @@ components: type: array items: type: string + hlsDirectory: + type: string # WebRTC webrtcDisable: diff --git a/internal/conf/conf.go b/internal/conf/conf.go index f4ff720e..0fdaf480 100644 --- a/internal/conf/conf.go +++ b/internal/conf/conf.go @@ -222,6 +222,7 @@ type Conf struct { HLSSegmentMaxSize StringSize `json:"hlsSegmentMaxSize"` HLSAllowOrigin string `json:"hlsAllowOrigin"` HLSTrustedProxies IPsOrCIDRs `json:"hlsTrustedProxies"` + HLSDirectory string `json:"hlsDirectory"` // WebRTC WebRTCDisable bool `json:"webrtcDisable"` diff --git a/internal/core/core.go b/internal/core/core.go index 26a04f1e..9aec6cb3 100644 --- a/internal/core/core.go +++ b/internal/core/core.go @@ -400,6 +400,7 @@ func (p *Core) createResources(initial bool) error { p.conf.HLSSegmentMaxSize, p.conf.HLSAllowOrigin, p.conf.HLSTrustedProxies, + p.conf.HLSDirectory, p.conf.ReadBufferCount, p.pathManager, p.metrics, @@ -575,6 +576,7 @@ func (p *Core) closeResources(newConf *conf.Conf, calledByAPI bool) { newConf.HLSSegmentMaxSize != p.conf.HLSSegmentMaxSize || newConf.HLSAllowOrigin != p.conf.HLSAllowOrigin || !reflect.DeepEqual(newConf.HLSTrustedProxies, p.conf.HLSTrustedProxies) || + newConf.HLSDirectory != p.conf.HLSDirectory || newConf.ReadBufferCount != p.conf.ReadBufferCount || closePathManager || closeMetrics diff --git a/internal/core/hls_muxer.go b/internal/core/hls_muxer.go index 149cc8f4..50a42232 100644 --- a/internal/core/hls_muxer.go +++ b/internal/core/hls_muxer.go @@ -9,6 +9,8 @@ import ( "io" "net" "net/http" + "os" + "path/filepath" "sync" "sync/atomic" "time" @@ -56,7 +58,6 @@ type hlsMuxerParent interface { } type hlsMuxer struct { - name string remoteAddr string externalAuthenticationURL string alwaysRemux bool @@ -65,6 +66,7 @@ type hlsMuxer struct { segmentDuration conf.StringDuration partDuration conf.StringDuration segmentMaxSize conf.StringSize + directory string readBufferCount int wg *sync.WaitGroup pathName string @@ -88,7 +90,6 @@ type hlsMuxer struct { func newHLSMuxer( parentCtx context.Context, - name string, remoteAddr string, externalAuthenticationURL string, alwaysRemux bool, @@ -97,6 +98,7 @@ func newHLSMuxer( segmentDuration conf.StringDuration, partDuration conf.StringDuration, segmentMaxSize conf.StringSize, + directory string, readBufferCount int, wg *sync.WaitGroup, pathName string, @@ -106,7 +108,6 @@ func newHLSMuxer( ctx, ctxCancel := context.WithCancel(parentCtx) m := &hlsMuxer{ - name: name, remoteAddr: remoteAddr, externalAuthenticationURL: externalAuthenticationURL, alwaysRemux: alwaysRemux, @@ -115,6 +116,7 @@ func newHLSMuxer( segmentDuration: segmentDuration, partDuration: partDuration, segmentMaxSize: segmentMaxSize, + directory: directory, readBufferCount: readBufferCount, wg: wg, pathName: pathName, @@ -207,7 +209,7 @@ func (m *hlsMuxer) run() { } case req := <-m.chAPIHLSMuxersList: - req.data.Items[m.name] = hlsServerAPIMuxersListItem{ + req.data.Items[m.pathName] = hlsServerAPIMuxersListItem{ Created: m.created, LastRequest: time.Unix(0, atomic.LoadInt64(m.lastRequestTime)), BytesSent: atomic.LoadUint64(m.bytesSent), @@ -296,6 +298,13 @@ func (m *hlsMuxer) runInner(innerCtx context.Context, innerReady chan struct{}) "the stream doesn't contain any supported codec (which are currently H264, H265, MPEG4-Audio, Opus)") } + var muxerDirectory string + if m.directory != "" { + muxerDirectory = filepath.Join(m.directory, m.pathName) + os.MkdirAll(muxerDirectory, 0o755) + defer os.Remove(muxerDirectory) + } + m.muxer = &gohlslib.Muxer{ Variant: gohlslib.MuxerVariant(m.variant), SegmentCount: m.segmentCount, @@ -304,6 +313,7 @@ func (m *hlsMuxer) runInner(innerCtx context.Context, innerReady chan struct{}) SegmentMaxSize: uint64(m.segmentMaxSize), VideoTrack: videoFormat, AudioTrack: audioFormat, + Directory: muxerDirectory, } err := m.muxer.Start() diff --git a/internal/core/hls_server.go b/internal/core/hls_server.go index 35ed3de1..34bb8e82 100644 --- a/internal/core/hls_server.go +++ b/internal/core/hls_server.go @@ -64,6 +64,7 @@ type hlsServer struct { segmentMaxSize conf.StringSize allowOrigin string trustedProxies conf.IPsOrCIDRs + directory string readBufferCount int pathManager *pathManager metrics *metrics @@ -99,6 +100,7 @@ func newHLSServer( segmentMaxSize conf.StringSize, allowOrigin string, trustedProxies conf.IPsOrCIDRs, + directory string, readBufferCount int, pathManager *pathManager, metrics *metrics, @@ -134,6 +136,7 @@ func newHLSServer( segmentMaxSize: segmentMaxSize, allowOrigin: allowOrigin, trustedProxies: trustedProxies, + directory: directory, readBufferCount: readBufferCount, pathManager: pathManager, parent: parent, @@ -344,7 +347,6 @@ func (s *hlsServer) onRequest(ctx *gin.Context) { func (s *hlsServer) createMuxer(pathName string, remoteAddr string) *hlsMuxer { r := newHLSMuxer( s.ctx, - pathName, remoteAddr, s.externalAuthenticationURL, s.alwaysRemux, @@ -353,6 +355,7 @@ func (s *hlsServer) createMuxer(pathName string, remoteAddr string) *hlsMuxer { s.segmentDuration, s.partDuration, s.segmentMaxSize, + s.directory, s.readBufferCount, &s.wg, pathName, diff --git a/rtsp-simple-server.yml b/rtsp-simple-server.yml index 894ba744..ddb83a47 100644 --- a/rtsp-simple-server.yml +++ b/rtsp-simple-server.yml @@ -167,6 +167,10 @@ hlsAllowOrigin: '*' # If the server receives a request from one of these entries, IP in logs # will be taken from the X-Forwarded-For header. hlsTrustedProxies: [] +# Directory in which to save segments, instead of keeping them in the RAM. +# This decreases performance, since reading from disk is less performant than +# reading from RAM, but allows to save RAM. +hlsDirectory: '' ############################################### # WebRTC parameters