| <!DOCTYPE html> |
| <html lang="en"> |
| <head> |
| <meta charset="UTF-8"> |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> |
| <title>Florence Video AI</title> |
| <script src="https://cdn.tailwindcss.com"></script> |
| <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css"> |
| <style> |
| @import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap'); |
| |
| body { |
| font-family: 'Inter', sans-serif; |
| background-color: #1a1a1a; |
| color: #ffffff; |
| } |
| |
| .video-container { |
| aspect-ratio: 16/9; |
| position: relative; |
| overflow: hidden; |
| border-radius: 12px; |
| } |
| |
| .video-wrapper { |
| position: relative; |
| background-color: #000000; |
| } |
| |
| .progress-bar { |
| height: 2px; |
| background-color: rgba(255, 255, 255, 0.2); |
| } |
| |
| .progress { |
| height: 100%; |
| background: linear-gradient(90deg, #2563eb, #3b82f6); |
| } |
| |
| .hover-card { |
| transition: all 0.3s ease; |
| border: 1px solid rgba(255, 255, 255, 0.1); |
| } |
| |
| .hover-card:hover { |
| transform: translateY(-4px); |
| box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.3); |
| border-color: rgba(59, 130, 246, 0.5); |
| } |
| |
| .ai-tag { |
| position: absolute; |
| top: 12px; |
| right: 12px; |
| background: linear-gradient(90deg, #2563eb, #3b82f6); |
| } |
| |
| .processing-pulse { |
| animation: pulse 2s infinite; |
| } |
| |
| @keyframes pulse { |
| 0% { |
| opacity: 0.6; |
| } |
| 50% { |
| opacity: 1; |
| } |
| 100% { |
| opacity: 0.6; |
| } |
| } |
| |
| .context-menu { |
| opacity: 0; |
| transform: scale(0.95); |
| transform-origin: top left; |
| transition: all 0.2s ease; |
| pointer-events: none; |
| } |
| |
| .context-menu.active { |
| opacity: 1; |
| transform: scale(1); |
| pointer-events: all; |
| } |
| |
| .loading-dots { |
| display: flex; |
| justify-content: center; |
| align-items: center; |
| } |
| |
| .loading-dots span { |
| width: 8px; |
| height: 8px; |
| margin: 0 2px; |
| background-color: #3b82f6; |
| border-radius: 50%; |
| display: inline-block; |
| animation: bounce 1.4s infinite ease-in-out both; |
| } |
| |
| .loading-dots span:nth-child(1) { |
| animation-delay: -0.32s; |
| } |
| |
| .loading-dots span:nth-child(2) { |
| animation-delay: -0.16s; |
| } |
| |
| @keyframes bounce { |
| 0%, 80%, 100% { |
| transform: translateY(0); |
| } |
| 40% { |
| transform: translateY(-8px); |
| } |
| } |
| |
| .video-thumbnail { |
| transition: all 0.3s ease; |
| cursor: pointer; |
| } |
| |
| .video-thumbnail:hover .play-icon { |
| transform: scale(1.1); |
| opacity: 1; |
| } |
| |
| .play-icon { |
| transition: all 0.3s ease; |
| opacity: 0.6; |
| } |
| </style> |
| </head> |
| <body class="min-h-screen bg-gray-900"> |
| <div class="container mx-auto px-4 py-8"> |
| |
| <header class="flex justify-between items-center mb-8"> |
| <div class="flex items-center"> |
| <div class="w-10 h-10 rounded-md bg-gradient-to-br from-blue-500 to-blue-600 flex items-center justify-center mr-3"> |
| <i class="fas fa-eye text-white text-lg"></i> |
| </div> |
| <h1 class="text-2xl font-bold text-white">Florence Video</h1> |
| </div> |
| <div class="flex space-x-3"> |
| <button class="px-4 py-2 bg-gray-800 hover:bg-gray-700 text-gray-300 rounded-lg text-sm font-medium flex items-center"> |
| <i class="fas fa-history mr-2"></i> History |
| </button> |
| <button id="accountBtn" class="px-4 py-2 bg-gray-800 hover:bg-gray-700 text-gray-300 rounded-lg text-sm font-medium flex items-center relative"> |
| <i class="fas fa-user mr-2"></i> Account |
| <div id="accountDropdown" class="hidden absolute top-full right-0 mt-1 w-48 bg-gray-800 rounded-lg shadow-lg z-50 py-1 border border-gray-700"> |
| <a href="#" class="block px-4 py-2 text-sm text-gray-300 hover:bg-gray-700">Profile</a> |
| <a href="#" class="block px-4 py-2 text-sm text-gray-300 hover:bg-gray-700">Settings</a> |
| <a href="#" class="block px-4 py-2 text-sm text-gray-300 hover:bg-gray-700 border-t border-gray-700 mt-1">Sign Out</a> |
| </div> |
| </button> |
| </div> |
| </header> |
|
|
| |
| <div class="grid grid-cols-1 lg:grid-cols-3 gap-6 mb-8"> |
| <div class="lg:col-span-2"> |
| <div class="bg-gray-800 rounded-xl p-4"> |
| <h2 class="text-lg font-semibold text-white mb-4">Video Processing</h2> |
| |
| |
| <div id="uploadContainer" class="mb-4 p-8 border-2 border-dashed border-gray-600 rounded-lg text-center cursor-pointer hover:border-blue-500 transition-colors"> |
| <input type="file" id="videoUpload" accept=".mp4,.mov,.avi,.mkv,.mp3,.wav" class="hidden"> |
| <i class="fas fa-cloud-upload-alt text-4xl text-gray-400 mb-3"></i> |
| <p class="text-gray-300 mb-2">Drag & drop your video file here</p> |
| <p class="text-sm text-gray-500">or click to browse files (MP4, MOV, AVI, MP3)</p> |
| </div> |
| |
| |
| <div id="videoPlayerContainer" class="hidden"> |
| |
| <div class="video-wrapper video-container rounded-lg mb-4"> |
| <video id="videoPlayer" class="w-full h-full object-contain" controls> |
| Your browser does not support the video tag. |
| </video> |
| <div class="absolute bottom-0 left-0 w-full"> |
| <div class="progress-bar"> |
| <div id="progressIndicator" class="progress" style="width: 0%"></div> |
| </div> |
| </div> |
| </div> |
|
|
| |
| <div class="flex items-center justify-between"> |
| <div class="flex space-x-3"> |
| <button id="playPauseBtn" class="w-10 h-10 bg-blue-600 hover:bg-blue-700 rounded-full flex items-center justify-center text-white"> |
| <i class="fas fa-play"></i> |
| </button> |
| <button class="w-10 h-10 bg-gray-700 hover:bg-gray-600 rounded-full flex items-center justify-center text-white"> |
| <i class="fas fa-volume-up"></i> |
| </button> |
| <button class="w-10 h-10 bg-gray-700 hover:bg-gray-600 rounded-full flex items-center justify-center text-white"> |
| <i class="fas fa-cog"></i> |
| </button> |
| </div> |
| <div class="flex items-center text-sm text-gray-400"> |
| <span id="currentTime">00:00</span> |
| <span class="mx-2">/</span> |
| <span id="duration">00:00</span> |
| </div> |
| <div class="flex space-x-2"> |
| <button class="px-3 py-1.5 bg-gray-700 hover:bg-gray-600 rounded-lg text-xs font-medium text-white flex items-center"> |
| <i class="fas fa-expand mr-2"></i> Fullscreen |
| </button> |
| <button id="processBtn" class="px-3 py-1.5 bg-blue-600 hover:blue-gray-700 rounded-lg text-xs font-medium text-white flex items-center"> |
| <i class="fas fa-bolt mr-2"></i> Process Video |
| </button> |
| </div> |
| </div> |
| </div> |
| </div> |
| </div> |
|
|
| |
| <div class="bg-gray-800 rounded-xl p-4 h-fit"> |
| <h2 class="text-lg font-semibold text-white mb-4">AI Vision Options</h2> |
| |
| <div class="space-y-4"> |
| <div class="p-3 bg-gray-900 rounded-lg border border-gray-700 hover-card"> |
| <div class="flex items-start"> |
| <div class="w-10 h-10 rounded-lg bg-blue-500/10 flex items-center justify-center mr-3 border border-blue-500/50"> |
| <i class="fas fa-search text-blue-400"></i> |
| </div> |
| <div> |
| <h3 class="font-medium text-white">Object Detection</h3> |
| <p class="text-sm text-gray-400 mt-1">Identify and label objects in your video</p> |
| <label class="relative inline-flex items-center mt-2"> |
| <input type="checkbox" class="sr-only peer" checked> |
| <div class="w-9 h-5 bg-gray-700 peer-focus:outline-none rounded-full peer peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:left-[2px] after:bg-white after:border-gray-300 after:border after:rounded-full after:h-4 after:w-4 after:transition-all peer-checked:bg-blue-600"></div> |
| </label> |
| </div> |
| </div> |
| </div> |
|
|
| <div class="p-3 bg-gray-900 rounded-lg border border-gray-700 hover-card"> |
| <div class="flex items-start"> |
| <div class="w-10 h-10 rounded-lg bg-purple-500/10 flex items-center justify-center mr-3 border border-purple-500/50"> |
| <i class="fas fa-person text-purple-400"></i> |
| </div> |
| <div> |
| <h3 class="font-medium text-white">People Tracking</h3> |
| <p class="text-sm text-gray-400 mt-1">Track individuals across scenes</p> |
| <label class="relative inline-flex items-center mt-2"> |
| <input type="checkbox" class="sr-only peer" checked> |
| <div class="w-9 h-5 bg-gray-700 peer-focus:outline-none rounded-full peer peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:left-[2px] after:bg-white after:border-gray-300 after:border after:rounded-full after:h-4 after:w-4 after:transition-all peer-checked:bg-purple-600"></div> |
| </label> |
| </div> |
| </div> |
| </div> |
|
|
| <div class="p-3 bg-gray-900 rounded-lg border border-gray-700 hover-card"> |
| <div class="flex items-start"> |
| <div class="w-10 h-10 rounded-lg bg-yellow-500/10 flex items-center justify-center mr-3 border border-yellow-500/50"> |
| <i class="fas fa-chart-line text-yellow-400"></i> |
| </div> |
| <div> |
| <h3 class="font-medium text-white">Activity Analysis</h3> |
| <p class="text-sm text-gray-400 mt-1">Detect actions and movements</p> |
| <label class="relative inline-flex items-center mt-2"> |
| <input type="checkbox" class="sr-only peer"> |
| <div class="w-9 h-5 bg-gray-700 peer-focus:outline-none rounded-full peer peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:left-[2px] after:bg-white after:border-gray-300 after:border after:rounded-full after:h-4 after:w-4 after:transition-all peer-checked:bg-yellow-600"></div> |
| </label> |
| </div> |
| </div> |
| </div> |
|
|
| <div class="p-3 bg-gray-900 rounded-lg border border-gray-700 hover-card"> |
| <div class="flex items-start"> |
| <div class="w-10 h-10 rounded-lg bg-green-500/10 flex items-center justify-center mr-3 border border-green-500/50"> |
| <i class="fas fa-image text-green-400"></i> |
| </div> |
| <div> |
| <h3 class="font-medium text-white">Scene Tags</h3> |
| <p class="text-sm text-gray-400 mt-1">Automatically categorize video segments</p> |
| <label class="relative inline-flex items-center mt-2"> |
| <input type="checkbox" class="sr-only peer" checked> |
| <div class="w-9 h-5 bg-gray-700 peer-focus:outline-none rounded-full peer peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:left-[2px] after:bg-white after:border-gray-300 after:border after:rounded-full after:h-4 after:w-4 after:transition-all peer-checked:bg-green-600"></div> |
| </label> |
| </div> |
| </div> |
| </div> |
| </div> |
|
|
| <div class="mt-4 p-4 bg-gray-900/50 rounded-lg border border-dashed border-gray-700"> |
| <div class="text-center"> |
| <button class="w-full py-2 px-4 border border-gray-600 hover:border-blue-500 rounded-lg text-sm text-gray-400 hover:text-blue-400 font-medium flex items-center justify-center"> |
| <i class="fas fa-plus mr-2"></i> Add Custom Analysis |
| </button> |
| </div> |
| </div> |
| </div> |
| </div> |
|
|
| |
| <div class="bg-gray-800 rounded-xl p-4 mb-8"> |
| <div class="flex justify-between items-center mb-4"> |
| <h2 class="text-lg font-semibold text-white">AI Analysis Results</h2> |
| <div class="flex space-x-2"> |
| <button class="px-3 py-1 bg-gray-700 hover:bg-gray-600 rounded-lg text-sm font-medium text-gray-300"> |
| <i class="fas fa-filter mr-2"></i> Filter |
| </button> |
| <button class="px-3 py-1 bg-gray-700 hover:bg-gray-600 rounded-lg text-sm font-medium text-gray-300"> |
| <i class="fas fa-download mr-2"></i> Export |
| </button> |
| </div> |
| </div> |
|
|
| |
| <div id="processingState" class="hidden"> |
| <div class="p-8 text-center rounded-lg bg-gray-900/50"> |
| <div class="loading-dots mb-4"> |
| <span></span> |
| <span></span> |
| <span></span> |
| </div> |
| <h3 class="text-lg font-medium text-white mb-2">Analyzing Video Content</h3> |
| <p class="text-gray-400">This usually takes 2-3 minutes depending on video length</p> |
| <div class="mt-4 text-xs text-gray-500"> |
| <i class="fas fa-info-circle mr-1"></i> Florence AI is detecting objects, people, and activities in your video. |
| </div> |
| </div> |
| </div> |
|
|
| |
| <div id="resultsDisplay"> |
| <div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4"> |
| |
| <div class="p-4 bg-gray-900 rounded-lg border border-gray-700"> |
| <h3 class="font-medium text-white mb-3 flex items-center"> |
| <i class="fas fa-box-open text-blue-400 mr-2"></i> Objects Detected |
| </h3> |
| <div class="flex flex-wrap gap-2"> |
| <span class="px-2 py-1 bg-blue-900/50 text-blue-300 rounded text-xs">person (92%)</span> |
| <span class="px-2 py-1 bg-blue-900/50 text-blue-300 rounded text-xs">car (87%)</span> |
| <span class="px-2 py-1 bg-blue-900/50 text-blue-300 rounded text-xs">tree (82%)</span> |
| <span class="px-2 py-1 bg-blue-900/50 text-blue-300 rounded text-xs">dog (76%)</span> |
| <span class="px-2 py-1 bg-blue-900/50 text-blue-300 rounded text-xs">building (94%)</span> |
| <span class="px-2 py-1 bg-blue-900/50 text-blue-300 rounded text-xs">bicycle (62%)</span> |
| </div> |
| </div> |
|
|
| |
| <div class="p-4 bg-gray-900 rounded-lg border border-gray-700"> |
| <h3 class="font-medium text-white mb-3 flex items-center"> |
| <i class="fas fa-running text-purple-400 mr-2"></i> Activities |
| </h3> |
| <div class="space-y-2"> |
| <div> |
| <div class="flex justify-between text-xs text-gray-400 mb-1"> |
| <span>Walking</span> |
| <span>00:12 - 01:35</span> |
| </div> |
| <div class="w-full bg-gray-700 rounded-full h-1.5"> |
| <div class="bg-purple-600 h-1.5 rounded-full" style="width: 78%"></div> |
| </div> |
| </div> |
| <div> |
| <div class="flex justify-between text-xs text-gray-400 mb-1"> |
| <span>Running</span> |
| <span>01:42 - 02:15</span> |
| </div> |
| <div class="w-full bg-gray-700 rounded-full h-1.5"> |
| <div class="bg-purple-600 h-1.5 rounded-full" style="width: 42%"></div> |
| </div> |
| </div> |
| <div> |
| <div class="flex justify-between text-xs text-gray-400 mb-1"> |
| <span>Standing</span> |
| <span>00:00 - 04:30</span> |
| </div> |
| <div class="w-full bg-gray-700 rounded-full h-1.5"> |
| <div class="bg-purple-600 h-1.5 rounded-full" style="width: 91%"></div> |
| </div> |
| </div> |
| </div> |
| </div> |
|
|
| |
| <div class="p-4 bg-gray-900 rounded-lg border border-gray-700"> |
| <h3 class="font-medium text-white mb-3 flex items-center"> |
| <i class="fas fa-photo-video text-yellow-400 mr-2"></i> Scene Segments |
| </h3> |
| <div class="space-y-3"> |
| <div class="flex items-start"> |
| <div class="w-8 h-8 rounded bg-yellow-500/10 flex items-center justify-center mr-2 flex-shrink-0 border border-yellow-500/30 text-yellow-400 text-xs">1</div> |
| <div> |
| <div class="text-sm text-white">Outdoor street view</div> |
| <div class="text-xs text-gray-400 mt-1">00:00 - 01:22</div> |
| </div> |
| </div> |
| <div class="flex items-start"> |
| <div class="w-8 h-8 rounded bg-yellow-500/10 flex items-center justify-center mr-2 flex-shrink-0 border border-yellow-500/30 text-yellow-400 text-xs">2</div> |
| <div> |
| <div class="text-sm text-white">Indoor conversation</div> |
| <div class="text-xs text-gray-400 mt-1">01:23 - 03:15</div> |
| </div> |
| </div> |
| <div class="flex items-start"> |
| <div class="w-8 h-8 rounded bg-yellow-500/10 flex items-center justify-center mr-2 flex-shrink-0 border border-yellow-500/30 text-yellow-400 text-xs">3</div> |
| <div> |
| <div class="text-sm text-white">Park activity</div> |
| <div class="text-xs text-gray-400 mt-1">03:16 - 04:30</div> |
| </div> |
| </div> |
| </div> |
| </div> |
| </div> |
|
|
| |
| <div class="mt-6 p-4 bg-gray-900 rounded-lg border border-gray-700"> |
| <h3 class="font-medium text-white mb-4">Timeline Analysis</h3> |
| <div class="relative h-40 overflow-hidden rounded-md"> |
| <canvas id="timelineCanvas" class="absolute top-0 left-0 w-full h-full"></canvas> |
| </div> |
| <div class="mt-2 flex justify-between text-xs text-gray-400"> |
| <span>00:00</span> |
| <span>01:30</span> |
| <span>03:00</span> |
| <span>04:30</span> |
| </div> |
| </div> |
|
|
| |
| <div class="mt-4"> |
| <h3 class="font-medium text-white mb-3">Key Frames</h3> |
| <div class="grid grid-cols-2 sm:grid-cols-3 md:grid-cols-4 lg:grid-cols-6 gap-3"> |
| <div class="relative rounded-md overflow-hidden aspect-video bg-gray-700"> |
| <div class="absolute inset-0 flex items-center justify-center text-gray-500"> |
| <i class="fas fa-image text-2xl"></i> |
| </div> |
| <div class="absolute bottom-0 left-0 right-0 bg-gradient-to-t from-black/80 to-transparent p-2"> |
| <div class="text-xs text-white truncate">Person walking (82%)</div> |
| <div class="text-[10px] text-gray-300">00:12</div> |
| </div> |
| </div> |
| <div class="relative rounded-md overflow-hidden aspect-video bg-gray-700"> |
| <div class="absolute inset-0 flex items-center justify-center text-gray-500"> |
| <i class="fas fa-image text-2xl"></i> |
| </div> |
| <div class="absolute bottom-0 left-0 right-0 bg-gradient-to-t from-black/80 to-transparent p-2"> |
| <div class="text-xs text-white truncate">Car moving (76%)</div> |
| <div class="text-[10px] text-gray-300">00:42</div> |
| </div> |
| </div> |
| <div class="relative rounded-md overflow-hidden aspect-video bg-gray-7 00"> |
| <div class="absolute inset-0 flex items-center justify-center text-gray-500"> |
| <i class="fas fa-image text-2xl"></i> |
| </div> |
| <div class="absolute bottom-0 left-0 right-0 bg-gradient-to-t from-black/80 to-transparent p-2"> |
| <div class="text-xs text-white truncate">Person running (68%)</div> |
| <div class="text-[10px] text-gray-300">01:55</div> |
| </div> |
| </div> |
| <div class="relative rounded-md overflow-hidden aspect-video bg-gray-700"> |
| <div class="absolute inset-0 flex items-center justify-center text-gray-500"> |
| <i class="fas fa-image text-2xl"></i> |
| </div> |
| <div class="absolute bottom-0 left-0 right-0 bg-gradient-to-t from-black/80 to-transparent p-2"> |
| <div class="text-xs text-white truncate">Building (93%)</div> |
| <div class="text-[10px] text-gray-300">02:30</div> |
| </div> |
| </div> |
| <div class="relative rounded-md overflow-hidden aspect-video bg-gray-700"> |
| <div class="absolute inset-0 flex items-center justify-center text-gray-500"> |
| <i class="fas fa-image text-2xl"></i> |
| </div> |
| <div class="absolute bottom-0 left-0 right-0 bg-gradient-to-t from-black/80 to-transparent p-2"> |
| <div class="text-xs text-white truncate">Dog sitting (71%)</div> |
| <div class="text-[10px] text-gray-300">03:15</div> |
| </div> |
| </div> |
| <div class="relative rounded-md overflow-hidden aspect-video bg-gray-700"> |
| <div class="absolute inset-0 flex items-center justify-center text-gray-500"> |
| <i class="fas fa-image text-2xl"></i> |
| </div> |
| <div class="absolute bottom-0 left-0 right-0 bg-gradient-to-t from-black/80 to-transparent p-2"> |
| <div class="text-xs text-white truncate">Bicycle (59%)</div> |
| <div class="text-[10px] text-gray-300">04:08</div> |
| </div> |
| </div> |
| </div> |
| </div> |
| </div> |
| </div> |
|
|
| |
| <div class="bg-gray-800 rounded-xl p-4"> |
| <div class="flex justify-between items-center mb-4"> |
| <h2 class="text-lg font-semibold text-white">Recent Projects</h2> |
| <button class="px-3 py-1 bg-gray-700 hover:bg-gray-600 rounded-lg text-sm font-medium text-gray-300"> |
| View All |
| </button> |
| </div> |
| <div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-4"> |
| <div class="group video-thumbnail relative rounded-lg overflow-hidden bg-gray-900 aspect-video"> |
| <div class="absolute inset-0 bg-gradient-to-br from-blue-900/20 to-purple-900/30 flex items-center justify-center"> |
| <i class="fas fa-play play-icon text-white/60 group-hover:text-white/90 text-4xl transition-all"></i> |
| </div> |
| <div class="absolute bottom-0 left-0 right-0 bg-gradient-to-t from-black/80 to-transparent p-3"> |
| <div class="text-sm font-medium text-white">Street Interview.mp4</div> |
| <div class="text-xs text-gray-400">Analyzed 2 days ago</div> |
| </div> |
| <div class="ai-tag text-xs px-2 py-1 rounded-full text-white">AI Processed</div> |
| </div> |
| <div class="group video-thumbnail relative rounded-lg overflow-hidden bg-gray-900 aspect-video"> |
| <div class="absolute inset-0 bg-gradient-to-br from-purple-900/20 to-pink-900/30 flex items-center justify-center"> |
| <i class="fas fa-play play-icon text-white/60 group-hover:text-white/90 text-4xl transition-all"></i> |
| </div> |
| <div class="absolute bottom-0 left-0 right-0 bg-gradient-to-t from-black/80 to-transparent p-3"> |
| <div class="text-sm font-medium text-white">Park Activities.mp4</div> |
| <div class="text-xs text-gray-400">Analyzed 1 week ago</div> |
| </div> |
| </div> |
| <div class="group video-thumbnail relative rounded-lg overflow-hidden bg-gray-900 aspect-video"> |
| <div class="absolute inset-0 bg-gradient-to-br from-pink-900/20 to-red-900/30 flex items-center justify-center"> |
| <i class="fas fa-play play-icon text-white/60 group-hover:text-white/90 text-4xl transition-all"></i> |
| </div> |
| <div class="absolute bottom-0 left-0 right-0 bg-gradient-to-t from-black/80 to-transparent p-3"> |
| <div class="text-sm font-medium text-white">Product Demo.mov</div> |
| <div class="text-xs text-gray-400">Analyzed 2 weeks ago</div> |
| </div> |
| <div class="ai-tag text-xs px-2 py-1 rounded-full text-white">AI Processed</div> |
| </div> |
| <div class="group video-thumbnail relative rounded-lg overflow-hidden bg-gray-900 aspect-video"> |
| <div class="absolute inset-0 bg-gradient-to-br from-green-900/20 to-blue-900/30 flex items-center justify-center"> |
| <i class="fas fa-plus text-white/60 group-hover:text-white/90 text-3xl transition-all"></i> |
| </div> |
| <div class="absolute bottom-0 left-0 right-0 bg-gradient-to-t from-black/80 to-transparent p-3 flex items-center justify-center"> |
| <div class="text-sm font-medium text-white">Upload New Video</div> |
| </div> |
| </div> |
| </div> |
| </div> |
| </div> |
|
|
| |
| <div id="contextMenu" class="context-menu absolute w-48 bg-gray-800 rounded-md shadow-lg z-50 py-1 border border-gray-700"> |
| <div class="text-gray-400 text-xs px-4 py-2 border-b border-gray-700">Video Actions</div> |
| <a href="#" class="block px-4 py-2 text-sm text-gray-300 hover:bg-gray-700">Analyze Scene</a> |
| <a href="#" class="block px-4 py-2 text-sm text-gray-300 hover:bg-gray-700">Extract Frame</a> |
| <a href="#" class="block px-4 py-2 text-sm text-gray-300 hover:bg-gray-700">Audio Analysis</a> |
| <div class="border-t border-gray-700 my-1"></div> |
| <a href="#" class="block px-4 py-2 text-sm text-gray-300 hover:bg-gray-700">Export Clip</a> |
| </div> |
|
|
| <script> |
| document.addEventListener('DOMContentLoaded', function() { |
| |
| const video = document.getElementById('videoPlayer'); |
| const playPauseBtn = document.getElementById('playPauseBtn'); |
| const progressIndicator = document.getElementById('progressIndicator'); |
| const currentTimeDisplay = document.getElementById('currentTime'); |
| const durationDisplay = document.getElementById('duration'); |
| const processBtn = document.getElementById('processBtn'); |
| const processingState = document.getElementById('processingState'); |
| const resultsDisplay = document.getElementById('resultsDisplay'); |
| const videoPlayerContainer = document.getElementById('videoPlayerContainer'); |
| const uploadContainer = document.getElementById('uploadContainer'); |
| const videoUpload = document.getElementById('videoUpload'); |
| const accountBtn = document.getElementById('accountBtn'); |
| const accountDropdown = document.getElementById('accountDropdown'); |
| |
| |
| const sampleVideoUrl = 'https://sample-videos.com/video123/mp4/720/big_buck_bunny_720p_1mb.mp4'; |
| |
| |
| function formatTime(seconds) { |
| const mins = Math.floor(seconds / 60); |
| const secs = Math.floor(seconds % 60); |
| return `${mins.toString().padStart(2, '0')}:${secs.toString().padStart(2, '0')}`; |
| } |
| |
| |
| function updateTimeDisplays() { |
| currentTimeDisplay.textContent = formatTime(video.currentTime); |
| durationDisplay.textContent = formatTime(video.duration); |
| progressIndicator.style.width = `${(video.currentTime / video.duration) * 100}%`; |
| } |
| |
| |
| function togglePlayPause() { |
| if (video.paused) { |
| video.play(); |
| playPauseBtn.innerHTML = '<i class="fas fa-pause"></i>'; |
| } else { |
| video.pause(); |
| playPauseBtn.innerHTML = '<i class="fas fa-play"></i>'; |
| } |
| } |
| |
| |
| function handleFileUpload(event) { |
| const file = event.target.files[0]; |
| if (!file) return; |
| |
| const fileType = file.type.split('/')[0]; |
| const isAudio = fileType === 'audio'; |
| |
| |
| const fileURL = URL.createObjectURL(file); |
| |
| |
| uploadContainer.classList.add('hidden'); |
| videoPlayerContainer.classList.remove('hidden'); |
| |
| if (isAudio) { |
| |
| video.poster = 'https://images.unsplash.com/photo-1511671782779-c97d3d27a1d4?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=1000&q=80'; |
| video.innerHTML = `<source src="${fileURL}" type="${file.type}">`; |
| } else { |
| |
| video.poster = ''; |
| video.innerHTML = `<source src="${fileURL}" type="${file.type}">`; |
| } |
| |
| |
| video.load(); |
| } |
| |
| |
| document.querySelectorAll('.video-thumbnail').forEach(thumbnail => { |
| thumbnail.addEventListener('click', function() { |
| const isNewUpload = this.querySelector('.fa-plus'); |
| |
| if (isNewUpload) { |
| |
| videoUpload.click(); |
| } else { |
| |
| uploadContainer.classList.add('hidden'); |
| videoPlayerContainer.classList.remove('hidden'); |
| video.innerHTML = `<source src="${sampleVideoUrl}" type="video/mp4">`; |
| video.load(); |
| video.play().then(() => { |
| playPauseBtn.innerHTML = '<i class="fas fa-pause"></i>'; |
| }); |
| } |
| }); |
| }); |
| |
| |
| video.addEventListener('timeupdate', updateTimeDisplays); |
| video.addEventListener('click', togglePlayPause); |
| video.addEventListener('play', () => { |
| playPauseBtn.innerHTML = '<i class="fas fa-pause"></i>'; |
| }); |
| video.addEventListener('pause', () => { |
| playPauseBtn.innerHTML = '<i class="fas fa-play"></i>'; |
| }); |
| video.addEventListener('loadedmetadata', updateTimeDisplays); |
| |
| playPauseBtn.addEventListener('click', togglePlayPause); |
| |
| |
| processBtn.addEventListener('click', function() { |
| processingState.classList.remove('hidden'); |
| resultsDisplay.classList.add('hidden'); |
| |
| |
| setTimeout(() => { |
| processingState.classList.add('hidden'); |
| resultsDisplay.classList.remove('hidden'); |
| drawTimeline(); |
| |
| |
| processBtn.innerHTML = '<i class="fas fa-sync-alt mr-2"></i> Re-process'; |
| processBtn.classList.add('bg-blue-700'); |
| }, 2500); |
| }); |
| |
| |
| uploadContainer.addEventListener('click', function() { |
| videoUpload.click(); |
| }); |
| |
| |
| videoUpload.addEventListener('change', handleFileUpload); |
| |
| |
| accountBtn.addEventListener('click', function(e) { |
| e.stopPropagation(); |
| accountDropdown.classList.toggle('hidden'); |
| }); |
| |
| |
| document.addEventListener('click', function() { |
| accountDropdown.classList.add('hidden'); |
| }); |
| |
| |
| document.addEventListener('contextmenu', function(e) { |
| e.preventDefault(); |
| const contextMenu = document.getElementById('contextMenu'); |
| |
| |
| let x = e.pageX; |
| let y = e.pageY; |
| |
| |
| const menuWidth = contextMenu.offsetWidth; |
| const menuHeight = contextMenu.offsetHeight; |
| |
| if (x + menuWidth > window.innerWidth) { |
| x = window.innerWidth - menuWidth; |
| } |
| |
| if (y + menuHeight > window.innerHeight) { |
| y = window.innerHeight - menuHeight; |
| } |
| |
| contextMenu.style.left = `${x}px`; |
| contextMenu.style.top = `${y}px`; |
| contextMenu.classList.add('active'); |
| |
| |
| const closeMenu = function() { |
| contextMenu.classList.remove('active'); |
| document.removeEventListener('click', closeMenu); |
| }; |
| |
| document.addEventListener('click', closeMenu); |
| }); |
| |
| |
| function drawTimeline() { |
| const canvas = document.getElementById('timelineCanvas'); |
| const ctx = canvas.getContext('2d'); |
| |
| |
| canvas.width = canvas.offsetWidth; |
| canvas.height = canvas.offsetHeight; |
| |
| |
| const activities = [ |
| { type: 'people', start: 0, end: 270, color: '#3b82f6' }, |
| { type: 'objects', start: 30, end: 180, color: '#10b981' }, |
| { type: 'movement', start: 60, end: 240, color: '#8b5cf6' }, |
| { type: 'people', start: 180, end: 270, color: '#3b82f6' } |
| ]; |
| |
| |
| ctx.strokeStyle = 'rgba(255, 255, 255, 0.1)'; |
| ctx.lineWidth = 2; |
| ctx.beginPath(); |
| ctx.moveTo(0, canvas.height / 2); |
| ctx.lineTo(canvas.width, canvas.height / 2); |
| ctx.stroke(); |
| |
| |
| activities.forEach(activity => { |
| const x1 = (activity.start / 270) * canvas.width; |
| const x2 = (activity.end / 270) * canvas.width; |
| const width = x2 - x1; |
| |
| ctx.fillStyle = activity.color + '20'; |
| ctx.strokeStyle = activity.color; |
| ctx.lineWidth = 1; |
| |
| |
| ctx.beginPath(); |
| ctx.roundRect(x1, canvas.height / 4, width, canvas.height / 2, 6); |
| ctx.fill(); |
| ctx.stroke(); |
| |
| |
| ctx.fillStyle = activity.color; |
| ctx.beginPath(); |
| ctx.arc(x1, canvas.height / 2, 3, 0, Math.PI * 2); |
| ctx.fill(); |
| ctx.beginPath(); |
| ctx.arc(x2, canvas.height / 2, 3, 0, Math.PI * 2); |
| ctx.fill(); |
| }); |
| |
| |
| const times = [0, 90, 180, 270]; |
| times.forEach(time => { |
| const x = (time / 270) * canvas.width; |
| |
| ctx.strokeStyle = 'rgba(255, 255, 255, 0.2)'; |
| ctx.lineWidth = 1; |
| ctx.beginPath(); |
| ctx.moveTo(x, canvas.height / 2 - 10); |
| ctx.lineTo(x, canvas.height / 2 + 10); |
| ctx.stroke(); |
| }); |
| } |
| |
| |
| window.addEventListener('resize', drawTimeline); |
| }); |
| </script> |
| </body> |
| </html> |