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:
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user