versionLabels

Labels for the alternate versions (MediaSources) of one item.

A version label has to answer "how is this file different from the others?" in a slot that ellipsizes: the details screen's collapsed Video trigger is 278 px wide. Before, every label was the full MediaSource.Name followed by resolution and codec, so a release-style name ("Silicon Valley - S04E06 - Customer Service WEBDL-1080p") filled the slot and the stream info was cut off. Measured on a Roku Ultra against Jellyfin 12.0. Since 12.0 resumes the exact file that holds the position and never upgrades on its own, the label is what tells a viewer which file they are about to play.

ONE RULE per part, each computed across ALL the versions, which is why this takes the whole list rather than one source:

Stream info: only the video fields that DIFFER between versions (resolution, codec, HDR range), and it comes first, so it survives the ellipsis. Versions whose video is identical (a bitrate ladder) get none, since repeating "1080p AV1" on every row does not help anyone choose. Audio is left out: the Audio dropdown lists it per version. Name: the words EVERY version shares are dropped from the start and the end, comparing case-insensitively with space, ".", "-" and "_" as separators. Only shared words go, so nothing that tells two versions apart is lost; the rest is kept as written. Then the words at either end that repeat a label the row's stream info already shows go too ("1080p", not "1080p · 1080p", for Jellyfin's "Movie - 1080p" naming). That is a plain comparison against whole labels, never a reading: names are user-controlled, so nothing here reads quality out of them ("2160p" stays beside "4K"). Fallback: a version left with no text at all shows its full name, then its full stream summary. Two versions that are identical in every field keep identical labels; an ordinal would be arbitrary (see remoteSubtitles.subtitleDropdownEntries).

TWO FORMS, because the places that name a version do different jobs:

title is the FULL label (stream info + name), for the lists a viewer CHOOSES from: the details screen's open Video menu and the in-player Select Video Source dialog. triggerTitle is the SHORT label, for the places that only say which version is current: the collapsed Video trigger and the player title. It is the stream info alone when that identifies the version among the others, and the full label otherwise.

Why the short form drops the name: a name is free text. Sometimes it is the only thing that matters (an edition), sometimes it is a whole release filename. Jellyfin returns the full filename when a version's file shares no naming pattern with the others (measured on 12.0: "silicon.valley.s04e06.720p.web.h264-tbs"), and MediaSourceInfo has no edition field to read instead (checked in the 12.0 spec). The cost accepted: two editions that also differ in quality show only the quality once picked ("4K HEVC", not "Director's Cut"); the list the viewer picked from showed both.

A single version has nothing to be told apart from and keeps the plain stream summary.

PURE: plain values in, plain values out, so every rule is unit-testable.

Members

(static, constant) MARKER_SEPARATOR

Default Value
  • ·

(static, constant) STREAM_NAME_SEPARATOR

Default Value
  • ·

Methods

(static) allTokensMatch(tokenLists, offset, fromEnd) → {boolean}

allTokensMatch: Whether every list has the same word at offset, counted from the start, or from the end when fromEnd is true. Case-insensitive.

Parameters:
NameTypeDescription
tokenListsobject
offsetinteger
fromEndboolean
Returns:
Type: 
boolean

(static) distinctNameParts(names) → {object}

distinctNameParts: Each name with the words every name shares removed from both ends.

Parameters:
NameTypeDescription
namesobject

array of strings ("" for a version with no name)

Returns:

array of strings, index-aligned with names; "" where nothing is left

Type: 
object

(static) fieldDiffers(fields, key) → {boolean}

Parameters:
NameTypeDescription
fieldsobject
keystring
Returns:
Type: 
boolean

(static) labelsFor(mediaSources, inProgressSourceId) → {object}

labelsFor: A label for each version, in the order given.

The caller passes exactly the versions the user chooses between (the details screen shows only VideoFile sources), because each label depends on the others. Entries that are not a source with an Id are skipped, as both pickers skip them.

invalid for none. Marks title only: the marker means something only beside the rows it is distinguishing from.

Parameters:
NameTypeDescription
mediaSourcesdynamic

MediaSourceInfo array

inProgressSourceIddynamic

the version the viewer is partway through, or "" /

Returns:

array of { id, title, triggerTitle } (see TWO FORMS above)

Type: 
object

(static) streamSummary(source) → {string}

streamSummary: The full video summary of one version ("1080p H264"), or "N/A" when it has no video stream.

Parameters:
NameTypeDescription
sourceobject
Returns:
Type: 
string

(static) tokenize(name) → {object}

tokenize: The words of a name, split on space, ".", "-" and "_", each with its position so the kept part can be cut from the original text unchanged.

Parameters:
NameTypeDescription
namestring
Returns:

array of { start, length, lower } (start is 0-based)

Type: 
object

(static) triggerLabelFor(mediaSources, sourceId) → {string}

triggerLabelFor: The short label of one version, judged against all of them. What the player shows beside the title.

Parameters:
NameTypeDescription
mediaSourcesdynamic

MediaSourceInfo array

sourceIddynamic

the version to name (matched ignoring case)

Returns:

the label, or "" when there is nothing to tell apart or no such version

Type: 
string

(static) trimShownLabels(text, shownLabels) → {string}

trimShownLabels: A name part without the words at either end that repeat a label its row already shows. Each label is matched whole, ignoring case, so a label that is several words ("DV 8.1") never matches part of a name ("Part 8"). Words in the middle stay, so what is left is still cut from the text unchanged.

Parameters:
NameTypeDescription
textstring

a name part from distinctNameParts

shownLabelsobject

the row's stream-info labels ("1080p", "HEVC", ...)

Returns:

the trimmed part; "" when every word repeats a shown label

Type: 
string

(static) videoFields(source) → {object}

videoFields: The comparable parts of a version's first video stream, each written as formatVideoDisplayTitle writes it ("" when absent). The range is only named for HDR, as there: "SDR" on every row is noise.

Parameters:
NameTypeDescription
sourceobject
Returns:
Type: 
object