fix hdr playback, lint warnings
This commit is contained in:
@@ -124,14 +124,15 @@ export default function EndOfVideoCard({
|
||||
}
|
||||
|
||||
function RateAndLogRow({ itemId, itemName }: { itemId?: string; itemName: string }) {
|
||||
if (!itemId || String(itemId).startsWith('tmdb-')) return null
|
||||
const [hoverRating, setHoverRating] = useState(0)
|
||||
const personal = usePersonalData(s => s.entries[itemId])
|
||||
const personal = usePersonalData(s => itemId ? s.entries[itemId] : undefined)
|
||||
const setRating = usePersonalData(s => s.setRating)
|
||||
const addDiary = useDiary(s => s.add)
|
||||
const current = personal?.rating || 0
|
||||
const [logged, setLogged] = useState(false)
|
||||
|
||||
if (!itemId || String(itemId).startsWith('tmdb-')) return null
|
||||
|
||||
return (
|
||||
<div className="flex items-center justify-center gap-3 mb-5">
|
||||
<div className="flex items-center gap-1">
|
||||
|
||||
@@ -13,6 +13,7 @@ import {
|
||||
videoRangeLabel,
|
||||
} from '../../lib/jellyfin-meta'
|
||||
import { formatBitrate } from '../../lib/format'
|
||||
import { isHdrDisplayActive } from '../../lib/device-profile'
|
||||
|
||||
interface Props {
|
||||
item?: BaseItemDto | null
|
||||
@@ -58,7 +59,7 @@ function readLiveStats(): LiveStats {
|
||||
}
|
||||
}
|
||||
|
||||
async function checkHwDecode(stream: { Codec?: string | null; Width?: number | null; Height?: number | null; BitRate?: number | null } | null): Promise<HwDecodeState> {
|
||||
async function checkHwDecode(stream: { Codec?: string | null; Width?: number | null; Height?: number | null; BitRate?: number | null; VideoRangeType?: string | null; VideoRange?: string | null } | null): Promise<HwDecodeState> {
|
||||
if (!stream || typeof navigator.mediaCapabilities?.decodingInfo !== 'function') {
|
||||
return { supported: null, hwAccelerated: null }
|
||||
}
|
||||
@@ -66,9 +67,15 @@ async function checkHwDecode(stream: { Codec?: string | null; Width?: number | n
|
||||
const w = stream.Width ?? 1920
|
||||
const h = stream.Height ?? 1080
|
||||
const br = stream.BitRate ?? 8000000
|
||||
// Map common Jellyfin codec names to MIME codec strings
|
||||
// Use the main10 profile codec string for HDR content so the
|
||||
// MediaCapabilities query matches what the actual stream requires.
|
||||
// The previous main (8-bit) string caused HDR sources to probe
|
||||
// against the wrong profile.
|
||||
const range = (stream.VideoRangeType || stream.VideoRange || '').toUpperCase()
|
||||
const isHdr = range === 'HDR' || range === 'HDR10' || range === 'HLG' || range.startsWith('DOVI')
|
||||
const mimeCodec =
|
||||
codec === 'h264' ? 'avc1.640033'
|
||||
: codec === 'hevc' && isHdr ? 'hev1.2.4.L153.B0'
|
||||
: codec === 'hevc' ? 'hev1.1.6.L150.90'
|
||||
: codec === 'av1' ? 'av01.0.05M.08'
|
||||
: codec === 'vp9' ? 'vp09.00.50.08'
|
||||
@@ -164,7 +171,7 @@ export default function StreamInfo({ item, visible, playMethod }: Props) {
|
||||
if (!visible) return
|
||||
const v = getVideoStream(item || {})
|
||||
checkHwDecode(v).then(setHw)
|
||||
}, [visible, item?.Id])
|
||||
}, [visible, item])
|
||||
|
||||
if (!visible || !item) return null
|
||||
const source = pickPrimarySource(item)
|
||||
@@ -192,6 +199,21 @@ export default function StreamInfo({ item, visible, playMethod }: Props) {
|
||||
|
||||
const res = resolutionLabel(item)
|
||||
const range = videoRangeLabel(item)
|
||||
|
||||
// HDR display status - tells the user whether their display is actually
|
||||
// in HDR mode. When the source is HDR but the display is SDR, the browser
|
||||
// tone-maps the content. If the profile was built with HDR display off,
|
||||
// the server did FFmpeg tone-mapping instead.
|
||||
const hdrDisplay = isHdrDisplayActive()
|
||||
if (range && range !== 'SDR') {
|
||||
rows.push({
|
||||
label: 'HDR display',
|
||||
value: hdrDisplay ? 'Active' : 'Off (tone-mapped)',
|
||||
accent: hdrDisplay,
|
||||
warn: !hdrDisplay,
|
||||
})
|
||||
}
|
||||
|
||||
if (res) rows.push({ label: 'Resolution', value: range ? `${res} · ${range}` : res })
|
||||
if (v) {
|
||||
rows.push({ label: 'Video', value: videoCodecLabel(v) })
|
||||
|
||||
@@ -54,7 +54,7 @@ function parseVTT(raw: string): Cue[] {
|
||||
// Accept both WebVTT dots and SRT commas for the milliseconds separator.
|
||||
// Jellyfin sometimes serves SRT content even on the .vtt endpoint.
|
||||
const m = lines[tsLine].match(
|
||||
/(\d+:)?(\d+):(\d+)[\.,](\d+)\s+-->\s+(\d+:)?(\d+):(\d+)[\.,](\d+)/,
|
||||
/(\d+:)?(\d+):(\d+)[.,](\d+)\s+-->\s+(\d+:)?(\d+):(\d+)[.,](\d+)/,
|
||||
)
|
||||
if (!m) continue
|
||||
const start = parseTimeStamp(m[1], m[2], m[3], m[4])
|
||||
|
||||
Reference in New Issue
Block a user