69 lines
2.0 KiB
TypeScript
69 lines
2.0 KiB
TypeScript
'use client';
|
|
|
|
import { useRef } from 'react';
|
|
import type { MediaPlayerInstance } from '@vidstack/react';
|
|
|
|
import { useProtectedVideoQuery } from '@/app/(modules)/results/hooks/useVideoResults';
|
|
import AnnotatedVideoPlayer from '@/components/video/annotatedVideoPlayer';
|
|
import { useVideoAnnotationPlayback } from '@/components/video/useVideoAnnotationPlayback';
|
|
import type { TicketOverviewDetail } from '@/types';
|
|
|
|
type TicketInlineAnalysisVideoProps = {
|
|
ticket: TicketOverviewDetail;
|
|
};
|
|
|
|
export function TicketInlineAnalysisVideo({
|
|
ticket,
|
|
}: TicketInlineAnalysisVideoProps) {
|
|
const videoRef = useRef<MediaPlayerInstance | null>(null);
|
|
const videoId = ticket.video_id ?? ticket.video?.id ?? undefined;
|
|
const sourceUrl = ticket.video?.url ?? undefined;
|
|
const fps = ticket.video_metadata?.fps ?? 0;
|
|
const videoWidth = ticket.video_metadata?.resolution.width ?? 0;
|
|
const videoHeight = ticket.video_metadata?.resolution.height ?? 0;
|
|
const {
|
|
visibleDetections,
|
|
handleSeeked,
|
|
handleTimeUpdate,
|
|
handleVideoFrame,
|
|
} = useVideoAnnotationPlayback({
|
|
videoId,
|
|
logs: [],
|
|
fps,
|
|
videoRef,
|
|
});
|
|
const {
|
|
videoUrl,
|
|
isLoading: isVideoLoading,
|
|
isError: isVideoError,
|
|
refetch: refetchVideo,
|
|
} = useProtectedVideoQuery(sourceUrl);
|
|
|
|
if (!videoId || !sourceUrl) {
|
|
return (
|
|
<div className="rounded-lg border border-dashed bg-muted/20 px-4 py-8 text-sm text-muted-foreground">
|
|
Analysis video is unavailable for this ticket.
|
|
</div>
|
|
);
|
|
}
|
|
|
|
return (
|
|
<div className="space-y-2">
|
|
<AnnotatedVideoPlayer
|
|
videoRef={videoRef}
|
|
logs={[]}
|
|
visibleDetections={visibleDetections}
|
|
videoWidth={videoWidth}
|
|
videoHeight={videoHeight}
|
|
videoUrl={videoUrl}
|
|
isLoading={isVideoLoading}
|
|
isError={isVideoError}
|
|
onRetry={() => void refetchVideo()}
|
|
onTimeUpdate={handleTimeUpdate}
|
|
onVideoFrame={handleVideoFrame}
|
|
onSeeked={handleSeeked}
|
|
/>
|
|
</div>
|
|
);
|
|
}
|