fix: name the real HDR format on the player and detail pages, and the playing audio codec in the player
[!NOTE]
Merge after #139. I tested this on top of #139's player and want it to land on that, not the current one.
Problem and reproduction
The Apple TV player's Info tab and the detail pages didn't name a file's real format:
- The player's dynamic-range badge said "HDR" for any HDR file, so a Dolby Vision file showed "HDR" and HDR10+, HDR10 and HLG weren't told apart.
- The player's audio badge showed the file version's main audio codec, not the track that's playing. With a second audio track selected the badges read
4K HDR HEVC TRUEHDwhile the Audio row saidAC3 · 5.1. - The detail pages only said
DVorHDR. The Apple TV detail page added a separateHDR10badge for profile 7 and 8.1, and Emby and Jellyfin files only ever showedHDR, because nothing read their range or Dolby Vision fields.
To reproduce: open a Dolby Vision title, note the badges on its detail page, play it, switch to an audio track with a different codec, then open the Info tab. Root cause: the player only checked the file's hdr flag and built its badges once at load from FileVersion.codecAudio, and each detail screen had its own DV/HDR logic that only read Silo's dolby_vision and video_range.
Implementation and impact
- New
PlayerStreamBadgesworks out one dynamic-range label from the selected file's video tracks:DV P<profile>when the profile is known (DV P5,DV P7,DV P8.1),DVwhen it isn't, thenHDR10+,HDR10orHLG,HDRonly when the file is HDR but the type is unknown, and nothing for SDR. The comment at the top of the file sets out where each provider's values come from. - The label names the file as it is. Profile 7 stays
DV P7even though Vivid plays it as 8.1 on a Dolby Vision display (and as its HDR10 base layer on other displays); the player's stats show the actual output. - What each provider sends, and what Vivid maps:
- Silo (
/api/v1/watch):dolby_visionis only everProfile <n>, so the.1comes fromdv_bl_compat_id, which is left out when it's 0.video_rangeis onlyDolbyVision,HDRor empty, so HDR10+, HDR10 and HLG come fromvideo_range_type,hdr10_plusand, for older probes,color_transfer.VideoTracknow decodesvideo_range_type,dv_profile,dv_bl_compat_idandhdr10_plus. - Jellyfin: the adapter now maps
VideoRangeType,DvProfile,DvBlSignalCompatibilityIdandHdr10PlusPresentFlaginto the same new fields.DOVIInvalid(Dolby Vision outside the spec, played as its base layer) isn't shown as DV. - Emby: the adapter translates
ExtendedVideoType(DolbyVision, Hdr10, Hdr10Plus, HyperLogGamma) andExtendedVideoSubtypeinto the same fields, and falls back toVideoRangetext on servers that don't send them. Emby'sExtendedVideoSubTypesreference only has two-digit values (DoviProfile02toDoviProfile92, soDoviProfile81is profile 8 with compatibility ID 1). Its API reference spells the fieldExtendedVideoSubTypewhile server JSON usesExtendedVideoSubtype, so both are read.
- Silo (
- Where the label now shows:
- the Apple TV player's Info tab (Stream badges);
- the Apple TV detail page, as one badge (
4K · DV P8.1 · ATMOS · CCinstead ofDVandHDR10); - the version pickers on both platforms (
DetailPlaybackFormatting.dynamicRangeLabel); - Continue Watching in the Apple TV Home focus info (badge text only);
- the iPhone and iPad detail page's hero chip, which now also shows for Dolby Vision with an SDR base layer (profile 8.2), and its Video range fact, which reads every video stream like the hero.
- The player's audio badge comes from the selected
PlayerTrackwith the same text as the Audio row (one shared helper), andPlayerViewModel.streamBadgesreadsaudioTracksandselectedAudioId, so the badge changes when you switch tracks. Until the engine reports a selected track, the file's main codec stands in as before. - Deliberately unchanged: card overlays (poster badges) and the catalogue-summary rows in the Home focus info have no video-track details, so they keep their DV and HDR marks; the Continue Watching overlay values aren't touched either. Downloads don't keep their video tracks, so a downloaded HDR file still shows
HDR. The player's stats and diagnostics keep reporting the engine's output. Emby and Jellyfin still leavevideoRangeanddolbyVisionempty, because the phone's Dolby Vision fact and the Apple TV Continue Watching card overlays read them. - iPhone and iPad have no player Info badges, so the player part of this is Apple TV only.
- Risk: the new
VideoTrackfields are optional and type-checked in the adapters, so a server that doesn't send them falls back toDVorHDR.
Validation
iosApp/Tests/PlayerStreamBadgesTests.swift, in bothVividTestsandVividTVTests(listed iniosApp/project.yml), covers Silo Dolby Vision profiles 5, 7, 8.1, 8.2, 8.4 and 10, compatibility from the range type, older Silo labels, HDR10+, HDR10 and HLG (including colour transfer only), the HDR fallback and SDR, Jellyfin and Emby through their realversion()mapping and decoder, that the detail label matches the player for all three providers (and, on tvOS, that the detail page showsDV P8.1as one badge with noHDR10), and the audio badge following the playing track.DetailVersionSelectionTests.testVersionSelectorUsesTheDolbyVisionProfilenow expectsDV P8.1in the version picker labels.- CI: Player regression on
dad60dapassed, iOS and tvOS (run 38484418131). Results for the latest head are in the checks below. - Local: signed Release tvOS builds of #139's head plus this PR built and installed for device testing (see below). No local test run.
Performance
Not applicable. This changes label text only; no benchmark was run.
Testing status
- Tested? Yes, on Apple TV. Not on iPhone or iPad.
- Environment: Apple TV 4K (3rd generation), signed Release build of #139's head (
experiment/vivid-player-bridge) with this PR on top; GitHub Actions simulators (iOS and tvOS). - Revision: first device build
dad60daon #139ccc9c42; second device build this PR at1c2ec42on #139ead3ead. Later commits only change comments, docs and the iPhone and iPad Video range fact. - Checks and results: I checked the first build on Apple TV: the player badge showed
DV P7for a profile 7 file, which led to the detail page changes here. On the second build the player badges and the detail page labels worked as intended. CI unit tests passed ondad60da. - Limitations: I haven't checked every provider and format on a device (Emby and Jellyfin titles, HDR10+, HLG and SDR files are covered by the unit tests). The iPhone and iPad detail page changes are untested on a device.
Design impact and approval
[!IMPORTANT]
Only blurbery can approve design changes. Obtain prior, explicit approval and reference it here. Unapproved design changes must not be merged.
- Design impact: label text only, no layout, style, order or spacing change. The player's dynamic-range and audio badges name the real format and the playing codec. The detail pages, version pickers, Home focus info (Continue Watching) and the iPhone and iPad hero chip and Video range fact use the same dynamic-range label, and the Apple TV detail page shows it as one badge instead of
DVplusHDR10. Profile 7 is labelledDV P7. - Approval from blurbery: in chat on 14 October 2026: first the player badges (real HDR format, audio badge matching the playing track, badge text only), then, after device testing, the file's real format everywhere the file's video details exist, one badge on the Apple TV detail page, and profile 7 labelled as
DV P7.
Documentation impact
-
docs/playback/architecture.md: what the Info tab's Stream badges show, the brief file-codec fallback, that profile 7 shows as DV P7, where else the label appears, and what keeps the old marks. -
docs/apple-tv-browsing.md: the detail page's dynamic-range badge and Version pill show the file's format as one label. -
docs/cores/emby.mdanddocs/cores/jellyfin.md: which stream fields the label reads, and that the detail pages, version pickers and Home focus info show it. -
I checked the docs this change affects and updated them in this PR, or explained above why none needed changes.
AI disclosure
[!IMPORTANT]
Required for every PR. Incomplete disclosures are not ready for review or merge.
I implemented these changes and used Claude Opus as a tool.