SubtitleEdit/subtitleedit · error · InvalidOperationException

No VobSub subpictures found in MP4 track.

Error message

No VobSub subpictures found in MP4 track.

What it means

Thrown by BitmapSubtitleLoader.LoadMp4VobSub when, after iterating the parallel paragraphs/subPictures arrays of an MP4 'subp' track, no bitmap decoded successfully. Either the track has zero paragraphs/subpictures, or every subPictures[i].GetBitmap(...) returned null because the palette or RLE payload is unusable. It is a terminal guard for an MP4 VobSub track that cannot yield any image events.

Source

Thrown at src/seconv/Core/BitmapSubtitleLoader.cs:348

        var count = Math.Min(paragraphs.Count, subPictures.Count);

        var items = new List<BitmapSubtitleItem>(count);
        for (var i = 0; i < count; i++)
        {
            var bmp = subPictures[i].GetBitmap(
                palette, SKColors.Transparent, SKColors.Black, SKColors.White, SKColors.Black, false);
            if (bmp is null)
            {
                continue;
            }
            // ImageDisplayArea is filled in by GetBitmap above.
            var displayArea = subPictures[i].ImageDisplayArea;
            items.Add(new BitmapSubtitleItem(paragraphs[i].StartTime, paragraphs[i].EndTime, bmp,
                Position: new SKPointI(displayArea.Left, displayArea.Top)));
        }
        if (items.Count == 0)
        {
            throw new InvalidOperationException("No VobSub subpictures found in MP4 track.");
        }
        return items;
    }

    /// <summary>
    /// Transport stream DVB-sub → one bitmap list per packet ID. Caller is responsible
    /// for routing each PID to its own output file (multiple subtitle streams =
    /// multiple languages, same as the OCR path in <see cref="ImageOcrLoader"/>).
    /// </summary>
    public static List<(IReadOnlyList<BitmapSubtitleItem> Items, int PacketId)> LoadTransportStreamDvbSub(string filePath)
    {
        var parser = new TransportStreamParser();
        parser.Parse(filePath, null);

        var results = new List<(IReadOnlyList<BitmapSubtitleItem>, int)>();
        if (parser.SubtitlePacketIds.Count == 0)
        {
            return results;

View on GitHub (pinned to 17a9f07487)

Solutions

  1. Check the track with an MP4 inspector (mp4box -info / ffprobe) to confirm it carries VobSub samples and a palette.
  2. If the palette is absent, re-mux from the original .sub+.idx with a tool that writes the sample-entry CLUT.
  3. Skip the track at the caller level by catching InvalidOperationException and continuing with remaining MP4 tracks.

Example fix

// before
var items = BitmapSubtitleLoader.LoadMp4VobSub(trak);

// after
List<BitmapSubtitleItem> items;
try { items = BitmapSubtitleLoader.LoadMp4VobSub(trak).ToList(); }
catch (InvalidOperationException) { continue; }  // skip empty VobSub track
Defensive patterns

Strategy: validation

Validate before calling

// Guard before calling LoadMp4VobSub.
var paragraphs = track.Mdia.Minf.Stbl.GetParagraphs();
var subPictures = track.Mdia.Minf.Stbl.SubPictures;
if (paragraphs.Count == 0 || subPictures.Count == 0) continue;

Try / catch

try { items = BitmapSubtitleLoader.LoadMp4VobSub(trak).ToList(); }
catch (InvalidOperationException) { continue; }  // empty VobSub track, skip

Prevention

When it happens

Trigger: Calling LoadMp4VobSub(track) where track.Mdia.Minf.Stbl.GetParagraphs() and .SubPictures are both non-empty but every GetBitmap(palette, ...) at line 335 returns null (missing VobSubPalette in the sample entry, or corrupt RLE); or where count == Math.Min(paragraphs, subPictures) is 0 so the loop never runs.

Common situations: An MP4 produced by MP4Box (or a similar muxer) whose VobSub track lost its CLUT; a truncated MP4 where the subpicture samples are incomplete; a file with an 'subp' handler type that is actually empty.

Related errors


AI-assisted analysis of SubtitleEdit/subtitleedit@17a9f07487 (2026-08-13). Data as JSON: /api/errors/6eb0a457de8d3bde. Report an issue: GitHub.