Convert preview player to use html5 video (#10016)

* Convert preview player to use html5

* Cleanup

* Increase padding and use constant

* Firefox doesn't support high fps either

* Cleanup

* no need to special case firefox
This commit is contained in:
Nicolas Mowen 2024-02-25 11:37:53 -07:00 committed by GitHub
parent 7ccc7fb393
commit 4a7c159a44
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -1,7 +1,5 @@
import VideoPlayer from "./VideoPlayer";
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
import { useApiHost } from "@/api";
import Player from "video.js/dist/types/player";
import { formatUnixTimestampToDateTime, isCurrentHour } from "@/utils/dateUtil";
import { ReviewSegment } from "@/types/review";
import { Slider } from "../ui/slider";
@ -169,6 +167,7 @@ export default function PreviewThumbnailPlayer({
);
}
const PREVIEW_PADDING = 16;
type PreviewContentProps = {
review: ReviewSegment;
relevantPreview: Preview | undefined;
@ -181,15 +180,69 @@ function PreviewContent({
setProgress,
setReviewed,
}: PreviewContentProps) {
const playerRef = useRef<Player | null>(null);
const playerRef = useRef<HTMLVideoElement | null>(null);
// keep track of playback state
const playerStartTime = useMemo(() => {
if (!relevantPreview) {
return 0;
}
// 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 - PREVIEW_PADDING);
}, []);
const [lastPercent, setLastPercent] = useState(0.0);
// initialize player correctly
useEffect(() => {
if (!playerRef.current) {
return;
}
if (isSafari) {
playerRef.current.pause();
setManualPlayback(true);
} else {
playerRef.current.currentTime = playerStartTime;
playerRef.current.playbackRate = 8;
}
}, [playerRef]);
// time progress update
const onProgress = useCallback(() => {
if (!setProgress) {
return;
}
const playerProgress =
(playerRef.current?.currentTime || 0) - playerStartTime;
// end with a bit of padding
const playerDuration = review.end_time - review.start_time + PREVIEW_PADDING;
const playerPercent = (playerProgress / playerDuration) * 100;
if (
setReviewed &&
!review.has_been_reviewed &&
lastPercent < 50 &&
playerPercent > 50
) {
setReviewed();
}
setLastPercent(playerPercent);
if (playerPercent > 100) {
playerRef.current?.pause();
setManualPlayback(false);
setProgress(100.0);
} else {
setProgress(playerPercent);
}
}, [setProgress, lastPercent]);
// manual playback
// safari is incapable of playing at a speed > 2x
@ -204,7 +257,7 @@ function PreviewContent({
let counter = 0;
const intervalId: NodeJS.Timeout = setInterval(() => {
if (playerRef.current) {
playerRef.current.currentTime(playerStartTime + counter);
playerRef.current.currentTime = playerStartTime + counter;
counter += 1;
}
}, 125);
@ -215,77 +268,17 @@ function PreviewContent({
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;
}
if (isSafari) {
player.pause();
setManualPlayback(true);
} else {
player.currentTime(playerStartTime);
player.playbackRate(8);
}
let lastPercent = 0;
player.on("timeupdate", () => {
if (!setProgress) {
return;
}
const playerProgress =
(player.currentTime() || 0) - playerStartTime;
// end with a bit of padding
const playerDuration = review.end_time - review.start_time + 8;
const playerPercent = (playerProgress / playerDuration) * 100;
if (
setReviewed &&
!review.has_been_reviewed &&
lastPercent < 50 &&
playerPercent > 50
) {
setReviewed();
}
lastPercent = playerPercent;
if (playerPercent > 100) {
playerRef.current?.pause();
setManualPlayback(false);
setProgress(100.0);
} else {
setProgress(playerPercent);
}
});
}}
onDispose={() => {
playerRef.current = null;
}}
/>
<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)) {
return (
@ -373,10 +366,6 @@ function PreviewContextItems({
setReviewed,
}: PreviewContextItemsProps) {
const exportReview = useCallback(() => {
console.log(
"trying to export to " +
`export/${review.camera}/start/${review.start_time}/end/${review.end_time}`
);
axios.post(
`export/${review.camera}/start/${review.start_time}/end/${review.end_time}`,
{ playback: "realtime" }