Files
originsdigital/frontend/src/components/VideoPlayer.tsx

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
/>
);
}