Skip to content

Verify should deterministically detect Direct Play failures (e.g. run the same Matroska/EBML parse Jellyfin uses), then remux only those #746

Description

@ptr727

Summary

A file can be 100% valid to ffprobe, ffmpeg, mkvmerge, and mkvinfo (rc=0, no errors, no warnings) yet still fail Direct Play in the players PlexCleaner targets (Jellyfin/Emby, Android TV / NVIDIA Shield / ExoPlayer). Because PlexCleaner's Verify/AutoRepair is built on exactly those tools, it reports the file as healthy and never remuxes it — so the file silently can't be Direct Played, which is the one thing PlexCleaner exists to guarantee.

The ask is not to remux MKVs heuristically or "just in case". Blindly remuxing every file that wasn't muxed by mkvmerge is wasteful and non-deterministic. The ask is for a deterministic check that predicts whether the target player will fail, and to remux only when that check says it will.

The deterministic signal (and why it's cheap for PlexCleaner specifically)

The failure is fully deterministic and reproducible. Jellyfin reads Matroska keyframes via Jellyfin.MediaEncoding.Keyframes.Matroska.MatroskaKeyframeExtractor, which is built on the NEbml library. On an affected file it throws every time:

[ERR] Jellyfin.MediaEncoding.Hls.Extractors.MatroskaKeyframeExtractor:
      Extracting keyframes from FILE using matroska metadata failed
System.InvalidOperationException: Operation is not valid due to the current state of the object.
   at NEbml.Core.EbmlReader.EnterContainer()
   at Jellyfin.MediaEncoding.Keyframes.Matroska.MatroskaKeyframeExtractor.GetKeyframeData(String filePath)

The Shield (Jellyfin Android TV / ExoPlayer) independently hangs at 0 ms with no server transcode ever started, confirming the file genuinely isn't Direct-Play-able — not an NEbml quirk.

The key point for PlexCleaner: PlexCleaner is .NET, NEbml is a .NET library, and so is Jellyfin's keyframe extractor. PlexCleaner can run the exact same structural EBML read the player uses and get a deterministic yes/no — "will Jellyfin's keyframe/Matroska parse succeed on this file?" — without re-encoding or guessing. If that read throws, the file is known-bad → remux; otherwise leave it untouched. This is a precise pass/fail oracle, not a heuristic.

(A strict Cues/SeekHead/EBML-element validation would achieve the same thing if you'd rather not take an NEbml dependency.)

Real-world repro

One episode refused to play on a Shield via Jellyfin; three siblings in the same folder played fine.

The file (broken for Direct Play): Matroska, Writing application: Lavf58.42.100 (older ffmpeg), H.264 High / E-AC3 5.1 / ASS subs.

Every tool PlexCleaner currently uses says it's clean:

$ ffmpeg -v error -i FILE -f null -                        # full decode   -> rc=0, no output
$ ffmpeg -v warning -i FILE -map 0:v -c copy -f null -     # container read -> rc=0, no output
$ mkvmerge -i FILE                                         # rc=0
$ mkvmerge -J FILE                                         # errors: []  warnings: []
$ mkvinfo FILE                                             # rc=0, parses end-to-end

Yet Jellyfin/Shield can't Direct Play it (NEbml exception + 0 ms hang above). A web client only works because that path transcodes. A plain lossless remux fixes it permanently:

$ mkvmerge -o FILE.fixed.mkv FILE      # or: ffmpeg -i FILE -map 0 -c copy FILE.fixed.mkv

Why PlexCleaner currently misses it

The "good" siblings were remuxed by PlexCleaner and show Writing application: mkvmerge. The broken one still shows Lavf58.42.100 and was left untouched because (a) it's already MKV so the container-conversion ReMux path doesn't apply, and (b) tool-based Verify reports no problem so AutoRepair never fires. Sidecar confirms: "Verified": false, original timestamp retained.

So the gap is specifically that Verify measures tool-parseability, not player-Direct-Play-ability. A deterministic player-parity check (run the same EBML/keyframe read Jellyfin runs) would close it while only remuxing files that are provably broken.

Environment

  • PlexCleaner 3.17.23+5c823303ee (docker ptr727/plexcleaner:latest)
  • Jellyfin 10.11.x + Jellyfin Android TV 0.19.9 (NVIDIA Shield)
  • mkvmerge v92.0, jellyfin-ffmpeg n7.x for diagnostics

Happy to provide a sample file, full ffprobe/mkvinfo dumps, or test a build.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions