nilaoda/N_m3u8DL-RE · error · Exception

VTT cues in mp4 with multiple MDAT are not currently…

Error message

VTT cues in mp4 with multiple MDAT are not currently supported

What it means

ExtractSub expects exactly one 'mdat' box holding the raw WebVTT sample payload; a second 'mdat' would make it impossible to know which payload the TRUN presentations index into. When a second MDAT is seen (sawMDAT already true), the library throws because multi-MDAT WVTT segments are not implemented.

Solutions

  1. Re-package the segment with a packager that emits a single mdat per fragment (e.g. standard ffmpeg/Shaka packager output).
  2. Pre-process the segment to merge adjacent mdat boxes before calling ExtractSub.
  3. Patch MP4VttUtil to concatenate multiple mdat payloads and adjust presentation offsets.
  4. Use a different subtitle extraction path (demux the segment with ffmpeg and extract WebVTT directly).
Defensive patterns

Strategy: try-catch

Validate before calling

// detect multiple mdat boxes before extraction
int CountMdat(byte[] seg) { int n = 0; int i = 0;
  while (i + 8 <= seg.Length) { var size = BitConverter.ToUInt32(seg.Reverse().Skip(0).ToArray(), 0); n++; i += (int)size; }
  return n; }

Try / catch

try { var subs = MP4VttUtil.ExtractSub(dataSeg, baseTime); }
catch (Exception ex) when (ex.Message.Contains("multiple MDAT")) {
    // fall back to an external demuxer
    subs = await FallbackExtractWithFfmpegAsync(segmentFile);
}

Prevention

When it happens

Trigger: ExtractSub is called on a segment containing two or more 'mdat' boxes (e.g. a muxer emitted multiple payload boxes per fragment).

Common situations: Non-standard segment muxers/producers that emit multiple mdat boxes in one media segment; re-muxed or edited segments; unusual HLS packagers.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


AI-assisted analysis of nilaoda/N_m3u8DL-RE@e113dee70c (2026-09-13). Data as JSON: /api/errors/4da0401fc24bae0f. Report an issue: GitHub.

Appendix: source

Thrown at src/N_m3u8DL-RE.Parser/Mp4/MP4VttUtil.cs:85

                .FullBox("tfhd", box =>
                {
                    if (box.Flags == 1000)
                        throw new Exception("A TFHD box should have a valid flags value");
                    defaultDuration = MP4Parser.ParseTFHD(box.Reader, box.Flags).DefaultSampleDuration;
                })
                .FullBox("trun", box =>
                {
                    sawTRUN = true;
                    if (box.Version == 1000)
                        throw new Exception("A TRUN box should have a valid version value");
                    if (box.Flags == 1000)
                        throw new Exception("A TRUN box should have a valid flags value");
                    presentations = MP4Parser.ParseTRUN(box.Reader, box.Version, box.Flags).SampleData;
                })
                .Box("mdat", MP4Parser.AllData(data =>
                {
                    if (sawMDAT)
                        throw new Exception("VTT cues in mp4 with multiple MDAT are not currently supported");
                    sawMDAT = true;
                    rawPayload = data;
                }))
                .Parse(dataSeg,/* partialOkay= */ false);

            if (!sawMDAT && !sawTFDT && !sawTRUN)
            {
                throw new Exception("A required box is missing");
            }

            var currentTime = baseTime;
            var reader = new BinaryReader2(new MemoryStream(rawPayload!));

            foreach (var presentation in presentations)
            {
                var duration = presentation.SampleDuration == 0 ? defaultDuration : presentation.SampleDuration;
                var startTime = presentation.SampleCompositionTimeOffset != 0 ?
                    baseTime + presentation.SampleCompositionTimeOffset :

View on GitHub (pinned to e113dee70c)