v1.21.0
New major features
Media-over-QUIC
- support forwarding streams (#6145)
API
- add /paths/static-sources/get endpoint (#6177) this allows to obtain details about static sources.
- add type-specific properties to forward destinations (#6178)
- add type-specific properties to static sources (#6184)
Fixes and improvements
General
- add --validate-conf flag (#5549) (#6140)
- use internal/core/VERSION as single source of truth to get version (#6119)
- httpp: propagate Flush() through the response writer wrappers (#6126) handlerLogger's responseRecorder and handlerWriteTimeout's writeTimeoutWriter both wrap http.ResponseWriter but implement neither http.Flusher nor Unwrap(). Any handler that flushes mid-response has that flush silently dropped, and its output only reaches the client when the handler returns. That defeats the stated purpose of writeTimeoutWriter, whose own comment says it exists so one can "write long responses, splitted in chunks, without causing timeouts": the deadline is reset per Write(), but nothing ever leaves the buffer until the end. Found while adding a server-sent-events endpoint: events written and flushed at t=0.4s onlyreached the client at t=2.2s, when the handler returned. Adding Flush() plus Unwrap() (so http.ResponseController can reach through) fixes both. The new test drives a real listener throughboth wrappers and reads while the handler is still blocked, so it fails on the current code by hitting the read deadline.
- support setting read buffer size on macOS (#6128) (#6131)
- drop support for Debian Bullseye (#6137) Bullseye reached EOL on 31st august 2026.
- emit "closed" log message when a server is closed (#6152)
- fix external command exit code reporting on non-Windows platforms (#6155)
- conf: support YAML version directives (#6157)
- metrics: add 'pos' property to forward_dests (#6183)
- metrics: deprecate the 'remoteAddr' property (#6174) Metrics are meant to provide aggregate statistics, not per-peer properties, that can be accessed through the API. The property is still served to keep backward compatibility.
- metrics: add 'type' to forward dests, deprecated 'protocol' (#6170) 'type' is aligned with the terminology used in the rest of the server.
- metrics, pprof: set default Allow-Origins to empty list (#6165) This prevents cross-site attacks to the API with the default configuration.
- always-available: support disabling recording when the source is offline (#6182) Add
alwaysAvailableRecordedparameter that controls whether recording happens during offline periods for always-available paths. When set to false, recording only starts when a real source is connected. Co-authored-by: Abdulrahman Nashaat abdelrahmanndev@gmail.com - allow sources and forward destinations with an empty password (#6193) Restore the behavior introduced in #395 and accidentally reverted by #5779, which factored the RTMP/HLS credential check into validateURL() and applied it to RTSP sources too. A username with an explicitly empty password is valid per RFC 3986 and is required by some legacy cameras whose password cannot be set. It is now accepted for every scheme handled by validateURL(), including forward destinations. A username without password or a password without username is still rejected,with a clearer error message pointing to the right syntax.
- fix wrong validation of HTTP allowed origins (#6198) An allowed origin with wildcards was making the server accept origins with a different scheme. This is fixed.
- fix HTTP allowed origins dots being interpreter as any character (#6199) A dot in an HTTP allowed origin now requires a corresponding dot in an incoming origin.
- serve Origin: Vary header with Access-Control-Allow-Origin (#6200) This prevents CDNs from caching the Access-Control-Allow-Origin header regardless of the origin.
- stop returning wildcard in Access-Control-Allow-Origin (#6201) if domain is allowed, return the domain, otherwise nothing.
- pmp4, fmp4: stop validating inbound H264/H265 SPS (bluenviron/mediacommon#366) Validating SPS adds latency and is generally redundant.
- pmp4, fmp4: do not accept empty H264/H265 parameters (bluenviron/mediacommon#367)
- h265: fix DTS extraction of streams with temporal sub-layers (bluenviron/mediacommon#368) The picture-type switches in the H265 DTS extractor accepted only TRAIL_N/TRAIL_R/RASL_N/RASL_R, so an access unit whose slices are TSA_N/TSA_R/STSA_N/STSA_R (Rec. ITU-T H.265, table 7-1, types 2-5) fell through to "access unit doesn't contain an IDR or non-IDR NALU" and the stream could never be recorded. TSA and STSA pictures use the same slice segment header syntax as TRAIL pictures, so handle them in the same way. Co-authored-by: aler9 46489434+aler9@users.noreply.github.com
API
- add 'type' to forward dests, deprecated 'protocol' (#6170) 'type' is aligned with the terminology used in the rest of the server.
- set default Allow-Origins to empty list (#6165) This prevents cross-site attacks to the API with the default configuration.
- deprecate 'conf' field of forward destinations (#6175) configuration is already available through the confName property of the path.
- refactor endpoint names (#6172) group endpoints by category (i.e. /hls/muxers, /hls/sessions), rename /forward/* into /forward-dests/*, use kebab-case. Backward compatibility is preserved by still serving old endpoints.
Media-Over-QUIC
- rename boolean header fields (#6148) rename Properties into HasProperties, FirstObject into IsFirstObject
- add shared Conn interface (#6149)
- close server streams when no longer in use (#6151) Explicitly close bidirectional and unidirectional streams that were previously keep open for the entire duration of the session. Note that closing a stream in QUIC/WebTransport means telling the peer that "we are not sending data anymore", while still allowing inbound data.
- add shared client (#6150)
- impose a 100MB limit on reordered bytes per session (#6194) previously, the limit was per-track. This decreases the probability of incurring in an out-of-memory situations.
RTSP
- redact credentials in logs (#6158)
- demux MPEG-TS from static source pull (#6181) When rtspDemuxMpegts is set, a pulled single MP2T track is demuxed into elementary streams, matching RTSP publishers, so HLS can attach. Co-authored-by: remreaygan remreaygan@gmail.com Co-authored-by: aler9 46489434+aler9@users.noreply.github.com
- support setting read buffer size on macOS (#6128) (bluenviron/gortsplib#1143)
- client: ignore invalid source IPs in SETUP responses (bluenviron/gortsplib#1070) (bluenviron/gortsplib#1145)
- fix decoding and encoding fragmented MPEG-4 audio packets (bluenviron/gortsplib#1150) The AU-size field was set incorrectly in subsequent fragments.
- stop validating inbound H264/H265 SPS (bluenviron/gortsplib#1151) Validating SPS adds latency and is generally redundant.
- Support SDES (RFC 4568) SRTP key exchange for RTSP/RTSPS sources (bluenviron/gortsplib#1148)
- rtpklv: do not reuse buffer of returned KLV units (bluenviron/gortsplib#1154) Decode() returns a slice that points to the decoder's internal buffer, and the next call to Decode() overwrites that same array in place. A caller that holds the previous unit - for instance while it is being recorded or forwarded on another goroutine - ends up reading the bytes of the next unit, or a torn mix of both when the sizes differ. Clear the buffer instead of truncating it, so each unit gets its own array. This is what the h264, h265, av1, vp8 andmpeg1video decoders already do, at the cost of one allocation per unit.
- auth: support qop=auth in digest client (bluenviron/gortsplib#1074) (bluenviron/gortsplib#1155) The client never looked at the qop directive of a digest challenge and always computed the legacy RFC 2069 response, so servers that require qop="auth" - as most RFC 7616 implementations do - rejected every request with a 401. Parse qop in WWW-Authenticate, and when the server offers "auth", send qop, cnonce and nc and compute the response as H(HA1:nonce:nc:cnonce:qop:HA2) (RFC 7616, section 3.4.1). The nonce count increases at every request, as required. Challenges without qop keep the previous behavior. auth-int is not implemented. Also copy the opaque value of the challenge into the Authorization header, which RFC 7616 section 3.3 says the client should return unchanged. Co-authored-by: aler9 46489434+aler9@users.noreply.github.com
- client: remove Content-Length from HTTP tunnel GET request (bluenviron/gortsplib#1158)
- rtpav1: do not set Y/Z bits when no OBU bytes were written (bluenviron/gortsplib#1153) When the remaining space in a packet is too small to hold any byte of thenext OBU, the encoder writes nothing but still marks the current packet with Y=1 and the following one with Z=1. The AV1 RTP payload format (v1.0, section 4.4) requires both bits to be 0 unless an OBU element is actually fragmented across the two packets. Receivers that honor the bits therefore join two complete OBUs into one: this happens with the decoder in this package, with pion/rtp and with ffmpeg. It is reachable whenever an earlier OBU leaves exactly 0 free bytes (or 0-2 when the next OBU is size-prefixed), so it affects streams that are repacketized, e.g. non-RTSP sources read over RTSP in mediamtx. Co-authored-by: aler9 46489434+aler9@users.noreply.github.com
RTMP
- reader: support empty H264 configs (#6132) (bluenviron/gortmplib#118)
- writer: fix crash in case of invalid H264/H265 parameters (bluenviron/gortmplib#122)
- reader: do not accept empty H264/H265 parameters (bluenviron/gortmplib#121)
- server: always strip auth parameters from URL (bluenviron/gortmplib#76) (bluenviron/gortmplib#123)
HLS
- validate hlsSegmentCount according to the HLS variant (#6154)
WebRTC
- Register RTX for incoming video tracks (#6125)
- fix deprecated webrtcICEServers parser for IPv6 hosts; (#5932)
RPI Camera
- drop support for Debian Bullseye (bluenviron/mediamtx-rpicamera#119) Bullseye reached EOL on 31st august 2026.
Dependencies
- code.cloudfoundry.org/bytefmt updated from v0.85.0 to v0.88.0
- github.com/bluenviron/gohlslib/v2 updated from v2.4.3 to v2.4.4
- github.com/bluenviron/gortmplib updated from v1.0.1 to v1.0.2
- github.com/bluenviron/gortsplib/v5 updated from v5.6.4 to v5.6.5
- github.com/bluenviron/mediacommon/v2 updated from v2.9.3 to v2.9.4
- github.com/matthewhartstonge/argon2 updated from v1.5.6 to v1.5.7
- github.com/pion/webrtc/v4 updated from v4.2.18 to v4.2.19
- github.com/quic-go/quic-go updated from v0.61.0 to v0.62.0
- github.com/quic-go/webtransport-go updated from v0.12.0 to v0.13.0
- github.com/stretchr/testify updated from v1.12.0 to v1.12.1
- github.com/dunglas/httpsfv updated from v1.1.0 to v1.1.1
- github.com/pion/stun/v3 updated from v3.1.6 to v3.1.7
- github.com/pion/turn/v5 updated from v5.0.12 to v5.0.13
- gopkg.in/yaml.v3 removed
- go.yaml.in/yaml/v3 v3.0.5 added
- github.com/bluenviron/mediamtx-rpicamera updated from v2.8.0 to v2.9.0
- hls.js updated from v1.7.0 to v1.7.2
Security
Binaries are compiled from source code by the Release workflow, which is a fully-visible process that prevents any change or external interference in produced artifacts.
Checksums of binaries are also published in a public blockchain by using GitHub Attestations, and they can be verified by running:
ls mediamtx_* | xargs -L1 gh attestation verify --repo bluenviron/mediamtx
You can verify checksums of binaries by downloading checksums.sha256 and running:
cat checksums.sha256 | grep "$(ls mediamtx_*)" | sha256sum --check