87 lines
2.4 KiB
TypeScript
87 lines
2.4 KiB
TypeScript
/**
|
|
* VideoPlayer — zéro dépendance runtime
|
|
*
|
|
* youtube → <iframe> embed natif (0KB ajouté au bundle)
|
|
* s3/local → <video> natif + HLS.js chargé lazily si .m3u8
|
|
* external → <video> natif
|
|
*/
|
|
|
|
import { useEffect, useRef } from 'react';
|
|
|
|
type StorageType = 'youtube' | 's3' | 'local' | 'external';
|
|
|
|
interface VideoPlayerProps {
|
|
storageType: StorageType;
|
|
storageKey: string;
|
|
}
|
|
|
|
export default function VideoPlayer({ storageType, storageKey }: VideoPlayerProps) {
|
|
if (storageType === 'youtube') {
|
|
return <YouTubePlayer videoId={storageKey} />;
|
|
}
|
|
|
|
const apiBase = import.meta.env.VITE_API_URL || '/api';
|
|
const url =
|
|
storageType === 'external'
|
|
? storageKey
|
|
: `${apiBase}/stream/${storageKey}`;
|
|
|
|
return <NativePlayer url={url} />;
|
|
}
|
|
|
|
// ── YouTube ───────────────────────────────────────────────────────────────────
|
|
|
|
function YouTubePlayer({ videoId }: { videoId: string }) {
|
|
return (
|
|
<iframe
|
|
src={`https://www.youtube.com/embed/${videoId}?rel=0&color=white`}
|
|
className="h-full w-full"
|
|
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
|
|
allowFullScreen
|
|
title="Lecteur vidéo"
|
|
/>
|
|
);
|
|
}
|
|
|
|
// ── Native + HLS.js lazy ──────────────────────────────────────────────────────
|
|
|
|
function NativePlayer({ url }: { url: string }) {
|
|
const videoRef = useRef<HTMLVideoElement>(null);
|
|
|
|
useEffect(() => {
|
|
const video = videoRef.current;
|
|
if (!video) return;
|
|
|
|
if (!url.includes('.m3u8')) {
|
|
video.src = url;
|
|
return;
|
|
}
|
|
|
|
// HLS — import dynamique, ne charge que si nécessaire
|
|
let hls: import('hls.js').default | null = null;
|
|
|
|
if (video.canPlayType('application/vnd.apple.mpegurl')) {
|
|
// Safari supporte HLS nativement
|
|
video.src = url;
|
|
} else {
|
|
import('hls.js').then(({ default: Hls }) => {
|
|
if (!Hls.isSupported() || !video) return;
|
|
hls = new Hls();
|
|
hls.loadSource(url);
|
|
hls.attachMedia(video);
|
|
});
|
|
}
|
|
|
|
return () => { hls?.destroy(); };
|
|
}, [url]);
|
|
|
|
return (
|
|
<video
|
|
ref={videoRef}
|
|
className="h-full w-full"
|
|
controls
|
|
playsInline
|
|
/>
|
|
);
|
|
}
|