Methods
(static) formatAudioChannels(channels) → {string}
formatAudioChannels: Convert channel count integer to display format Ignores ChannelLayout field since it can return inconsistent strings (for example "stereo")
| Name | Type | Description |
|---|---|---|
channels | integer | Number of audio channels |
- Channel layout string (for example "2.0", "5.1", "7.1") or "" if invalid/zero
- Type:
- string
(static) formatAudioDisplayTitle(stream) → {string}
formatAudioDisplayTitle: Build a display title for an audio stream Format: "Language CODEC CHANNELS" or "Language CODEC CHANNELS (Default)"
| Name | Type | Description |
|---|---|---|
stream | object | Audio MediaStream object from Jellyfin API |
- Formatted display title (for example "English AAC 2.0 (Default)") or "N/A" if insufficient data
- Type:
- string
(static) formatSubtitleDisplayTitle(stream, cacheopt) → {string}
formatSubtitleDisplayTitle: Build a display title for a subtitle stream Format: "Language CODEC", optionally followed by a parenthesized flag list: "English SUBRIP (Hearing impaired)", "English SUBRIP (Hearing impaired, Forced)". The language is omitted for "und"/Undefined. The flags matter: the panel badges hearing-impaired, so without it the dropdown and the panel described the same track differently.
| Name | Type | Attributes | Default | Description |
|---|---|---|---|---|
stream | object | Subtitle MediaStream object from Jellyfin API | ||
cache | object | <optional> | invalid | translateCached() batch cache, for a caller labeling many tracks |
- Formatted display title (for example "English SUBRIP (Forced)") or "N/A" if insufficient data
- Type:
- string
(static) formatSubtitleTrackLabel(stream, markExternalopt, cacheopt) → {string}
formatSubtitleTrackLabel: The label a subtitle list shows for one track. The details-screen dropdown and the playback picker both use it, so the same track reads the same on both. It was two paths once, and the picker's (the server's DisplayTitle verbatim) led with "Undefined" for a track with no language.
A track's own Title leads when it has one, because it is often the only thing telling two tracks apart: "Spanish (Latin America)" and "Spanish (Spain)" are both "Spanish SUBRIP" by language and codec, as are a "Signs" track and a full one. This is the server's own DisplayTitle rule, minus its "Undefined" placeholder: the Title, then each part it does not already say. A Title that names the language stands in for it, so the codec follows with a space ("English (SDH) SUBRIP"); otherwise " · " separates the two ("SDH · English SUBRIP (Hearing impaired)").
A file kept outside the video gets a marker. "External" is the word Jellyfin and the playback report use for it, and it covers a download and a file placed by hand alike. When there is no Title, language or codec to build from, the server's DisplayTitle says more than "N/A".
| Name | Type | Attributes | Default | Description |
|---|---|---|---|---|
stream | object | Subtitle MediaStream object from Jellyfin API | ||
markExternal | boolean | <optional> | true | false for a slot that shows the track alone, without the entries the marker distinguishes it from |
cache | object | <optional> | invalid | translateCached() batch cache, for a caller labeling many tracks |
- for example "English SUBRIP", "SAMI · External", "Spanish (Latin America) SUBRIP"; "N/A" if there is nothing to describe it by
- Type:
- string
(static) formatVideoDisplayTitle(stream) → {string}
formatVideoDisplayTitle: Build a display title for a video stream Format: "RESOLUTION CODEC" or "RESOLUTION CODEC RANGETYPE" (when HDR)
| Name | Type | Description |
|---|---|---|
stream | object | Video MediaStream object from Jellyfin API |
- Formatted display title (for example "4K HEVC HDR10") or "N/A" if insufficient data
- Type:
- string
(static) formatVideoRangeLabel(stream) → {string}
formatVideoRangeLabel: The dynamic-range label for a video stream.
Extracted from formatVideoDisplayTitle so the playback-info report can name the same range the track pickers do, rather than growing a second copy of the Dolby Vision profile/compatibility formatting.
Callers differ in one way, and this function leaves that choice to them on purpose: formatVideoDisplayTitle only asks for a label when VideoRange is "HDR", because "1080p H264 SDR" is noise in a picker row. The report asks unconditionally, because "SDR" is exactly what it needs to render on the target side of a tone-mapping transcode.
VideoRangeType is a 10.8+ field, so on the floor server this falls back to the coarse VideoRange ("SDR" / "HDR") that has existed throughout.
| Name | Type | Description |
|---|---|---|
stream | object | Video MediaStream object from Jellyfin API |
- for example "DV 8.1", "HDR10+", "HLG", "SDR", or "" with nothing to go on
- Type:
- string
(static) getVideoResolutionLabel(width, height, isInterlaced) → {string}
getVideoResolutionLabel: Determine resolution label from video dimensions Resolution thresholds check width OR height (either can qualify) 4K never gets p/i suffix. All other resolutions get "p" or "i" based on interlacing.
| Name | Type | Description |
|---|---|---|
width | integer | Video width in pixels |
height | integer | Video height in pixels |
isInterlaced | boolean | Whether the video is interlaced |
- Resolution label (for example "4K", "1080p", "720i") or "" if below all thresholds
- Type:
- string
(static) joinSubtitleLabelParts(language, codec, flags) → {string}
joinSubtitleLabelParts: "Language CODEC (flag, flag)", leaving out whatever is empty. "" when there is no language and no codec, whatever the flags: a flag alone does not say which track it is.
| Name | Type | Description |
|---|---|---|
language | string | |
codec | string | |
flags | object |
- Type:
- string
(static) resolveLanguageName(langCode, cacheopt) → {string}
resolveLanguageName: Convert a media stream language code to a localized display name.
MediaStream.Language passes through whatever the container metadata holds: ffmpeg/Jellyfin do not normalize, so real-world inputs include ISO 639-2/T ("fra"), 639-2/B ("fre"), 639-1 ("fr"), and BCP-47 tags ("fr-FR", "pt_BR").
Three-tier resolution chain:
- Lowercase + strip after first "-" or "_" (drop region/script suffix)
- "und" / "zxx" give "": caller omits the language label
- Alias map: normalize 3-letter / deprecated codes to a base form
- Tier 1: translationKey lookup, then translate(): localized to user's UI
- Tier 2: English-name fallback: covers every other ISO 639-2 code
- Tier 3: raw code passthrough: last-resort, preserves info
"und" (Undefined) and "zxx" (No linguistic content: instrumental music, ambient sound, foley) are both omitted: rendering "No linguistic content EAC3 5.1" as a track label is noisier than plain "EAC3 5.1". The other ISO 639-2 special codes ("mul" Multiple, "mis" Uncoded) ARE displayed because they convey real information when they appear.
| Name | Type | Attributes | Default | Description |
|---|---|---|---|---|
langCode | string | Media stream language code from any common format | ||
cache | object | <optional> | invalid | translateCached() batch cache |
- Localized name, English fallback, "" for und/zxx, or raw code
- Type:
- string
(static) subtitleLabelParts(stream, cacheopt) → {object}
subtitleLabelParts: What a subtitle stream says about itself, as the pieces its labels are built from: the full language name ("" for none, "und" or "zxx"), the codec uppercased ("" for none), and the flags in display order. Hearing-impaired leads because it changes what the track IS rather than when it plays; Forced takes precedence over Default if both are set.
| Name | Type | Attributes | Default | Description |
|---|---|---|---|---|
stream | object | Subtitle MediaStream object from Jellyfin API | ||
cache | object | <optional> | invalid | translateCached() batch cache, for a caller labeling many tracks |
- { language as string, codec as string, flags as roArray of string }
- Type:
- object