From 2f670ec9a486518bc5d280ef22be5c342cb2b277 Mon Sep 17 00:00:00 2001 From: Nicolas Date: Mon, 14 Sep 2026 14:45:38 +0200 Subject: [PATCH] Flag image-based subtitle tracks (PGS/VobSub/DVB) as not burn-in-able Two different items both failed the same way when picking a subtitle - without knowing whether the second one was also a PGS (image/bitmap) track like the first confirmed one, that result was ambiguous: still the same known issue, or something new? Rather than keep digging through server logs per item, this app can just know the answer itself - Emby's PlaybackInfo response already includes each subtitle stream's Codec. - server/src/services/CatalogService.ts: getPlaybackOptions reads it and reports supportsBurnIn: false for image-based subtitle codecs (hdmv_pgs_subtitle/dvd_subtitle/dvb_subtitle - IMAGE_SUBTITLE_CODECS). This app forces SubtitleMethod=Encode whenever a subtitle is picked (applyPlaybackOverrides), asking ffmpeg's `subtitles` filter (libass) to burn it in - libass renders text via a font, it has no path for compositing a pre-rendered bitmap at all, confirmed against a real server (see docs/architecture.md's Round 4/5). - server/src/types.ts, client/src/types.ts: PlaybackTrackOption gains supportsBurnIn (subtitle tracks only, undefined for audio). - client/src/views/player/Player.ts: the subtitle population. + supportsBurnIn?: boolean; } export interface PlaybackOptionsDto { diff --git a/client/src/views/player/Player.ts b/client/src/views/player/Player.ts index c12ed82..d5500ea 100644 --- a/client/src/views/player/Player.ts +++ b/client/src/views/player/Player.ts @@ -230,8 +230,17 @@ function renderVideoPlayer(root: HTMLElement, partyId: string, party: PartyPubli audioSelect.innerHTML = options.audioTracks.length ? options.audioTracks.map((t) => ``).join('') : ''; + // supportsBurnIn: false means this is an image/bitmap subtitle (PGS/ + // VobSub/DVB, typically a Blu-ray/DVD rip) - this player forces a + // real burn-in (SubtitleMethod=Encode, see CatalogService) whenever + // a subtitle is picked, which only ever works for text subtitles. + // Disabled rather than hidden, so it's clear the track exists and + // *why* it can't be picked, instead of silently missing from the + // list - confirmed against a real server that picking one of these + // doesn't just fail to show, it breaks playback outright (see + // docs/architecture.md's player-track-selection section). subtitleSelect.innerHTML = '' + - options.subtitleTracks.map((t) => ``).join(''); + options.subtitleTracks.map((t) => ``).join(''); } catch (err) { console.error('[watchparty player] playback-options failed', err); // Non-fatal: playback can still work with Emby's own defaults, just without a picker. diff --git a/docs/architecture.md b/docs/architecture.md index 698001b..96d91d5 100644 --- a/docs/architecture.md +++ b/docs/architecture.md @@ -533,6 +533,39 @@ this bug (a subtitle picked, never shown) instead of fixing anything. Nothing to change in this app for this one; it needs fonts/fontconfig fixed wherever Emby's own container/host runs. +**Round 5: fontconfig fixed, and a *different* item still failed the same +way - added a real check instead of guessing further.** After Round 4's +fix, the font loaded fine (`Loading font file '/config/fonts/ +GoNotoKurrent.ttf'`, no more "Failed to load fontconfig fonts") - but a +retest on the same item still failed, this time with `Could not find +codec parameters for stream N (Subtitle: hdmv_pgs_subtitle (pgssub))`. +`hdmv_pgs_subtitle` (PGS) is a Blu-ray **image/bitmap** subtitle format - +a pre-rendered picture per frame, not text. This app's forced +`SubtitleMethod=Encode` asks ffmpeg's `subtitles` filter to burn it in, +and that filter is `libass` - it renders *text* via a font (exactly what +Round 4 just fixed the ability to do), and has no code path for +compositing a bitmap at all. Picking a PGS track was never going to work +here, fontconfig or not. A second item, tested specifically to rule PGS +in or out as the whole explanation, hit the exact same wall - without +knowing that item's own subtitle codec, that result was genuinely +ambiguous (still PGS on a second file? or something else entirely?), +which is exactly the kind of guess this saga had already spent four +rounds on. + +Rather than keep asking for one more log line per item, `getPlaybackOptions` +(`CatalogService.ts`) now reads each subtitle stream's own `Codec` from +the same `PlaybackInfo` response it already fetches, and reports +`supportsBurnIn: false` for the three image-based subtitle codecs +(`hdmv_pgs_subtitle`, `dvd_subtitle`, `dvb_subtitle` - `IMAGE_SUBTITLE_CODECS`). +The player's subtitle `