Convert preview player to use html5

This commit is contained in:
Nicolas Mowen 2024-02-24 07:26:15 -07:00
parent 7ccc7fb393
commit cba980602b

View File

@ -181,7 +181,10 @@ function PreviewContent({
setProgress, setProgress,
setReviewed, setReviewed,
}: PreviewContentProps) { }: PreviewContentProps) {
const playerRef = useRef<Player | null>(null); const playerRef = useRef<HTMLVideoElement | null>(null);
// keep track of playback state
const playerStartTime = useMemo(() => { const playerStartTime = useMemo(() => {
if (!relevantPreview) { if (!relevantPreview) {
return 0; return 0;
@ -190,73 +193,33 @@ function PreviewContent({
// start with a bit of padding // start with a bit of padding
return Math.max(0, review.start_time - relevantPreview.start - 8); return Math.max(0, review.start_time - relevantPreview.start - 8);
}, []); }, []);
const [lastPercent, setLastPercent] = useState(0.0);
// manual playback // initialize player correctly
// safari is incapable of playing at a speed > 2x
// so manual seeking is required on iOS
const [manualPlayback, setManualPlayback] = useState(false);
useEffect(() => { useEffect(() => {
if (!manualPlayback || !playerRef.current) { if (!playerRef.current) {
return;
}
let counter = 0;
const intervalId: NodeJS.Timeout = setInterval(() => {
if (playerRef.current) {
playerRef.current.currentTime(playerStartTime + counter);
counter += 1;
}
}, 125);
return () => clearInterval(intervalId);
}, [manualPlayback, playerRef]);
// preview
if (relevantPreview) {
return (
<VideoPlayer
options={{
preload: "auto",
autoplay: true,
controls: false,
muted: true,
fluid: true,
aspectRatio: "16:9",
loadingSpinner: false,
sources: relevantPreview
? [
{
src: `${relevantPreview.src}`,
type: "video/mp4",
},
]
: [],
}}
seekOptions={{}}
onReady={(player) => {
playerRef.current = player;
if (!relevantPreview) {
return; return;
} }
if (isSafari) { if (isSafari) {
player.pause(); playerRef.current.pause();
setManualPlayback(true); setManualPlayback(true);
} else { } else {
player.currentTime(playerStartTime); playerRef.current.currentTime = playerStartTime;
player.playbackRate(8); playerRef.current.playbackRate = 8;
} }
}, [playerRef]);
let lastPercent = 0; // time progress update
player.on("timeupdate", () => {
const onProgress = useCallback(() => {
if (!setProgress) { if (!setProgress) {
return; return;
} }
const playerProgress = const playerProgress =
(player.currentTime() || 0) - playerStartTime; (playerRef.current?.currentTime || 0) - playerStartTime;
// end with a bit of padding // end with a bit of padding
const playerDuration = review.end_time - review.start_time + 8; const playerDuration = review.end_time - review.start_time + 8;
@ -271,7 +234,7 @@ function PreviewContent({
setReviewed(); setReviewed();
} }
lastPercent = playerPercent; setLastPercent(playerPercent);
if (playerPercent > 100) { if (playerPercent > 100) {
playerRef.current?.pause(); playerRef.current?.pause();
@ -280,12 +243,43 @@ function PreviewContent({
} else { } else {
setProgress(playerPercent); setProgress(playerPercent);
} }
}); }, [setProgress, lastPercent]);
}}
onDispose={() => { // manual playback
playerRef.current = null; // safari is incapable of playing at a speed > 2x
}} // so manual seeking is required on iOS
/>
const [manualPlayback, setManualPlayback] = useState(false);
useEffect(() => {
if (!manualPlayback || !playerRef.current) {
return;
}
let counter = 0;
const intervalId: NodeJS.Timeout = setInterval(() => {
if (playerRef.current) {
playerRef.current.currentTime = playerStartTime + counter;
counter += 1;
}
}, 125);
return () => clearInterval(intervalId);
}, [manualPlayback, playerRef]);
// preview
if (relevantPreview) {
return (
<video
ref={playerRef}
className="w-full h-full aspect-video bg-black"
autoPlay
playsInline
preload="auto"
muted
onTimeUpdate={onProgress}
>
<source src={relevantPreview.src} type={relevantPreview.type} />
</video>
); );
} else if (isCurrentHour(review.start_time)) { } else if (isCurrentHour(review.start_time)) {
return ( return (