fix: use HLS.js for fullscreen camera stream

Fullscreen HLS video now initializes HLS.js via bind:this + $effect
instead of raw <video src>, which only works in Safari. Non-Safari
browsers now correctly play HLS streams in fullscreen mode.
This commit is contained in:
2026-03-25 14:35:07 +03:00
parent 215c8fdd46
commit 819283fa62
@@ -14,6 +14,7 @@
let error = $state(false); let error = $state(false);
let fullscreen = $state(false); let fullscreen = $state(false);
let videoEl: HTMLVideoElement | null = $state(null); let videoEl: HTMLVideoElement | null = $state(null);
let fullscreenVideoEl: HTMLVideoElement | null = $state(null);
const streamType = $derived(config.type ?? 'image'); const streamType = $derived(config.type ?? 'image');
const refreshMs = $derived((config.refreshInterval ?? 10) * 1000); const refreshMs = $derived((config.refreshInterval ?? 10) * 1000);
@@ -106,6 +107,34 @@
}; };
}); });
// HLS.js for fullscreen video element
$effect(() => {
if (streamType !== 'hls' || !fullscreenVideoEl) return;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
let hls: any = null;
(async () => {
try {
const { default: Hls } = await import('hls.js');
if (Hls.isSupported()) {
hls = new Hls();
hls.loadSource(config.streamUrl);
hls.attachMedia(fullscreenVideoEl!);
} else if (fullscreenVideoEl!.canPlayType('application/vnd.apple.mpegurl')) {
fullscreenVideoEl!.src = config.streamUrl;
}
} catch {
if (fullscreenVideoEl!.canPlayType('application/vnd.apple.mpegurl')) {
fullscreenVideoEl!.src = config.streamUrl;
}
}
})();
return () => {
if (hls) hls.destroy();
};
});
function handleImgError() { function handleImgError() {
error = true; error = true;
loading = false; loading = false;
@@ -206,13 +235,15 @@
<!-- svelte-ignore a11y_click_events_have_key_events --> <!-- svelte-ignore a11y_click_events_have_key_events -->
<div class="max-h-[90vh] max-w-[90vw]" onclick={(e) => e.stopPropagation()}> <div class="max-h-[90vh] max-w-[90vw]" onclick={(e) => e.stopPropagation()}>
{#if streamType === 'hls'} {#if streamType === 'hls'}
<!-- eslint-disable-next-line svelte/no-unused-svelte-ignore -->
<!-- svelte-ignore a11y_media_has_caption -->
<video <video
src={config.streamUrl}
autoplay autoplay
muted muted
playsinline playsinline
controls controls
class="max-h-[90vh] max-w-[90vw] object-contain" class="max-h-[90vh] max-w-[90vw] object-contain"
bind:this={fullscreenVideoEl}
></video> ></video>
{:else} {:else}
<img <img