Record: Corrupted fMP4 segments in storage for RTSP/H.264 sources — frame drops and playback stuttering when downloading clips
Which version are you using?
1.21.0
Which operating system are you using?
Linux arm64 standard, Linux amd64 standard
Describe the issue
When using RTSP/H.264 sources from some Optimus cameras, corrupted MP4 files are found in the storage when using the fMP4 format. As a result, when downloading a clip from the archive, playback in the browser stutters and jumps.
FFmpeg reports the following errors: missing picture in access unit with size 9 no frame! Invalid data found when processing input Application provided invalid, non monotonically increasing dts to muxer in stream 0: xxx >= xxx
GetClip and RecordFile attached from Google Disk. https://drive.google.com/file/d/1sGJ7SoTIYGO1t75-MdI__ZAC-M7RbkAi/view https://drive.google.com/file/d/1SpUCTfQD4km1MrPj73DRlDcNyw5k5OKX/view
Describe how to replicate the issue
- start the MediaMTX
- configure MediaMTX to record an RTSP/H.264 stream from Optimus camera into fMP4 storage
- let the recording run for some time
- download and play a clip from the archive (attached)
- stop MediaMTX
- check for error in ffmpeg clip and record files (attached)
Checked in Optimus cameras V5.00.R02.J38309ED.10010.348700.0020000 and V4.02.R12.00018531.10012.140800.00000
MediaMTX configuration
###############################################
# Global settings
# Settings in this section are applied anywhere.
###############################################
# Global settings -> General
# Verbosity of the program; available values are "error", "warn", "info", "debug".
logLevel: debug
# Destinations of log messages; available values are "stdout", "file" and "syslog".
logDestinations: [file]
# When destination is "stdout" or "file", emit logs in structured format (JSONL).
logStructured: false
# When "file" is in logDestinations, this is the file which will receive logs.
logFile: mediamtx.log
# When "syslog" is in logDestinations, use prefix for logs.
sysLogPrefix: mediamtx
# Dump packets to disk. This is useful for debugging.
dumpPackets: true
# Timeout of read operations.
readTimeout: 10s
# Timeout of write operations.
writeTimeout: 10s
# Size of the queue of outgoing packets.
# A higher value allows to increase throughput, a lower value allows to save RAM.
writeQueueSize: 512
# Maximum size of outgoing UDP payloads.
# It defaults to the maximum packet size on ethernet (1500) minus IPv6 and UDP headers (48).
# This can be decreased to avoid fragmentation on networks with a low MTU.
udpMaxPayloadSize: 1452
# Size of the read buffer of every UDP socket.
# This can be increased to decrease packet losses.
# It defaults to the default value of the operating system.
udpReadBufferSize: 0
# Command to run when a client connects to the server.
# This is terminated with SIGINT when a client disconnects from the server.
# The following environment variables are available:
# * MTX_CONN_TYPE: connection type
# * MTX_CONN_ID: connection ID
# * RTSP_PORT: RTSP server port
runOnConnect:
# Restart the command if it exits.
runOnConnectRestart: false
# Command to run when a client disconnects from the server.
# Environment variables are the same as runOnConnect.
runOnDisconnect:
###############################################
# Global settings -> Authentication
# Authentication method. Available values:
# * Internal database: credentials are stored in the configuration file
# * External HTTP server: an external HTTP URL is contacted for each authentication request
# * External JWT provider: credentials are signed tokens released by an external identity server
authMethod: internal
# Internal authentication.
# Enabled users.
authInternalUsers:
# Default unprivileged user.
# Username. 'any' means any user, including anonymous ones.
- user: any
# Password. Not used in case of 'any' user.
pass:
# IPs or networks allowed to use this user. An empty list means any IP.
ips: []
# Permissions.
permissions:
# Available actions are: publish, read, playback, api, metrics, pprof.
- action: publish
# Paths can be set to further restrict access to a specific path.
# An empty path means any path.
# Regular expressions can be used by using a tilde as prefix.
path:
- action: read
path:
- action: playback
path:
# Default administrator.
# This allows to use API, metrics and PPROF without authentication,
# if the IP is localhost.
- user: any
pass:
ips: ["127.0.0.1", "::1","0.0.0.0","10.243.30.10"]
permissions:
- action: api
- action: metrics
- action: pprof
# HTTP-based authentication.
# URL called to perform authentication. Every time a user wants
# to perform an action, the server calls this URL with the POST method
# and a payload described in the documentation.
# If the response code is 20x, the action is allowed, otherwise
# it is forbidden.
authHTTPAddress:
# If the HTTP authentication URL has a self-signed or invalid certificate,
# you can provide the fingerprint of the certificate in order to
# validate it anyway. It can be obtained by running:
# openssl s_client -connect auth_http_domain:443 </dev/null 2>/dev/null | sed -n '/BEGIN/,/END/p' > server.crt
# openssl x509 -in server.crt -noout -fingerprint -sha256 | cut -d "=" -f2 | tr -d ':'
authHTTPFingerprint:
# Actions to exclude from HTTP-based authentication.
# Format is the same as the one of user permissions.
authHTTPExclude: []
# JWT-based authentication.
# Users have to log in through an external identity server and obtain a JWT.
# This JWT must contain the claim "mediamtx_permissions" with permissions,
# for instance:
# {
# "mediamtx_permissions": [
# {
# "action": "publish",
# "path": "somepath"
# }
# ]
# }
# Users are expected to pass the JWT in the Authorization header or as password.
# This is the JWKS URL that will be used to pull (once) the public key that allows
# to validate JWTs.
authJWTJWKS:
# If the JWKS URL has a self-signed or invalid certificate,
# you can provide the fingerprint of the certificate in order to
# validate it anyway. It can be obtained by running:
# openssl s_client -connect jwt_jwks_domain:443 </dev/null 2>/dev/null | sed -n '/BEGIN/,/END/p' > server.crt
# openssl x509 -in server.crt -noout -fingerprint -sha256 | cut -d "=" -f2 | tr -d ':'
authJWTJWKSFingerprint:
# name of the claim that contains permissions.
authJWTClaimKey: mediamtx_permissions
# Actions to exclude from JWT-based authentication.
# Format is the same as the one of user permissions.
authJWTExclude: []
# Expected issuer (iss) claim in the JWT. Leave empty to skip validation.
authJWTIssuer:
# Expected audience (aud) claim in the JWT. Leave empty to skip validation.
authJWTAudience:
###############################################
# Global settings -> Control API
# Enable the control API server, which allows to control the server.
api: true
# Address of the TCP/HTTP listener.
apiAddress: :9997
# Enable HTTPS.
apiEncryption: false
# Path to the server key. This is needed only when encryption is yes.
# This can be generated with:
# openssl genrsa -out server.key 2048
# openssl req -new -x509 -sha256 -key server.key -out server.crt -days 3650
apiServerKey: server.key
# Path to the server certificate.
apiServerCert: server.crt
# Allowed CORS origins.
# Supports wildcards: ['http://*.example.com']
apiAllowOrigins: []
# IPs or CIDRs of proxies placed before the HTTP server.
# These proxies can use the X-Forwarded-For header to set the real IP of clients,
# and the X-Forwarded-Proto header to set the original protocol.
apiTrustedProxies: []
###############################################
# Global settings -> Metrics server
# Enable the metrics server, which allows to extract Prometheus-compatible metrics.
metrics: false
# Address of the TCP/HTTP listener.
metricsAddress: :9998
# Enable HTTPS.
metricsEncryption: false
# Path to the server key. This is needed only when encryption is yes.
# This can be generated with:
# openssl genrsa -out server.key 2048
# openssl req -new -x509 -sha256 -key server.key -out server.crt -days 3650
metricsServerKey: server.key
# Path to the server certificate.
metricsServerCert: server.crt
# Allowed CORS origins.
# Supports wildcards: ['http://*.example.com']
metricsAllowOrigins: []
# IPs or CIDRs of proxies placed before the HTTP server.
# These proxies can use the X-Forwarded-For header to set the real IP of clients,
# and the X-Forwarded-Proto header to set the original protocol.
metricsTrustedProxies: []
###############################################
# Global settings -> PPROF server
# Enable the PPROF server, which allows to extract performance reports.
pprof: false
# Address of the TCP/HTTP listener.
pprofAddress: :9999
# Enable HTTPS.
pprofEncryption: false
# Path to the server key. This is needed only when encryption is yes.
# This can be generated with:
# openssl genrsa -out server.key 2048
# openssl req -new -x509 -sha256 -key server.key -out server.crt -days 3650
pprofServerKey: server.key
# Path to the server certificate.
pprofServerCert: server.crt
# Allowed CORS origins.
# Supports wildcards: ['http://*.example.com']
pprofAllowOrigins: []
# IPs or CIDRs of proxies placed before the HTTP server.
# These proxies can use the X-Forwarded-For header to set the real IP of clients,
# and the X-Forwarded-Proto header to set the original protocol.
pprofTrustedProxies: []
###############################################
# Global settings -> Playback server
# Enable the playback server, which allows to download recordings from the server.
playback: true
# Address of the TCP/HTTP listener.
playbackAddress: :9996
# Enable HTTPS.
playbackEncryption: false
# Path to the server key. This is needed only when encryption is yes.
# This can be generated with:
# openssl genrsa -out server.key 2048
# openssl req -new -x509 -sha256 -key server.key -out server.crt -days 3650
playbackServerKey: server.key
# Path to the server certificate.
playbackServerCert: server.crt
# Allowed CORS origins.
# Supports wildcards: ['http://*.example.com']
playbackAllowOrigins: ["*"]
# IPs or CIDRs of proxies placed before the HTTP server.
# These proxies can use the X-Forwarded-For header to set the real IP of clients,
# and the X-Forwarded-Proto header to set the original protocol.
playbackTrustedProxies: []
###############################################
# Global settings -> RTSP server
# Enable the RTSP server, which allows to publish and read streams with the RTSP protocol.
rtsp: true
# Enabled RTSP transport protocols. The handshake is always performed with TCP.
#rtspTransports: [udp,multicast,tcp]
rtspTransports: [tcp]
# Use secure protocol variants (RTSPS, SRTP, SRTCP).
# Available values are "no", "strict", "optional".
rtspEncryption: "no"
# Address of the TCP/RTSP listener. This is needed only when encryption is "no" or "optional".
rtspAddress: :8554
# Address of the TCP/RTSPS listener. This is needed only when encryption is "strict" or "optional".
rtspsAddress: :8322
# Address of the UDP/RTP listener. This is needed only when "udp" is in rtspTransports and encryption is "no" or "optional".
rtpAddress: :8000
# Address of the UDP/RTCP listener. This is needed only when "udp" is in rtspTransports and encryption is "no" or "optional".
rtcpAddress: :8001
# IP range of all UDP-multicast listeners. This is needed only when "multicast" is in rtspTransports and encryption is "no" or "optional".
multicastIPRange: 224.1.0.0/16
# Port of all UDP-multicast/RTP listeners. This is needed only when "multicast" is in rtspTransports and encryption is "no" or "optional".
multicastRTPPort: 8002
# Port of all UDP-multicast/RTCP listeners. This is needed only when "multicast" is in rtspTransports and encryption is "no" or "optional".
multicastRTCPPort: 8003
# Address of the UDP/SRTP listener. This is needed only when "udp" is in rtspTransports and encryption is "strict" or "optional".
srtpAddress: :8004
# Address of the UDP/SRTCP listener. This is needed only when "udp" is in rtspTransports and encryption is "strict" or "optional".
srtcpAddress: :8005
# Port of all UDP-multicast/SRTP listeners. This is needed only when "multicast" is in rtspTransports and encryption is "strict" or "optional".
multicastSRTPPort: 8006
# Port of all UDP-multicast/SRTCP listeners. This is needed only when "multicast" is in rtspTransports and encryption is "strict" or "optional".
multicastSRTCPPort: 8007
# Path to the server key. This is needed only when encryption is "strict" or "optional".
# This can be generated with:
# openssl genrsa -out server.key 2048
# openssl req -new -x509 -sha256 -key server.key -out server.crt -days 3650
rtspServerKey: server.key
# Path to the server certificate. This is needed only when encryption is "strict" or "optional".
rtspServerCert: server.crt
# Authentication methods. Available are "basic" and "digest".
# "digest" doesn't provide any additional security and is available for compatibility only.
rtspAuthMethods: [basic]
# IPs or CIDRs of proxies placed before the RTSP server.
# If the server receives a request from one of these entries, IP in logs
# and authentication will be taken from the PROXY protocol header.
rtspTrustedProxies: []
###############################################
# Global settings -> RTMP server
# Enable the RTMP server, which allows to publish and read streams with the RTMP protocol.
rtmp: false
# Use the secure protocol variant (RTMPS).
# Available values are "no", "strict", "optional".
rtmpEncryption: "no"
# Address of the TCP/RTMP listener. This is needed only when encryption is "no" or "optional".
rtmpAddress: :1935
# Address of the TCP/RTMPS listener. This is needed only when encryption is "strict" or "optional".
rtmpsAddress: :1936
# Path to the server key. This is needed only when encryption is "strict" or "optional".
# This can be generated with:
# openssl genrsa -out server.key 2048
# openssl req -new -x509 -sha256 -key server.key -out server.crt -days 3650
rtmpServerKey: server.key
# Path to the server certificate. This is needed only when encryption is "strict" or "optional".
rtmpServerCert: server.crt
# IPs or CIDRs of proxies placed before the RTMP server.
# If the server receives a request from one of these entries, IP in logs
# and authentication will be taken from the PROXY protocol header.
rtmpTrustedProxies: []
###############################################
# Global settings -> HLS server
# Enable the HLS server, which allows to read streams with the HLS protocol.
hls: true
# Address of the TCP/HTTP listener.
hlsAddress: :8888
# Enable HTTPS.
# This is required for Low-Latency HLS to function correctly on Apple devices.
hlsEncryption: false
# Path to the server key. This is needed only when encryption is yes.
# This can be generated with:
# openssl genrsa -out server.key 2048
# openssl req -new -x509 -sha256 -key server.key -out server.crt -days 3650
hlsServerKey: server.key
# Path to the server certificate.
hlsServerCert: server.crt
# Allowed CORS origins.
# Supports wildcards: ['http://*.example.com']
hlsAllowOrigins: ["*"]
# IPs or CIDRs of proxies placed before the HLS server.
# If the server receives a request from one of these entries, IP in logs
# will be taken from the X-Forwarded-For header.
hlsTrustedProxies: []
# By default, HLS is generated only when requested by a user.
# This option allows to generate it always, avoiding the delay between request and generation.
hlsAlwaysRemux: false
# Variant of the HLS protocol to use. Available options are:
# * mpegts - uses MPEG-TS segments, for maximum compatibility.
# * fmp4 - uses fragmented MP4 segments, more efficient.
# * lowLatency - uses Low-Latency HLS.
hlsVariant: lowLatency
# Number of HLS segments to keep on the server.
# Segments allow to seek through the stream.
# Their number doesn't influence latency.
hlsSegmentCount: 7
# Minimum duration of each segment.
# A player usually puts 3 segments in a buffer before reproducing the stream.
# The final segment duration is also influenced by the interval between IDR frames,
# since the server changes the duration in order to include at least one IDR frame
# in each segment.
hlsSegmentDuration: 1s
# Minimum duration of each part.
# A player usually puts 3 parts in a buffer before reproducing the stream.
# Parts are used in Low-Latency HLS in place of segments.
# Part duration is influenced by the distance between video/audio samples
# and is adjusted in order to produce segments with a similar duration.
hlsPartDuration: 200ms
# Maximum size of each segment.
# This prevents RAM exhaustion.
hlsSegmentMaxSize: 50M
# Directory in which to save segments and non-low-latency playlists.
# This has two purposes: offloading RAM and creating a self-consistent directory
# that can be served by a CDN.
hlsDirectory: ""
# The muxer will be closed when there are no
# reader requests and this amount of time has passed.
hlsMuxerCloseAfter: 60s
# Secret to identify requests coming from a CDN.
# The CDN must insert this secret in every request in the
# 'Authorization: Bearer' header.
hlsCDNSecret: ""
###############################################
# Global settings -> WebRTC server
# Enable the WebRTC server, which allows to publish and read streams with the WebRTC protocol.
webrtc: true
# Address of the WebRTC TCP/HTTP listener.
webrtcAddress: :8889
# Enable HTTPS.
# This covers only the WebRTC handshake, while WebRTC streams
# are always encrypted with a key that is exchanged during the WebRTC handshake.
webrtcEncryption: false
# Path to the server key.
# This can be generated with:
# openssl genrsa -out server.key 2048
# openssl req -new -x509 -sha256 -key server.key -out server.crt -days 3650
webrtcServerKey: server.key
# Path to the server certificate.
webrtcServerCert: server.crt
# Allowed CORS origins.
# Supports wildcards: ['http://*.example.com']
webrtcAllowOrigins: ["*"]
# IPs or CIDRs of proxies placed before the WebRTC server.
# If the server receives a request from one of these entries, IP in logs
# will be taken from the X-Forwarded-For header.
webrtcTrustedProxies: []
# Address of a UDP/ICE listener that will receive connections.
# Use a blank string to disable.
webrtcLocalUDPAddress: :8189
# Address of a TCP/ICE listener that will receive connections.
# This is disabled by default since TCP is less efficient than UDP and
# introduces a progressive delay when network is congested.
webrtcLocalTCPAddress: ""
# WebRTC clients need to know the IP of the server.
# Gather IPs from interfaces and send them to clients.
webrtcIPsFromInterfaces: true
# Interfaces whose IPs will be sent to clients.
# An empty value means to use all available interfaces.
webrtcIPsFromInterfacesList: []
# Additional hosts or IPs to send to clients.
webrtcAdditionalHosts: []
# ICE servers. Needed only when local listeners can't be reached by clients.
# STUN servers allow to obtain and share the public IP of the server.
# TURN/TURNS servers force all traffic through them.
webrtcICEServers2: []
# - url: stun:stun.l.google.com:19302
# if user is "AUTH_SECRET", then authentication is secret based.
# the secret must be inserted into the password field.
# username: ''
# password: ''
# clientOnly: false
# Maximum time to gather STUN candidates.
webrtcSTUNGatherTimeout: 5s
# Time to wait for the WebRTC handshake to complete.
webrtcHandshakeTimeout: 10s
# Maximum time to gather tracks.
webrtcTrackGatherTimeout: 2s
###############################################
# Global settings -> SRT server
# Enable the SRT server, which allows to publish and read streams with the SRT protocol.
srt: false
# Address of the UDP/SRT listener.
srtAddress: :8890
###############################################
# MoQ server
# Enable the MoQ (Media over QUIC) server, which allows to publish and read streams with the MoQ protocol.
moq: false
# Address of the TCP/HTTP2 listener.
# This hosts the web client.
moqHTTP2Address: :8892
# Address of the UDP/HTTPSource: bluenviron/mediamtx