/** * Компонент отображения информации о синхронизации */ import { AlertCircle, CheckCircle2, Clock, Music } from "lucide-react" import { useMemo } from "react" import { Badge } from "@/components/ui/badge" import type { MediaFile } from "@/features/media/types/media" import { cn } from "@/lib/utils" import { useMulticam } from "../hooks/use-multicam" import { supportsTimecodeSync } from "../services/timecode-sync" interface SyncInfoProps { baseClipId: string mediaFiles: MediaFile[] className?: string showDetails?: boolean } export function SyncInfo({ baseClipId, mediaFiles, className, showDetails = true }: SyncInfoProps) { const multicam = useMulticam(baseClipId) // Анализируем возможности синхронизации для каждого угла const syncCapabilities = useMemo(() => { return multicam.angles.map((angle) => { const mediaFile = mediaFiles.find((m) => m.id === angle.clip.mediaId) if (!mediaFile) return { angle, hasTimecode: false, hasAudio: false } const hasTimecode = supportsTimecodeSync(mediaFile) const hasAudio = mediaFile.probeData?.streams.some((s) => s.codec_type === "audio") || false return { angle, hasTimecode, hasAudio } }) }, [multicam.angles, mediaFiles]) // Проверяем общие возможности синхронизации const canSyncByTimecode = syncCapabilities.filter((c) => c.hasTimecode).length >= 2 const canSyncByAudio = syncCapabilities.filter((c) => c.hasAudio).length >= 2 const hasSyncOffsets = multicam.syncOffsets.some((offset) => Math.abs(offset) > 0.01) if (!multicam.hasMulticamSupport) { return null } return (
{/* Статус синхронизации */}
{hasSyncOffsets ? ( <> Синхронизировано ) : ( <> Не синхронизировано )}
{/* Возможности синхронизации */}
Таймкод {canSyncByTimecode ? "✓" : "✗"} Аудио {canSyncByAudio ? "✓" : "✗"}
{/* Детальная информация */} {showDetails && hasSyncOffsets && (
Смещения:
{multicam.angles.map((angle, index) => { const offset = multicam.syncOffsets[index] || 0 if (Math.abs(offset) < 0.01) return null return (
{angle.name}: {offset > 0 ? "+" : ""} {offset.toFixed(3)}s
) })}
)}
) }