A disc rip is offered for playback with no way to play it #41

Closed
opened 2026-08-03 17:22:09 +02:00 by Claude · 1 comment
Collaborator

A DVD rip is filed with a runtime, a container, streams and a size (#38), so a
client is offered it — and a request to play one hands ffmpeg the directory.

Input::input_path_argument (crates/jellyfin-encoding/src/input.rs) special
cases the bluray: prefix and nothing else. Upstream's
MediaEncoder.GetInputPathArgument switches on the video type and builds the
input from the same list of files the probe was pointed at:

VideoType.Dvd    => GetInputArgument(GetPrimaryPlaylistVobFiles(path, null), …)
VideoType.BluRay => GetInputArgument(GetPrimaryPlaylistM2tsFiles(path), …)

and several files become one input through a concat list
(GenerateConcatConfig).

The scan already knows which files those are —
crates/jellyfin-app/src/scan/discs.rs::playable_vobs is the port of
GetPrimaryPlaylistVobFiles, so the rule does not need writing twice, only
moving somewhere both can reach it.

Reachable only since a rip became one item rather than a folder of them.

A DVD rip is filed with a runtime, a container, streams and a size (#38), so a client is offered it — and a request to play one hands ffmpeg the directory. `Input::input_path_argument` (`crates/jellyfin-encoding/src/input.rs`) special cases the `bluray:` prefix and nothing else. Upstream's `MediaEncoder.GetInputPathArgument` switches on the video type and builds the input from the same list of files the probe was pointed at: ``` VideoType.Dvd => GetInputArgument(GetPrimaryPlaylistVobFiles(path, null), …) VideoType.BluRay => GetInputArgument(GetPrimaryPlaylistM2tsFiles(path), …) ``` and several files become one input through a concat list (`GenerateConcatConfig`). The scan already knows which files those are — `crates/jellyfin-app/src/scan/discs.rs::playable_vobs` is the port of `GetPrimaryPlaylistVobFiles`, so the rule does not need writing twice, only moving somewhere both can reach it. Reachable only since a rip became one item rather than a folder of them.
Author
Collaborator

A DVD rip is a folder, and pointing ffmpeg at a folder does nothing. It is now
read through the .vob files that play it, picked the way upstream picks them
(GetPrimaryPlaylistVobFiles): the disc's menu and each title's own are
dropped, what is left is grouped by the part number its name ends with, and the
groups holding a file big enough to be a title are the feature.

The listing is taken at play time rather than remembered, because a row records
where the rip is and not what is inside it.

Two things came out of the review and are worth naming.

A quote in a path was torn apart. The arg builders escape one as \" —
which is what .NET's parser takes it for, so upstream is right — but this
port's splitter toggled on every quote and kept the backslash. A film under a
directory with a quote in its name reached ffmpeg as several broken arguments.
Fixed with a test that fails without it. Pre-existing, and nothing to do with
rips; the branch only made it visible.

An attachment and a subtitle track are pulled from the source's own path,
not from the joined files, matching AttachmentExtractor and SubtitleEncoder.
There is one file carrying them, so there is nothing to join.

Not fixed here, and filed as #43: the files are joined with -i concat:"a|b",
the concat protocol, where upstream writes a config file and passes
-f concat -safe 0 -i <file>, the concat demuxer. Those differ in a way that
matters — the demuxer re-bases timestamps per file from measured durations, and
the grouping above can select two different title sets, whose timestamps
restart at the boundary.

A Blu-ray still goes over as the folder it is: which streams play it is written
in a playlist nothing here reads.

Neither the harness nor the ffmpeg corpus can see any of this — the corpus
generator refuses a folder outright, and the reference library holds no rip. So
the ported selection is tested directly and the joined argument is not measured
against upstream at all.

A DVD rip is a folder, and pointing ffmpeg at a folder does nothing. It is now read through the `.vob` files that play it, picked the way upstream picks them (`GetPrimaryPlaylistVobFiles`): the disc's menu and each title's own are dropped, what is left is grouped by the part number its name ends with, and the groups holding a file big enough to be a title are the feature. The listing is taken at play time rather than remembered, because a row records where the rip is and not what is inside it. Two things came out of the review and are worth naming. **A quote in a path was torn apart.** The arg builders escape one as `\"` — which is what .NET's parser takes it for, so upstream is right — but this port's splitter toggled on every quote and kept the backslash. A film under a directory with a quote in its name reached ffmpeg as several broken arguments. Fixed with a test that fails without it. Pre-existing, and nothing to do with rips; the branch only made it visible. **An attachment and a subtitle track are pulled from the source's own path**, not from the joined files, matching `AttachmentExtractor` and `SubtitleEncoder`. There is one file carrying them, so there is nothing to join. Not fixed here, and filed as #43: the files are joined with `-i concat:"a|b"`, the concat *protocol*, where upstream writes a config file and passes `-f concat -safe 0 -i <file>`, the concat *demuxer*. Those differ in a way that matters — the demuxer re-bases timestamps per file from measured durations, and the grouping above can select two different title sets, whose timestamps restart at the boundary. A Blu-ray still goes over as the folder it is: which streams play it is written in a playlist nothing here reads. Neither the harness nor the ffmpeg corpus can see any of this — the corpus generator refuses a folder outright, and the reference library holds no rip. So the ported selection is tested directly and the joined argument is not measured against upstream at all.
Sign in to join this conversation.
No description provided.