Add rtspRequire and rtspRateControl to RTSP sources - #6047
Open
nlsrchtr wants to merge 1 commit into
Open
Conversation
mediamtx can already pull ONVIF Profile G recordings: rtspRangeType/rtspRangeStart produce the "Range: clock=" header on PLAY, and rtspScale accelerates delivery beyond real time. Two headers from the ONVIF Streaming Specification are still unreachable, and both matter for replay. "Rate-Control: no" (section 6.5.2) asks for a recording as fast as the transport allows rather than in real time. It matters because rtspScale is not an equivalent: section 6.5 says a device MAY accept Scale values other than 1.0/-1.0, while section 6.5.2 says an ONVIF compliant server SHALL support Rate-Control=no for playback. So today's only fast-replay option rests on an optional feature while the mandatory one cannot be sent. The two are also mutually exclusive: with Rate-Control=no, section 6.5 requires Scale to be 1.0 or -1.0, since the client rather than the server then paces the stream. "Require: onvif-replay" (section 6.4) declares that the client understands the replay extensions. Without it a device that does not implement them does not fail, it streams something else -- live, or the recording from its start -- so a request for a specific past window can silently return different footage. With the tag the same device answers 551 (Option not supported), which is a much better outcome than plausible-looking wrong data. Both follow the rtspScale pattern exactly: a per-path string, applied to PLAY through OnRequest. Require is APPENDED rather than assigned, because gortsplib already sets that header when the client is reading a back channel and both feature tags have to survive. Tested with TestRequireAndRateControl, alongside the existing TestScale.
There was a problem hiding this comment.
Pull request overview
This PR extends RTSP static sources configuration to support ONVIF Profile G replay by allowing additional RTSP headers to be sent on PLAY, improving correctness for replay requests and enabling transport-paced playback.
Changes:
- Add new per-path config options
rtspRequireandrtspRateControl(docs + config struct fields). - Inject
Require(appended) andRate-Controlheaders into RTSPPLAYrequests. - Add a unit test verifying the new headers are sent on
PLAY, and expose the options in the OpenAPI schema.
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| mediamtx.yml | Documents new rtspRequire / rtspRateControl path defaults. |
| internal/staticsources/rtsp/source.go | Adds header injection on RTSP PLAY via client OnRequest. |
| internal/staticsources/rtsp/source_test.go | Adds a test that asserts Require and Rate-Control are present on PLAY. |
| internal/conf/path.go | Adds config fields for the new options to the Path struct. |
| api/openapi.yaml | Exposes the new fields in the API schema. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
+142
to
+146
| if req.Method == base.Play { | ||
| if params.Conf.RTSPScale != "" { | ||
| if req.Header == nil { | ||
| req.Header = base.Header{} | ||
| } |
| # Negative values play in reverse, values > 1 fast-forward, | ||
| # values 0 < x < 1 play slow motion. | ||
| rtspScale: | ||
| # Require header value to send to the source, in order to declare support for a RTSP feature. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
mediamtx can already pull ONVIF Profile G recordings: rtspRangeType/rtspRangeStart produce the "Range: clock=" header on PLAY, and rtspScale accelerates delivery beyond real time. Two headers from the ONVIF Streaming Specification are still unreachable, and both matter for replay.
"Rate-Control: no" (section 6.5.2) asks for a recording as fast as the transport allows rather than in real time. It matters because rtspScale is not an equivalent: section 6.5 says a device MAY accept Scale values other than 1.0/-1.0, while section 6.5.2 says an ONVIF compliant server SHALL support Rate-Control=no for playback. So today's only fast-replay option rests on an optional feature while the mandatory one cannot be sent. The two are also mutually exclusive: with Rate-Control=no, section 6.5 requires Scale to be 1.0 or -1.0, since the client rather than the server then paces the stream.
"Require: onvif-replay" (section 6.4) declares that the client understands the replay extensions. Without it a device that does not implement them does not fail, it streams something else -- live, or the recording from its start -- so a request for a specific past window can silently return different footage. With the tag the same device answers 551 (Option not supported), which is a much better outcome than plausible-looking wrong data.
Both follow the rtspScale pattern exactly: a per-path string, applied to PLAY through OnRequest. Require is APPENDED rather than assigned, because gortsplib already sets that header when the client is reading a back channel and both feature tags have to survive.
Tested with TestRequireAndRateControl, alongside the existing TestScale.