Skip to content

Commit

Permalink
support unix timestamp in filenames of recorded segments (#2774)
Browse files Browse the repository at this point in the history
* added support for %s to use unix timestamp in filenames

* fix lint errors

* add tests

* update documentation

---------

Co-authored-by: aler9 <46489434+aler9@users.noreply.github.com>
  • Loading branch information
neerajkanhere and aler9 authored Dec 2, 2023
1 parent 3e12f83 commit 47bd735
Show file tree
Hide file tree
Showing 4 changed files with 66 additions and 3 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -1153,7 +1153,7 @@ pathDefaults:
record: yes
# Path of recording segments.
# Extension is added automatically.
# Available variables are %path (path name), %Y %m %d %H %M %S %f (time in strftime format)
# Available variables are %path (path name), %Y %m %d %H %M %S %f %s (time in strftime format)
recordPath: ./recordings/%path/%Y-%m-%d_%H-%M-%S-%f
```
Expand Down
14 changes: 13 additions & 1 deletion internal/record/record_path.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ func decodeRecordPath(format string, v string) *recordPathParams {
re = strings.ReplaceAll(re, "%M", "([0-9]{2})")
re = strings.ReplaceAll(re, "%S", "([0-9]{2})")
re = strings.ReplaceAll(re, "%f", "([0-9]{6})")
re = strings.ReplaceAll(re, "%s", "([0-9]{10})")
r := regexp.MustCompile(re)

var groupMapping []string
Expand All @@ -77,6 +78,7 @@ func decodeRecordPath(format string, v string) *recordPathParams {
"%M",
"%S",
"%f",
"%s",
} {
if strings.HasPrefix(cur, va) {
groupMapping = append(groupMapping, va)
Expand Down Expand Up @@ -104,6 +106,7 @@ func decodeRecordPath(format string, v string) *recordPathParams {
var minute int
var second int
var micros int
var unixSec int64 = -1

for k, v := range values {
switch k {
Expand Down Expand Up @@ -134,10 +137,18 @@ func decodeRecordPath(format string, v string) *recordPathParams {
case "%f":
tmp, _ := strconv.ParseInt(v, 10, 64)
micros = int(tmp)

case "%s":
unixSec, _ = strconv.ParseInt(v, 10, 64)
}
}

t := time.Date(year, month, day, hour, minute, second, micros*1000, time.Local)
var t time.Time
if unixSec > 0 {
t = time.Unix(unixSec, 0)
} else {
t = time.Date(year, month, day, hour, minute, second, micros*1000, time.Local)
}

return &recordPathParams{
path: values["%path"],
Expand All @@ -153,5 +164,6 @@ func encodeRecordPath(params *recordPathParams, v string) string {
v = strings.ReplaceAll(v, "%M", leadingZeros(params.time.Minute(), 2))
v = strings.ReplaceAll(v, "%S", leadingZeros(params.time.Second(), 2))
v = strings.ReplaceAll(v, "%f", leadingZeros(params.time.Nanosecond()/1000, 6))
v = strings.ReplaceAll(v, "%s", strconv.FormatInt(params.time.Unix(), 10))
return v
}
51 changes: 51 additions & 0 deletions internal/record/record_path_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package record

import (
"strings"
"testing"
"time"

"github.com/stretchr/testify/require"
)

var recordPathCases = []struct {
name string
format string
dec *recordPathParams
enc string
}{
{
"standard",
"%path/%Y-%m-%d_%H-%M-%S-%f.mp4",
&recordPathParams{
path: "mypath",
time: time.Date(2008, 11, 0o7, 11, 22, 4, 123456000, time.Local),
},
"mypath/2008-11-07_11-22-04-123456.mp4",
},
{
"unix seconds",
"%path/%s.mp4",
&recordPathParams{
path: "mypath",
time: time.Date(2021, 12, 2, 12, 15, 23, 0, time.UTC).Local(),
},
"mypath/1638447323.mp4",
},
}

func TestRecordPathDecode(t *testing.T) {
for _, ca := range recordPathCases {
t.Run(ca.name, func(t *testing.T) {
require.Equal(t, ca.dec, decodeRecordPath(ca.format, ca.enc))
})
}
}

func TestRecordPathEncode(t *testing.T) {
for _, ca := range recordPathCases {
t.Run(ca.name, func(t *testing.T) {
require.Equal(t, ca.enc, strings.ReplaceAll(encodeRecordPath(ca.dec, ca.format), "%path", "mypath"))
})
}
}
2 changes: 1 addition & 1 deletion mediamtx.yml
Original file line number Diff line number Diff line change
Expand Up @@ -296,7 +296,7 @@ pathDefaults:
record: no
# Path of recording segments.
# Extension is added automatically.
# Available variables are %path (path name), %Y %m %d %H %M %S %f (time in strftime format)
# Available variables are %path (path name), %Y %m %d %H %M %S %f %s (time in strftime format)
recordPath: ./recordings/%path/%Y-%m-%d_%H-%M-%S-%f
# Format of recorded segments.
# Available formats are "fmp4" (fragmented MP4) and "mpegts" (MPEG-TS).
Expand Down

0 comments on commit 47bd735

Please sign in to comment.