watchparty/client/src/global.d.ts
Nicolas fff0b7a984
All checks were successful
Publier l'image Docker / test (push) Successful in 24s
Publier l'image Docker / publish (push) Successful in 9s
Fix subtitle selection timing out: hls.js's default timeouts too tight
Reported: selecting a subtitle track (only subtitles, not audio/quality)
made the request "time out". Confirmed from the browser's own error:
hls.js gave up with a fatal fragLoadTimeOut after 4 retries, each hitting
its default 10s fragment-load timeout - not a hang, and not a repeat of
the earlier "override doesn't reach Emby" bug (see docs/architecture.md's
Player-track-selection section) - the same error's frag.baseurl already
shows SubtitleMethod=Encode correctly present in the request Emby
received, so the override chain works end to end. It's just slow: burning
a subtitle in forces a real re-encode (not a rendition, not a remux),
which measurably takes Emby longer than 10s to produce a first segment
for.

Fixed by giving both players' Hls instances explicit longer timeouts
(manifestLoadingTimeOut/levelLoadingTimeOut: 30s, fragLoadingTimeOut: 60s)
instead of hls.js's untouched defaults - applied to musicBar/MusicBar.ts
too, not just the video player, since music tracks go through the same
PlaybackInfo/transcode pipeline and could hit the same latency for a
quality change even without subtitles being involved there today.

global.d.ts's HlsStatic constructor gained an optional HlsConfig
parameter (only the four properties actually used) so this doesn't need
an `as any`/unsafe cast to pass config through.

Verified the property names are real and actually honored by hls.js
1.5.17 (the exact pinned CDN build), not silently ignored: constructed a
real Hls instance with this config and read back hls.config.* - all four
values came back as set, not as hls.js's own (tighter) defaults.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-14 13:11:06 +02:00

69 lines
2.2 KiB
TypeScript

/**
* Ambient declarations for things esbuild/the browser provide that aren't
* npm packages - see client/build.mjs's `.html`-as-text loader, and
* client/index.html's CDN <script> tags for hls.js/socket.io (both used
* as plain globals, not imported - keeping the "pin an exact CDN version,
* no bundler-managed copy" choice this app made from the start).
*/
/** Each component's own .html template, imported as a raw string - see
* any view's own .ts file for the pattern (`import html from './Foo.html'`). */
declare module '*.html' {
const content: string;
export default content;
}
/** Imported purely for esbuild's CSS bundling side effect (see any view's
* own `import './Foo.css'`) - there's nothing to type, the import itself
* is the whole point. */
declare module '*.css';
// --- socket.io-client (CDN global, see client/index.html) -------------------
// Minimal shape covering only what this app actually calls - not the full
// socket.io-client API surface.
interface AppClientSocket {
on(event: string, handler: (...args: unknown[]) => void): void;
emit(event: string, payload?: unknown): void;
disconnect(): void;
}
declare function io(): AppClientSocket;
// --- hls.js (CDN global, see client/index.html) -----------------------------
// Same idea - only the surface client/src/views/player and musicBar
// actually use.
interface HlsErrorData {
fatal: boolean;
[key: string]: unknown;
}
interface HlsInstance {
on(event: string, handler: (event: string, data: HlsErrorData) => void): void;
loadSource(url: string): void;
attachMedia(media: HTMLMediaElement): void;
destroy(): void;
}
/** Only the loading-timeout knobs Player.ts/musicBar actually override -
* see their own HLS_CONFIG comment for why the defaults are too tight
* for this app's real transcode latency. */
interface HlsConfig {
manifestLoadingTimeOut?: number;
manifestLoadingMaxRetry?: number;
levelLoadingTimeOut?: number;
fragLoadingTimeOut?: number;
}
interface HlsStatic {
new (config?: HlsConfig): HlsInstance;
isSupported(): boolean;
Events: { MANIFEST_PARSED: string; ERROR: string };
}
declare const Hls: HlsStatic | undefined;
interface Window {
Hls?: HlsStatic;
}