diff --git a/README.md b/README.md
index 9584eabf..d45e040c 100644
--- a/README.md
+++ b/README.md
@@ -553,7 +553,7 @@ This web page can be embedded into another web page by using an iframe:
```
-For more advanced setups, you can create and serve a custom web page by starting from the [source code of the WebRTC publish page](internal/servers/webrtc/publish_index.html).
+For more advanced setups, you can create and serve a custom web page by starting from the [source code of the WebRTC publish page](internal/servers/webrtc/publish_index.html). In particular, there's a ready-to-use, standalone JavaScript class for publishing streams with WebRTC, available in [publisher.js](internal/servers/webrtc/publisher.js).
### By device
@@ -1104,7 +1104,7 @@ This web page can be embedded into another web page by using an iframe:
```
-For more advanced setups, you can create and serve a custom web page by starting from the [source code of the WebRTC read page](internal/servers/webrtc/read_index.html).
+For more advanced setups, you can create and serve a custom web page by starting from the [source code of the WebRTC read page](internal/servers/webrtc/read_index.html). In particular, there's a ready-to-use, standalone JavaScript class for reading streams with WebRTC, available in [reader.js](internal/servers/webrtc/reader.js).
Web browsers can also read a stream with the [HLS protocol](#hls). Latency is higher but there are less problems related to connectivity between server and clients, furthermore the server load can be balanced by using a common HTTP CDN (like CloudFront or Cloudflare), and this allows to handle readers in the order of millions. Visit the web page:
diff --git a/internal/conf/conf_test.go b/internal/conf/conf_test.go
index c555078e..203e1d17 100644
--- a/internal/conf/conf_test.go
+++ b/internal/conf/conf_test.go
@@ -423,6 +423,14 @@ func TestConfErrors(t *testing.T) {
" recordPath: invalid\n",
`record path 'invalid' is missing one of the mandatory elements: %path %Y %m %d %H %M %S %f`,
},
+ {
+ "invalid record delete after",
+ "paths:\n" +
+ " my_path:\n" +
+ " recordSegmentDuration: 30m\n" +
+ " recordDeleteAfter: 20m\n",
+ `'recordDeleteAfter' cannot be lower than 'recordSegmentDuration'`,
+ },
} {
t.Run(ca.name, func(t *testing.T) {
tmpf, err := createTempFile([]byte(ca.conf))
diff --git a/internal/conf/path.go b/internal/conf/path.go
index 087f49b0..28b2b6ff 100644
--- a/internal/conf/path.go
+++ b/internal/conf/path.go
@@ -512,6 +512,10 @@ func (pconf *Path) validate(
return fmt.Errorf("maximum segment duration is 1 day")
}
+ if pconf.RecordDeleteAfter != 0 && pconf.RecordDeleteAfter < pconf.RecordSegmentDuration {
+ return fmt.Errorf("'recordDeleteAfter' cannot be lower than 'recordSegmentDuration'")
+ }
+
// Authentication (deprecated)
if deprecatedCredentialsMode {