support unix timestamp in filenames of recorded segments (#2774)

* 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>
This commit is contained in:
Neeraj Kanhere 2023-12-02 08:36:13 -05:00 committed by GitHub
parent 3e12f83732
commit 47bd7352f0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 66 additions and 3 deletions

View File

@ -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
```

View File

@ -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
@ -77,6 +78,7 @@ func decodeRecordPath(format string, v string) *recordPathParams {
"%M",
"%S",
"%f",
"%s",
} {
if strings.HasPrefix(cur, va) {
groupMapping = append(groupMapping, va)
@ -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 {
@ -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"],
@ -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
}

View File

@ -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"))
})
}
}

View File

@ -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).