* refactor(web): consolidate media-spec formatters into lib/mediaFormat
Media-spec formatting was duplicated with divergent behavior across six
modules: versionFormatUtils (GB/"" fallback), playback-info (GiB/"—"
fallback, CODEC_LABELS), overlay tech.ts (prettyResolution,
compactHdrSuffix), versionRankingUtils (mapAudioLabel), plus private
formatBitrate copies in ItemCard and useTranscodeQuality.
One canonical module now owns these helpers; the deliberate per-surface
display differences (fallback text, GB vs GiB labels) are parameters
instead of copies. All call sites migrated, including two cross-boundary
imports (adminActivityPresentation reaching into @/player/playback-info,
player components reaching into page-level utils). The quality-menu Mbps
label in useTranscodeQuality stays local as a distinct display policy,
renamed formatQualityBitrate. Also removes the unused TrackSection/
TrackRow components and renames versionFormatUtils.tsx to .ts.
Behavior-preserving: playback-info.test.ts and VersionFlyout.test.ts are
unmodified and assert exact rendered strings ("7.1 GiB", "640 kbps",
"Dolby Vision Profile 8.1 (HDR10)").
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* feat(web): add Media Info dialog with detailed per-file technical specs
Adds a curator/admin-gated "Media Info" dialog to movie and episode
detail pages showing full technical specs per file: per-stream bitrates,
Dolby Vision profile with base-layer compatibility and EL flags, HDR10+,
chroma subsampling derived from pixel format, color primaries/transfer/
space, bit depth, codec profile/level (H.264, HEVC, and AV1 level
decoding), audio layouts/sample rates, and subtitle stream details.
Frontend-only: the item-detail response already serialized all of this;
VersionVideoTrack in api/types.ts was just missing the DV/HDR10+/
video_range_type fields the backend sends. Entry points: a "Media Info"
item in the detail-page overflow menu (opens on the selected version)
and a per-row info button in Media locations (opens on that file). All
versions render as accordion sections with the target expanded.
Spec rows are built by pure section builders in mediaSpecSections.ts
with fixture tests covering SDR/HDR10/DV 7/DV 8.1/HDR10+/multi-track/
external-subtitle cases; the dialog is a thin renderer over them.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* fix(web): recover DV compatibility detail from video_range_type
Review follow-ups on the Media Info dialog's dynamic-range labels:
- When ffprobe omits dv_bl_signal_compatibility_id, the scanner still
derives video_range_type (DOVIWithHDR10/HLG/SDR) from color_transfer.
formatDolbyVisionLabel now falls back to that enum for the
compatibility detail instead of showing a bare "Dolby Vision
Profile 8"; explicit DV side-data fields still win when present.
- formatVideoRangeLabel checks the video_range_type mapping before the
standalone HDR10+ shortcut, so DOVIWithHDR10Plus tracks without a raw
dolby_vision string keep their Dolby Vision hint.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>