ai-video-generator / index.html
XXXMARK's picture
Add 3 files
4dd3b05 verified
<!DOCTYPE html>
<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>