import { useState } from 'react'; import { motion } from 'framer-motion'; import { useGeneration } from '@/context/GenerationContext'; import { CheckIcon, DownloadIcon, PlayIcon, RefreshIcon, VideoIcon } from './Icons'; import { mergeVideos, ClipMetadata } from '@/utils/api'; export const GenerationComplete: React.FC = () => { const { state, reset } = useGeneration(); const { generatedVideos, provider } = state; const [playingIndex, setPlayingIndex] = useState(null); const [isMerging, setIsMerging] = useState(false); const [mergeError, setMergeError] = useState(null); const [mergedVideoUrl, setMergedVideoUrl] = useState(null); const [isPlayingMerged, setIsPlayingMerged] = useState(false); const accentColor = provider === 'kling' ? 'coral' : 'electric'; const handleDownload = async (video: typeof generatedVideos[0], index: number) => { try { const url = video.blobUrl || video.url; const response = await fetch(url); const blob = await response.blob(); const downloadUrl = URL.createObjectURL(blob); const a = document.createElement('a'); a.href = downloadUrl; a.download = `video-segment-${index + 1}.mp4`; document.body.appendChild(a); a.click(); document.body.removeChild(a); URL.revokeObjectURL(downloadUrl); } catch (error) { console.error('Download failed:', error); } }; const handleDownloadAll = async () => { for (let i = 0; i < generatedVideos.length; i++) { await handleDownload(generatedVideos[i], i); // Small delay between downloads await new Promise(r => setTimeout(r, 500)); } }; // Merge all videos into a single file const handleMergeAndExport = async () => { if (generatedVideos.length === 0) return; setIsMerging(true); setMergeError(null); try { // Collect all video blobs const videoBlobs: Blob[] = []; const clipMetadata: ClipMetadata[] = []; for (let i = 0; i < generatedVideos.length; i++) { const video = generatedVideos[i]; const url = video.blobUrl || video.url; // Fetch blob from URL const response = await fetch(url); const blob = await response.blob(); videoBlobs.push(blob); // Create clip metadata // Use Whisper-detected trim point if available, otherwise use full duration // No start trimming - keep full video from beginning const trimStart = 0; // Always start from beginning (no overlap removal) const trimEnd = video.trimPoint || video.duration; // Use Whisper trim point if available clipMetadata.push({ index: i, startTime: trimStart, endTime: trimEnd, type: 'video', duration: trimEnd - trimStart, }); } console.log('🎬 Merging videos...', clipMetadata); // Call merge API const mergedBlob = await mergeVideos(videoBlobs, clipMetadata); // Create URL for preview (don't auto-download) const previewUrl = URL.createObjectURL(mergedBlob); setMergedVideoUrl(previewUrl); console.log('✅ Merged video ready for preview!'); } catch (error) { console.error('Merge failed:', error); setMergeError(error instanceof Error ? error.message : 'Failed to merge videos'); } finally { setIsMerging(false); } }; // Download the merged video const handleDownloadMerged = () => { if (!mergedVideoUrl) return; const a = document.createElement('a'); a.href = mergedVideoUrl; a.download = `final-video-${Date.now()}.mp4`; document.body.appendChild(a); a.click(); document.body.removeChild(a); }; return (
{/* Success Header */}
Generation Complete! {generatedVideos.length} video{generatedVideos.length !== 1 ? 's' : ''} generated successfully
{/* Video Grid */} {generatedVideos.map((video, index) => (
{/* Video Preview */}
{/* Video Info */}

Segment {index + 1}

~{Math.round(video.duration)}s duration

))}
{/* Merged Video Preview */} {mergedVideoUrl && (

Final Exported Video

All segments merged into one video

{/* Video Player */}
{/* Download Button */}
)} {/* Merge Error */} {mergeError && (

{mergeError}

)} {/* Actions */} {/* Primary: Merge & Export */} {!mergedVideoUrl && ( )} {/* Re-merge option if already merged */} {mergedVideoUrl && ( )} {/* Secondary: Download All */} {/* Tertiary: Generate More */} {/* Tip */} {mergedVideoUrl ? 'Your final video is ready! Download it or re-merge with different settings.' : generatedVideos.length >= 2 ? '"Export Final Video" will merge all segments into a single video file with Whisper-optimized trim points.' : 'Videos are ready to use in your video editor or social media.' }
); };