Skip to content

Excessive number of chunks when streaming with RootEncoder #5810

@zeridon

Description

@zeridon

Which version are you using?

1.17.0

Which operating system are you using?

Linux amd64 standard

Describe the issue

When streaming from an application created with RootEncoder we are randomly seeing excessive number of chunks (about 7000 in one instance) when recording the streaming. The same is observed on HLS streamed from the server.

The client (device) is an android phone with RootEncoder app (https://github.com/pedroSG94/RootEncoder). It is streaming over LTE(4g) mobile network with h264/720p/1.6 Mbps CBR.

The behaviour is observed on different quality of network connectivity (not only poor). We do not have control over location, quality of connectivity of the device doing the streaming.

We have 60 ingest servers (mediamtx handling incomming rtmp traffic) and the clinets are more or less equally distributed on them. Top planned load per server is 200 streams, and we are doing extremely minimal processing (e.g. appending a bit of metadata with ffmpeg, calling few curls to external services). Servers in and of themselves are not overloaded. Usuall observed load is in the range of 90% - 95%

ffprobe of recorded (on device) segment:

  Metadata:
    major_brand     : mp42
    minor_version   : 0
    compatible_brands: isommp42
    creation_time   : 2026-04-19T19:05:27.000000Z
    com.android.version: 13
  Duration: 01:52:16.48, start: 0.000000, bitrate: 1592 kb/s
  Stream #0:0(eng): Video: h264 (Constrained Baseline) (avc1 / 0x31637661), yuv420p(tv, bt709), 1280x720, 1540 kb/s, 20 fps, 90k tbr, 90k tbn, 180k tbc (default)
    Metadata:
      creation_time   : 2026-04-19T19:05:27.000000Z
      handler_name    : VideoHandle
      vendor_id       : [0][0][0][0]
  Stream #0:1(eng): Audio: aac (LC) (mp4a / 0x6134706D), 44100 Hz, mono, fltp, 47 kb/s (default)
    Metadata:
      creation_time   : 2026-04-19T19:05:27.000000Z
      handler_name    : SoundHandle
      vendor_id       : [0][0][0][0]

ffprobe of streamed segment (recoded by mediamtx):

  Metadata:
    major_brand     : isom
    minor_version   : 512
    compatible_brands: isomiso2avc1mp41
    title           :  <metadata added with ffmpeg after segment is recorded>
    encoder         : Lavf60.16.100
  Duration: 01:52:15.93, start: 0.000000, bitrate: 1595 kb/s
  Stream #0:0(und): Video: h264 (Constrained Baseline) (avc1 / 0x31637661), yuv420p(tv, bt709), 1280x720, 1540 kb/s, 20 fps, 90k tbr, 90k tbn, 180k tbc (default)
    Metadata:
      handler_name    : VideoHandler
      vendor_id       : [0][0][0][0]
  Stream #0:1(und): Audio: aac (LC) (mp4a / 0x6134706D), 44100 Hz, mono, fltp, 47 kb/s (default)
    Metadata:
      handler_name    : SoundHandler
      vendor_id       : [0][0][0][0]

Describe how to replicate the issue

  1. start the MediaMTX
  2. publish with ...
  3. read with ...

MediaMTX configuration

# Enable the HTTP API. (for stats)
api: yes
apiAddress: 0.0.0.0:9997

metrics: no
pprof: no

# Enabled services/endpoints
rtsp: no
webrtc: no
srt: no

# Allow publishing and reading streams with the RTMP protocol.
rtmp: yes
rtmpAddress: 0.0.0.0:1935
rtmpEncryption: "no"

###############################################
# HLS settings
hls: yes
hlsAddress: 0.0.0.0:443
hlsAlwaysRemux: yes
# 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: mpegts
# 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: 10M
# Value of the Access-Control-Allow-Origin header provided in every HTTP response.
# This allows to play the HLS stream from an external website.
hlsAllowOrigin: '*'
# List of 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: ['10.0.0.0/8']
# Directory in which to save segments, instead of keeping them in the RAM.
# This decreases performance, since reading from disk is less performant than
# reading from RAM, but allows to save RAM.
hlsDirectory: '/var/www/hls'
hlsEncryption: yes
hlsServerKey: /etc/ssl.crt/privkey.pem
hlsServerCert: /etc/ssl.crt/fullchain.pem

###############################################
# Recording settings
record: yes
# Path of recording segments.
# Extension is added automatically.
# Available variables are %path (path name), %Y %m %d %H %M %S %f (time in strftime format)
recordPath: /data/recordings/%path/%Y%m%d%H%M%S%f
# Format of recorded segments.
# Currently the only available format is fmp4 (fragmented MP4).
recordFormat: fmp4
# fMP4 segments are concatenation of small MP4 files (parts), each with this duration.
# When a system failure occurs, the last part gets lost.
# Therefore, the part duration is equal to the RPO (recovery point objective).
recordPartDuration: 1s
# Minimum duration of each segment.
recordSegmentDuration: 24h
# Delete segments after this timespan.
# Set to 0s to disable automatic deletion.
recordDeleteAfter: 2400h

paths:
  # prod
  "~^(prod)/([a-z0-9]+)/([0-9]{9})(.*)":
    source: publisher
    record: yes

    overridePublisher: no
    #                                           $special1 $special2 $mode $params
    runOnReady: /var/www/scripts/send.sh started $G2 $G3 $G1 $G4
    runOnReadyRestart: no
    runOnNotReady: /var/www/scripts/send.sh stopped $G2 $G3 $G1 $G4
    #                                                                                                        $mode $special1 $special2
    runOnRecordSegmentComplete: /var/www/scripts/video_processing.py $MTX_SEGMENT_PATH /data/recordings_done $G1 $G2 $G3

MediaMTX logs

Logs look normal like client disconnecting. The process we have implemented requires the client to reauthenticate to external api to issue special token, and takes usually at least 10 seconds, so this behaviour does not look normal.

Packet dump

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions