owl-stream/app/streams/[id]/VideoPlayer.tsx

59 lines
1.6 KiB
TypeScript

'use client';
import React, { useEffect, useRef } from 'react';
import { Radio } from 'lucide-react';
interface Props {
hlsUrl?: string;
thumbnailUrl?: string;
}
export default function VideoPlayer({ hlsUrl, thumbnailUrl }: Props) {
const videoRef = useRef<HTMLVideoElement>(null);
useEffect(() => {
if (!hlsUrl || !videoRef.current) return;
const video = videoRef.current;
if (video.canPlayType('application/vnd.apple.mpegurl')) {
video.src = hlsUrl;
return;
}
import('hls.js').then(({ default: Hls }) => {
if (Hls.isSupported()) {
const hls = new Hls();
hls.loadSource(hlsUrl);
hls.attachMedia(video);
return () => hls.destroy();
}
});
}, [hlsUrl]);
if (!hlsUrl) {
return (
<div className="relative aspect-video bg-black/40 rounded-2xl border border-white/5 flex flex-col items-center justify-center gap-4 text-stone-500">
<Radio size={48} className="text-stone-600" />
<p className="text-sm font-medium">Stream offline no source available</p>
{thumbnailUrl && (
// eslint-disable-next-line @next/next/no-img-element
<img src={thumbnailUrl} alt="Stream thumbnail" className="absolute inset-0 w-full h-full object-cover rounded-2xl opacity-20" />
)}
</div>
);
}
return (
<div className="relative aspect-video rounded-2xl overflow-hidden bg-black shadow-2xl shadow-black/60">
<video
ref={videoRef}
controls
autoPlay
muted
playsInline
className="w-full h-full"
poster={thumbnailUrl}
/>
</div>
);
}