* fix(overlays): derive dynamic-range badges from Dolby Vision metadata
Dolby Vision files were labeled with a generic "HDR" badge everywhere
outside the Media Info dialog, because badge sites only consulted the
bare FileVersion.hdr boolean even though the payload carries
video_tracks[].dolby_vision / dv_profile / video_range_type /
color_transfer.
Web: add a shared helper (web/src/lib/videoRange.ts) that derives a
display label ("DV", "DV HDR10", "DV HLG", "HDR10+", "HDR10", "HLG")
from the probed video tracks, mirroring the server-side normalizeHDR
vocabulary, with the hdr boolean kept as the last-resort fallback for
stale pre-DV probe rows. Use it in QualityBadges, VersionDropdown,
VersionFlyout, and the player HUD (playback-info) in place of the
hardcoded "HDR" literal. Badge styling is unchanged.
Server: in internal/overlays/summary.go, break bestFile resolution
ties by richness of dynamic-range metadata (DV > explicit HDR10/HLG
via color_transfer > bare hdr boolean > SDR) so a first-scanned
generic-HDR file no longer masks a Dolby Vision sibling on card
overlays. Full ties still keep the earliest file, so the selection
stays deterministic.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* fix(overlays): detect Dolby Vision via dv_profile and DOVI range type
Probed rows set DolbyVision and DVProfile together, but catalog-seeded
or imported tracks can carry only dv_profile or a DOVI* video_range_type
with an empty dolby_vision string. Share one hasDolbyVision predicate
between rangeRank and normalizeHDR so those rows rank and label as DV,
matching the web videoRange helper.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* fix(overlays): read video_range_type and hdr10_plus in hdrTypeFromTracks
Review follow-up: hdrTypeFromTracks only inspected color_transfer, so
server card overlays could never label HDR10+ and a track whose only
signal is video_range_type (e.g. catalog-seeded rows without probed
color metadata) fell through to the bare-boolean tier of rangeRank —
inconsistent with hasDolbyVision, which already reads the range type.
The server now shares the web helper's detection order exactly, making
the web/server vocabulary mirror claim true.
Also drops the unused video_range field from the web VideoRangeTrack
interface.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: rxwatcher <rxwatcher@users.noreply.github.com>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Co-authored-by: Quick104 <31828688+Quick104@users.noreply.github.com>
104 lines
3.4 KiB
TypeScript
104 lines
3.4 KiB
TypeScript
import { describe, expect, it } from "vitest";
|
|
|
|
import { bestVideoRangeLabel, videoRangeLabel, type VideoRangeSource } from "./videoRange";
|
|
|
|
describe("videoRangeLabel", () => {
|
|
it("returns empty for SDR / unprobed", () => {
|
|
expect(videoRangeLabel({ hdr: false })).toBe("");
|
|
expect(videoRangeLabel({ hdr: false, video_tracks: [{}] })).toBe("");
|
|
});
|
|
|
|
it("falls back to generic HDR from the bare boolean", () => {
|
|
expect(videoRangeLabel({ hdr: true })).toBe("HDR");
|
|
expect(videoRangeLabel({ hdr: true, video_tracks: [{}] })).toBe("HDR");
|
|
});
|
|
|
|
it("detects Dolby Vision from the dolby_vision string", () => {
|
|
expect(videoRangeLabel({ hdr: true, video_tracks: [{ dolby_vision: "Profile 5" }] })).toBe(
|
|
"DV",
|
|
);
|
|
});
|
|
|
|
it("detects Dolby Vision from dv_profile alone", () => {
|
|
expect(videoRangeLabel({ hdr: true, video_tracks: [{ dv_profile: 8 }] })).toBe("DV");
|
|
});
|
|
|
|
it("detects Dolby Vision from a DOVI video_range_type", () => {
|
|
expect(
|
|
videoRangeLabel({ hdr: true, video_tracks: [{ video_range_type: "DOVIWithSDR" }] }),
|
|
).toBe("DV");
|
|
});
|
|
|
|
it("combines DV with HDR10 base-layer compatibility", () => {
|
|
expect(
|
|
videoRangeLabel({
|
|
hdr: true,
|
|
video_tracks: [{ dolby_vision: "Profile 8", video_range_type: "DOVIWithHDR10" }],
|
|
}),
|
|
).toBe("DV HDR10");
|
|
expect(
|
|
videoRangeLabel({
|
|
hdr: true,
|
|
video_tracks: [{ dolby_vision: "Profile 7", color_transfer: "smpte2084" }],
|
|
}),
|
|
).toBe("DV HDR10");
|
|
});
|
|
|
|
it("combines DV with HLG compatibility", () => {
|
|
expect(
|
|
videoRangeLabel({ hdr: true, video_tracks: [{ video_range_type: "DOVIWithHLG" }] }),
|
|
).toBe("DV HLG");
|
|
});
|
|
|
|
it("labels HDR10+ from the flag or range type", () => {
|
|
expect(videoRangeLabel({ hdr: true, video_tracks: [{ hdr10_plus: true }] })).toBe("HDR10+");
|
|
expect(videoRangeLabel({ hdr: true, video_tracks: [{ video_range_type: "HDR10Plus" }] })).toBe(
|
|
"HDR10+",
|
|
);
|
|
expect(
|
|
videoRangeLabel({
|
|
hdr: true,
|
|
video_tracks: [{ video_range_type: "DOVIWithELHDR10Plus" }],
|
|
}),
|
|
).toBe("DV HDR10+");
|
|
});
|
|
|
|
it("labels HDR10 and HLG from video_range_type or color_transfer", () => {
|
|
expect(videoRangeLabel({ hdr: true, video_tracks: [{ video_range_type: "HDR10" }] })).toBe(
|
|
"HDR10",
|
|
);
|
|
expect(videoRangeLabel({ hdr: true, video_tracks: [{ color_transfer: "smpte2084" }] })).toBe(
|
|
"HDR10",
|
|
);
|
|
expect(videoRangeLabel({ hdr: true, video_tracks: [{ video_range_type: "HLG" }] })).toBe("HLG");
|
|
expect(videoRangeLabel({ hdr: true, video_tracks: [{ color_transfer: "arib-std-b67" }] })).toBe(
|
|
"HLG",
|
|
);
|
|
});
|
|
});
|
|
|
|
describe("bestVideoRangeLabel", () => {
|
|
it("prefers DV over a generic-HDR sibling version", () => {
|
|
const versions: VideoRangeSource[] = [
|
|
{ hdr: true },
|
|
{
|
|
hdr: true,
|
|
video_tracks: [{ dolby_vision: "Profile 8", video_range_type: "DOVIWithHDR10" }],
|
|
},
|
|
];
|
|
expect(bestVideoRangeLabel(versions)).toBe("DV HDR10");
|
|
});
|
|
|
|
it("prefers explicit HDR10 over the bare boolean", () => {
|
|
const versions: VideoRangeSource[] = [
|
|
{ hdr: true },
|
|
{ hdr: true, video_tracks: [{ color_transfer: "smpte2084" }] },
|
|
];
|
|
expect(bestVideoRangeLabel(versions)).toBe("HDR10");
|
|
});
|
|
|
|
it("returns empty when every version is SDR", () => {
|
|
expect(bestVideoRangeLabel([{ hdr: false }, { hdr: false }])).toBe("");
|
|
});
|
|
});
|