Spaces:
Running
Running
<html lang="en"> | |
<head> | |
<meta charset="UTF-8"> | |
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
<title>AI Video Generator | Transform Images to Videos</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=Poppins:wght@300;400;500;600;700&display=swap'); | |
body { | |
font-family: 'Poppins', sans-serif; | |
background-color: #f8fafc; | |
} | |
.dropzone { | |
border: 2px dashed #cbd5e1; | |
transition: all 0.3s ease; | |
} | |
.dropzone.active { | |
border-color: #6366f1; | |
background-color: #eef2ff; | |
} | |
.progress-bar { | |
height: 8px; | |
transition: width 0.3s ease; | |
} | |
.video-preview { | |
box-shadow: 0 10px 25px -5px rgba(0, 0, 0, 0.1); | |
transition: all 0.3s ease; | |
} | |
.video-preview:hover { | |
transform: translateY(-2px); | |
box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1); | |
} | |
.tooltip { | |
position: relative; | |
} | |
.tooltip-text { | |
visibility: hidden; | |
width: 120px; | |
background-color: #1e293b; | |
color: #fff; | |
text-align: center; | |
border-radius: 6px; | |
padding: 5px; | |
position: absolute; | |
z-index: 1; | |
bottom: 125%; | |
left: 50%; | |
margin-left: -60px; | |
opacity: 0; | |
transition: opacity 0.3s; | |
} | |
.tooltip:hover .tooltip-text { | |
visibility: visible; | |
opacity: 1; | |
} | |
.animate-pulse { | |
animation: pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite; | |
} | |
@keyframes pulse { | |
0%, 100% { | |
opacity: 1; | |
} | |
50% { | |
opacity: 0.5; | |
} | |
} | |
</style> | |
</head> | |
<body class="min-h-screen"> | |
<div class="container mx-auto px-4 py-8 max-w-6xl"> | |
<!-- Header --> | |
<header class="mb-12 text-center"> | |
<h1 class="text-4xl font-bold text-indigo-900 mb-2">AI Video Generator</h1> | |
<p class="text-lg text-gray-600">Transform your images into stunning videos with AI-powered motion effects</p> | |
</header> | |
<!-- Main Content --> | |
<div class="bg-white rounded-xl shadow-lg overflow-hidden"> | |
<div class="md:flex"> | |
<!-- Left Panel - Upload & Settings --> | |
<div class="md:w-1/2 p-8 border-r border-gray-100"> | |
<div class="mb-8"> | |
<h2 class="text-xl font-semibold text-gray-800 mb-4">Upload Images</h2> | |
<!-- Dropzone --> | |
<div id="dropzone" class="dropzone rounded-lg p-8 text-center cursor-pointer mb-4"> | |
<div class="flex flex-col items-center justify-center"> | |
<i class="fas fa-cloud-upload-alt text-4xl text-indigo-500 mb-3"></i> | |
<p class="text-gray-600 mb-1">Drag & drop your images here</p> | |
<p class="text-sm text-gray-500">or click to browse files</p> | |
<input type="file" id="fileInput" class="hidden" accept="image/*" multiple> | |
</div> | |
</div> | |
<div class="text-sm text-gray-500 text-center"> | |
Supports JPG, PNG, WEBP (Max 20 images, 10MB each) | |
</div> | |
</div> | |
<!-- Uploaded Files List --> | |
<div id="fileListContainer" class="mb-8 hidden"> | |
<h3 class="font-medium text-gray-700 mb-3">Selected Images</h3> | |
<div id="fileList" class="max-h-48 overflow-y-auto border border-gray-200 rounded-lg p-2"> | |
<!-- Files will be listed here --> | |
</div> | |
</div> | |
<!-- Settings --> | |
<div class="mb-8"> | |
<h2 class="text-xl font-semibold text-gray-800 mb-4">Video Settings</h2> | |
<div class="space-y-4"> | |
<div> | |
<label class="block text-sm font-medium text-gray-700 mb-1">Transition Style</label> | |
<select id="transitionStyle" class="w-full rounded-lg border-gray-300 focus:border-indigo-500 focus:ring-indigo-500"> | |
<option value="slide">Slide</option> | |
<option value="fade">Fade</option> | |
<option value="zoom">Zoom</option> | |
<option value="pan">Pan & Zoom</option> | |
</select> | |
</div> | |
<div> | |
<label class="block text-sm font-medium text-gray-700 mb-1">Duration per Image (seconds)</label> | |
<input type="range" id="durationSlider" min="1" max="10" value="3" class="w-full h-2 bg-gray-200 rounded-lg appearance-none cursor-pointer"> | |
<div class="flex justify-between text-xs text-gray-500 mt-1"> | |
<span>1s</span> | |
<span id="durationValue">3s</span> | |
<span>10s</span> | |
</div> | |
</div> | |
<div> | |
<label class="block text-sm font-medium text-gray-700 mb-1">Video Resolution</label> | |
<select id="resolution" class="w-full rounded-lg border-gray-300 focus:border-indigo-500 focus:ring-indigo-500"> | |
<option value="480p">480p (SD)</option> | |
<option value="720p" selected>720p (HD)</option> | |
<option value="1080p">1080p (Full HD)</option> | |
<option value="4k">4K (Ultra HD)</option> | |
</select> | |
</div> | |
<div class="flex items-center"> | |
<input type="checkbox" id="addMusic" class="h-4 w-4 text-indigo-600 focus:ring-indigo-500 border-gray-300 rounded"> | |
<label for="addMusic" class="ml-2 block text-sm text-gray-700">Add background music</label> | |
</div> | |
</div> | |
</div> | |
<!-- Generate Button --> | |
<button id="generateBtn" class="w-full bg-indigo-600 hover:bg-indigo-700 text-white font-medium py-3 px-4 rounded-lg transition duration-200 flex items-center justify-center"> | |
<i class="fas fa-magic mr-2"></i> Generate Video | |
</button> | |
</div> | |
<!-- Right Panel - Preview & Results --> | |
<div class="md:w-1/2 p-8 bg-gray-50"> | |
<h2 class="text-xl font-semibold text-gray-800 mb-6">Video Preview</h2> | |
<!-- Empty State --> | |
<div id="emptyState" class="flex flex-col items-center justify-center h-64 bg-white rounded-lg border-2 border-dashed border-gray-200 text-center p-6"> | |
<i class="fas fa-video text-4xl text-gray-300 mb-3"></i> | |
<h3 class="text-lg font-medium text-gray-500">No video generated yet</h3> | |
<p class="text-gray-400 mt-1">Upload images and click "Generate Video" to create your AI video</p> | |
</div> | |
<!-- Processing State --> | |
<div id="processingState" class="hidden flex-col items-center justify-center h-64 bg-white rounded-lg border border-gray-200 text-center p-6"> | |
<div class="animate-pulse mb-4"> | |
<i class="fas fa-cog fa-spin text-3xl text-indigo-500"></i> | |
</div> | |
<h3 class="text-lg font-medium text-gray-700 mb-2">Processing your video</h3> | |
<p class="text-gray-500 mb-4">This may take a few moments...</p> | |
<div class="w-full bg-gray-200 rounded-full h-2.5 mb-2"> | |
<div id="progressBar" class="progress-bar bg-indigo-600 rounded-full h-2.5" style="width: 0%"></div> | |
</div> | |
<p id="progressText" class="text-sm text-gray-500">0% completed</p> | |
</div> | |
<!-- Result State --> | |
<div id="resultState" class="hidden"> | |
<div class="video-preview bg-white rounded-lg overflow-hidden mb-4"> | |
<video id="generatedVideo" controls class="w-full" poster="https://via.placeholder.com/800x450?text=Video+Preview"> | |
Your browser does not support the video tag. | |
</video> | |
</div> | |
<div class="flex flex-col sm:flex-row gap-3"> | |
<button id="downloadBtn" class="flex-1 bg-green-600 hover:bg-green-700 text-white font-medium py-2 px-4 rounded-lg transition duration-200 flex items-center justify-center"> | |
<i class="fas fa-download mr-2"></i> Download | |
</button> | |
<button id="newVideoBtn" class="flex-1 bg-gray-200 hover:bg-gray-300 text-gray-800 font-medium py-2 px-4 rounded-lg transition duration-200 flex items-center justify-center"> | |
<i class="fas fa-redo mr-2"></i> Create New | |
</button> | |
<div class="tooltip"> | |
<button id="shareBtn" class="flex-1 bg-blue-600 hover:bg-blue-700 text-white font-medium py-2 px-4 rounded-lg transition duration-200 flex items-center justify-center"> | |
<i class="fas fa-share-alt mr-2"></i> Share | |
</button> | |
<span class="tooltip-text">Coming soon!</span> | |
</div> | |
</div> | |
<div class="mt-6 bg-indigo-50 border border-indigo-100 rounded-lg p-4"> | |
<h3 class="font-medium text-indigo-800 mb-2">Video Details</h3> | |
<div class="grid grid-cols-2 gap-2 text-sm"> | |
<div class="text-gray-600">Duration:</div> | |
<div id="videoDuration" class="text-gray-800">-</div> | |
<div class="text-gray-600">Resolution:</div> | |
<div id="videoResolution" class="text-gray-800">-</div> | |
<div class="text-gray-600">File Size:</div> | |
<div id="videoSize" class="text-gray-800">-</div> | |
<div class="text-gray-600">Format:</div> | |
<div id="videoFormat" class="text-gray-800">MP4</div> | |
</div> | |
</div> | |
</div> | |
</div> | |
</div> | |
</div> | |
<!-- Features Section --> | |
<div class="mt-16"> | |
<h2 class="text-2xl font-bold text-center text-gray-800 mb-8">AI-Powered Video Creation</h2> | |
<div class="grid md:grid-cols-3 gap-8"> | |
<div class="bg-white p-6 rounded-xl shadow-sm hover:shadow-md transition duration-200"> | |
<div class="text-indigo-500 mb-4 text-3xl"> | |
<i class="fas fa-brain"></i> | |
</div> | |
<h3 class="font-semibold text-lg mb-2">Smart Motion Effects</h3> | |
<p class="text-gray-600">Our AI analyzes your images and applies natural-looking motion effects to create dynamic videos.</p> | |
</div> | |
<div class="bg-white p-6 rounded-xl shadow-sm hover:shadow-md transition duration-200"> | |
<div class="text-indigo-500 mb-4 text-3xl"> | |
<i class="fas fa-sliders-h"></i> | |
</div> | |
<h3 class="font-semibold text-lg mb-2">Customizable Transitions</h3> | |
<p class="text-gray-600">Choose from multiple transition styles and durations to match your creative vision.</p> | |
</div> | |
<div class="bg-white p-6 rounded-xl shadow-sm hover:shadow-md transition duration-200"> | |
<div class="text-indigo-500 mb-4 text-3xl"> | |
<i class="fas fa-bolt"></i> | |
</div> | |
<h3 class="font-semibold text-lg mb-2">Fast Processing</h3> | |
<p class="text-gray-600">Generate high-quality videos in minutes with our optimized AI processing pipeline.</p> | |
</div> | |
</div> | |
</div> | |
</div> | |
<script> | |
document.addEventListener('DOMContentLoaded', function() { | |
// DOM Elements | |
const dropzone = document.getElementById('dropzone'); | |
const fileInput = document.getElementById('fileInput'); | |
const fileListContainer = document.getElementById('fileListContainer'); | |
const fileList = document.getElementById('fileList'); | |
const durationSlider = document.getElementById('durationSlider'); | |
const durationValue = document.getElementById('durationValue'); | |
const generateBtn = document.getElementById('generateBtn'); | |
const emptyState = document.getElementById('emptyState'); | |
const processingState = document.getElementById('processingState'); | |
const resultState = document.getElementById('resultState'); | |
const progressBar = document.getElementById('progressBar'); | |
const progressText = document.getElementById('progressText'); | |
const downloadBtn = document.getElementById('downloadBtn'); | |
const newVideoBtn = document.getElementById('newVideoBtn'); | |
const generatedVideo = document.getElementById('generatedVideo'); | |
const videoDuration = document.getElementById('videoDuration'); | |
const videoResolution = document.getElementById('videoResolution'); | |
const videoSize = document.getElementById('videoSize'); | |
// Variables | |
let selectedFiles = []; | |
// Event Listeners | |
dropzone.addEventListener('click', () => fileInput.click()); | |
fileInput.addEventListener('change', handleFileSelect); | |
dropzone.addEventListener('dragover', (e) => { | |
e.preventDefault(); | |
dropzone.classList.add('active'); | |
}); | |
dropzone.addEventListener('dragleave', () => { | |
dropzone.classList.remove('active'); | |
}); | |
dropzone.addEventListener('drop', (e) => { | |
e.preventDefault(); | |
dropzone.classList.remove('active'); | |
if (e.dataTransfer.files.length > 0) { | |
fileInput.files = e.dataTransfer.files; | |
handleFileSelect({ target: fileInput }); | |
} | |
}); | |
durationSlider.addEventListener('input', () => { | |
durationValue.textContent = `${durationSlider.value}s`; | |
}); | |
generateBtn.addEventListener('click', generateVideo); | |
downloadBtn.addEventListener('click', downloadVideo); | |
newVideoBtn.addEventListener('click', resetForm); | |
// Functions | |
function handleFileSelect(event) { | |
const files = Array.from(event.target.files).slice(0, 20); // Limit to 20 files | |
// Filter only image files | |
selectedFiles = files.filter(file => file.type.match('image.*')); | |
if (selectedFiles.length > 0) { | |
displayFileList(); | |
} else { | |
alert('Please select valid image files (JPG, PNG, WEBP)'); | |
} | |
} | |
function displayFileList() { | |
fileList.innerHTML = ''; | |
selectedFiles.forEach((file, index) => { | |
const fileItem = document.createElement('div'); | |
fileItem.className = 'flex items-center justify-between py-2 px-3 hover:bg-gray-50 rounded'; | |
const fileInfo = document.createElement('div'); | |
fileInfo.className = 'flex items-center truncate'; | |
const fileIcon = document.createElement('i'); | |
fileIcon.className = 'fas fa-image text-gray-400 mr-3'; | |
const fileName = document.createElement('span'); | |
fileName.className = 'text-sm text-gray-700 truncate'; | |
fileName.textContent = file.name; | |
const fileSize = document.createElement('span'); | |
fileSize.className = 'text-xs text-gray-500 ml-2'; | |
fileSize.textContent = formatFileSize(file.size); | |
const removeBtn = document.createElement('button'); | |
removeBtn.className = 'text-red-400 hover:text-red-600 ml-2'; | |
removeBtn.innerHTML = '<i class="fas fa-times"></i>'; | |
removeBtn.addEventListener('click', () => removeFile(index)); | |
fileInfo.appendChild(fileIcon); | |
fileInfo.appendChild(fileName); | |
fileInfo.appendChild(fileSize); | |
fileItem.appendChild(fileInfo); | |
fileItem.appendChild(removeBtn); | |
fileList.appendChild(fileItem); | |
}); | |
fileListContainer.classList.remove('hidden'); | |
} | |
function removeFile(index) { | |
selectedFiles.splice(index, 1); | |
if (selectedFiles.length > 0) { | |
displayFileList(); | |
} else { | |
fileListContainer.classList.add('hidden'); | |
} | |
} | |
function formatFileSize(bytes) { | |
if (bytes === 0) return '0 Bytes'; | |
const k = 1024; | |
const sizes = ['Bytes', 'KB', 'MB', 'GB']; | |
const i = Math.floor(Math.log(bytes) / Math.log(k)); | |
return parseFloat((bytes / Math.pow(k, i)).toFixed(1)) + ' ' + sizes[i]; | |
} | |
function generateVideo() { | |
if (selectedFiles.length === 0) { | |
alert('Please upload at least one image'); | |
return; | |
} | |
// Show processing state | |
emptyState.classList.add('hidden'); | |
processingState.classList.remove('hidden'); | |
resultState.classList.add('hidden'); | |
// Simulate processing with progress updates | |
let progress = 0; | |
const interval = setInterval(() => { | |
progress += Math.random() * 10; | |
if (progress > 100) progress = 100; | |
progressBar.style.width = `${progress}%`; | |
progressText.textContent = `${Math.round(progress)}% completed`; | |
if (progress === 100) { | |
clearInterval(interval); | |
setTimeout(showResult, 500); | |
} | |
}, 500); | |
} | |
function showResult() { | |
processingState.classList.add('hidden'); | |
resultState.classList.remove('hidden'); | |
// In a real app, this would be the actual generated video | |
// For demo purposes, we'll use a placeholder | |
generatedVideo.src = 'https://sample-videos.com/video123/mp4/720/big_buck_bunny_720p_1mb.mp4'; | |
generatedVideo.poster = URL.createObjectURL(selectedFiles[0]); | |
// Set video details | |
const duration = selectedFiles.length * parseInt(durationSlider.value); | |
videoDuration.textContent = `${duration} seconds`; | |
const resolution = document.getElementById('resolution').value; | |
videoResolution.textContent = resolution.toUpperCase(); | |
// Random file size for demo | |
const sizeMB = (Math.random() * 5 + 1).toFixed(1); | |
videoSize.textContent = `${sizeMB} MB`; | |
} | |
function downloadVideo() { | |
// In a real app, this would download the actual generated video | |
alert('Video download would start here. This is a demo.'); | |
} | |
function resetForm() { | |
selectedFiles = []; | |
fileInput.value = ''; | |
fileListContainer.classList.add('hidden'); | |
resultState.classList.add('hidden'); | |
emptyState.classList.remove('hidden'); | |
durationSlider.value = 3; | |
durationValue.textContent = '3s'; | |
} | |
}); | |
</script> | |
<p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://enzostvs-deepsite.hf.space?remix=XXXMARK/ai-video-generator" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body> | |
</html> |