Skip to content

Commit

Permalink
playback: add "endpoint" field to recording timespans in /list
Browse files Browse the repository at this point in the history
  • Loading branch information
aler9 committed Aug 5, 2024
1 parent 53e9470 commit 863965a
Show file tree
Hide file tree
Showing 3 changed files with 28 additions and 7 deletions.
12 changes: 7 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -1186,7 +1186,7 @@ The JWT is expected to contain the `mediamtx_permissions` scope, with a list of
}
```

Clients are expected to pass the JWT in the Authorization header (in case of HLS and WebRTC) or in query parameters (in case of any other protocol), for instance (RTSP):
Clients are expected to pass the JWT in the Authorization header (in case of HLS and WebRTC) or in query parameters (in case of all other protocols), for instance:

```
ffmpeg -re -stream_loop -1 -i file.ts -c copy -f rtsp rtsp://localhost:8554/mystream?jwt=MY_JWT
Expand Down Expand Up @@ -1350,16 +1350,18 @@ Where [mypath] is the name of a path. The server will return a list of timespans
[
{
"start": "2006-01-02T15:04:05Z07:00",
"duration": "60.0"
"duration": "60.0",
"endpoint": "/get?path=[mypath]&start=2006-01-02T15%3A04%3A05Z07%3A00&duration=60.0"
},
{
"start": "2006-01-02T15:07:05Z07:00",
"duration": "32.33"
"duration": "32.33",
"endpoint": "/get?path=[mypath]&start=2006-01-02T15%3A07%3A05Z07%3A00&duration=32.33"
}
]
```

The server provides an endpoint for downloading recordings:
The server provides an endpoint to download recordings:

```
http://localhost:9996/get?path=[mypath]&start=[start_date]&duration=[duration]&format=[format]
Expand All @@ -1375,7 +1377,7 @@ Where:
All parameters must be [url-encoded](https://www.urlencoder.org/). For instance:

```
http://localhost:9996/get?path=stream2&start=2024-01-14T16%3A33%3A17%2B00%3A00&duration=200.5
http://localhost:9996/get?path=mypath&start=2024-01-14T16%3A33%3A17%2B00%3A00&duration=200.5
```

The resulting stream uses the fMP4 format, that is natively compatible with any browser, therefore its URL can be directly inserted into a \<video> tag:
Expand Down
15 changes: 13 additions & 2 deletions internal/playback/on_list.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@ import (
"fmt"
"io"
"net/http"
"net/url"
"os"
"strconv"
"time"

"github.com/bluenviron/mediacommon/pkg/formats/fmp4"
Expand All @@ -23,6 +25,7 @@ func (d listEntryDuration) MarshalJSON() ([]byte, error) {
type listEntry struct {
Start time.Time `json:"start"`
Duration listEntryDuration `json:"duration"`
Endpoint string `json:"endpoint"`
}

func computeDurationAndConcatenate(recordFormat conf.RecordFormat, segments []*Segment) ([]listEntry, error) {
Expand Down Expand Up @@ -106,11 +109,19 @@ func (p *Server) onList(ctx *gin.Context) {
return
}

out, err := computeDurationAndConcatenate(pathConf.RecordFormat, segments)
entries, err := computeDurationAndConcatenate(pathConf.RecordFormat, segments)
if err != nil {
p.writeError(ctx, http.StatusInternalServerError, err)
return
}

ctx.JSON(http.StatusOK, out)
for i := range entries {
v := url.Values{}
v.Add("path", pathName)
v.Add("start", entries[i].Start.Format(time.RFC3339Nano))
v.Add("duration", strconv.FormatFloat(time.Duration(entries[i].Duration).Seconds(), 'f', -1, 64))
entries[i].Endpoint = "/get?" + v.Encode()
}

ctx.JSON(http.StatusOK, entries)
}
8 changes: 8 additions & 0 deletions internal/playback/on_list_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,10 +78,14 @@ func TestOnList(t *testing.T) {
map[string]interface{}{
"duration": float64(65),
"start": time.Date(2008, 11, 0o7, 11, 22, 0, 500000000, time.Local).Format(time.RFC3339Nano),
"endpoint": "/get?duration=65&path=mypath&start=" +
url.QueryEscape(time.Date(2008, 11, 0o7, 11, 22, 0, 500000000, time.Local).Format(time.RFC3339Nano)),
},
map[string]interface{}{
"duration": float64(3),
"start": time.Date(2009, 11, 0o7, 11, 23, 2, 500000000, time.Local).Format(time.RFC3339Nano),
"endpoint": "/get?duration=3&path=mypath&start=" +
url.QueryEscape(time.Date(2009, 11, 0o7, 11, 23, 2, 500000000, time.Local).Format(time.RFC3339Nano)),
},
}, out)
}
Expand Down Expand Up @@ -136,10 +140,14 @@ func TestOnListDifferentInit(t *testing.T) {
map[string]interface{}{
"duration": float64(62),
"start": time.Date(2008, 11, 0o7, 11, 22, 0, 500000000, time.Local).Format(time.RFC3339Nano),
"endpoint": "/get?duration=62&path=mypath&start=" +
url.QueryEscape(time.Date(2008, 11, 0o7, 11, 22, 0, 500000000, time.Local).Format(time.RFC3339Nano)),
},
map[string]interface{}{
"duration": float64(1),
"start": time.Date(2008, 11, 0o7, 11, 23, 2, 500000000, time.Local).Format(time.RFC3339Nano),
"endpoint": "/get?duration=1&path=mypath&start=" +
url.QueryEscape(time.Date(2008, 11, 0o7, 11, 23, 2, 500000000, time.Local).Format(time.RFC3339Nano)),
},
}, out)
}

0 comments on commit 863965a

Please sign in to comment.