Spaces:
Running
Running
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>Video Face Swap | Tonyassi</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> | |
| .dropzone { | |
| border: 2px dashed #ccc; | |
| transition: all 0.3s ease; | |
| } | |
| .dropzone.active { | |
| border-color: #3b82f6; | |
| background-color: rgba(59, 130, 246, 0.05); | |
| } | |
| .progress-bar { | |
| transition: width 0.3s ease; | |
| } | |
| .face-preview { | |
| transition: all 0.3s ease; | |
| } | |
| .face-preview:hover { | |
| transform: scale(1.05); | |
| box-shadow: 0 10px 25px rgba(0, 0, 0, 0.1); | |
| } | |
| .tooltip { | |
| position: relative; | |
| } | |
| .tooltip-text { | |
| visibility: hidden; | |
| width: 120px; | |
| background-color: #333; | |
| 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; | |
| } | |
| </style> | |
| </head> | |
| <body class="bg-gray-50 min-h-screen"> | |
| <header class="bg-white shadow-sm"> | |
| <div class="container mx-auto px-4 py-6"> | |
| <div class="flex justify-between items-center"> | |
| <div class="flex items-center space-x-2"> | |
| <i class="fas fa-exchange-alt text-blue-500 text-2xl"></i> | |
| <h1 class="text-2xl font-bold text-gray-800">Video Face Swap</h1> | |
| </div> | |
| <div class="flex space-x-4"> | |
| <button class="px-4 py-2 bg-blue-500 text-white rounded-lg hover:bg-blue-600 transition"> | |
| <i class="fas fa-user mr-2"></i>Login | |
| </button> | |
| <button class="px-4 py-2 border border-blue-500 text-blue-500 rounded-lg hover:bg-blue-50 transition"> | |
| <i class="fas fa-sign-in-alt mr-2"></i>Sign Up | |
| </button> | |
| </div> | |
| </div> | |
| </div> | |
| </header> | |
| <main class="container mx-auto px-4 py-8"> | |
| <div class="max-w-4xl mx-auto"> | |
| <div class="text-center mb-12"> | |
| <h2 class="text-3xl font-bold text-gray-800 mb-4">Swap Faces in Videos Effortlessly</h2> | |
| <p class="text-gray-600 text-lg">Upload your video and target face, then let our AI do the magic!</p> | |
| </div> | |
| <div class="grid grid-cols-1 md:grid-cols-2 gap-8 mb-8"> | |
| <!-- Source Face Upload --> | |
| <div class="bg-white p-6 rounded-xl shadow-md"> | |
| <div class="flex items-center mb-4"> | |
| <div class="w-10 h-10 bg-blue-100 rounded-full flex items-center justify-center mr-3"> | |
| <i class="fas fa-user text-blue-500"></i> | |
| </div> | |
| <h3 class="text-xl font-semibold text-gray-800">Source Face</h3> | |
| </div> | |
| <p class="text-gray-600 mb-4">Upload the face you want to swap from (image or video)</p> | |
| <div id="source-dropzone" class="dropzone rounded-lg p-8 text-center cursor-pointer mb-4"> | |
| <i class="fas fa-cloud-upload-alt text-4xl text-gray-400 mb-3"></i> | |
| <p class="text-gray-500">Drag & drop your file here or click to browse</p> | |
| <input type="file" id="source-input" class="hidden" accept="image/*,video/*"> | |
| </div> | |
| <div id="source-preview" class="hidden"> | |
| <div class="flex justify-between items-center mb-2"> | |
| <span class="text-sm font-medium text-gray-700">Selected file:</span> | |
| <button id="clear-source" class="text-red-500 hover:text-red-700"> | |
| <i class="fas fa-times"></i> Clear | |
| </button> | |
| </div> | |
| <div class="flex items-center space-x-4"> | |
| <div class="w-16 h-16 bg-gray-200 rounded-lg overflow-hidden"> | |
| <img id="source-thumbnail" src="" alt="Source preview" class="w-full h-full object-cover"> | |
| </div> | |
| <div class="flex-1"> | |
| <p id="source-filename" class="text-sm font-medium text-gray-800 truncate"></p> | |
| <p id="source-filesize" class="text-xs text-gray-500"></p> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Target Video Upload --> | |
| <div class="bg-white p-6 rounded-xl shadow-md"> | |
| <div class="flex items-center mb-4"> | |
| <div class="w-10 h-10 bg-purple-100 rounded-full flex items-center justify-center mr-3"> | |
| <i class="fas fa-video text-purple-500"></i> | |
| </div> | |
| <h3 class="text-xl font-semibold text-gray-800">Target Video</h3> | |
| </div> | |
| <p class="text-gray-600 mb-4">Upload the video where you want to swap the face</p> | |
| <div id="target-dropzone" class="dropzone rounded-lg p-8 text-center cursor-pointer mb-4"> | |
| <i class="fas fa-cloud-upload-alt text-4xl text-gray-400 mb-3"></i> | |
| <p class="text-gray-500">Drag & drop your video here or click to browse</p> | |
| <input type="file" id="target-input" class="hidden" accept="video/*"> | |
| </div> | |
| <div id="target-preview" class="hidden"> | |
| <div class="flex justify-between items-center mb-2"> | |
| <span class="text-sm font-medium text-gray-700">Selected file:</span> | |
| <button id="clear-target" class="text-red-500 hover:text-red-700"> | |
| <i class="fas fa-times"></i> Clear | |
| </button> | |
| </div> | |
| <div class="flex items-center space-x-4"> | |
| <div class="w-16 h-16 bg-gray-200 rounded-lg overflow-hidden relative"> | |
| <video id="target-thumbnail" src="" class="w-full h-full object-cover"></video> | |
| <div class="absolute inset-0 flex items-center justify-center"> | |
| <i class="fas fa-play text-white bg-black bg-opacity-50 rounded-full p-2"></i> | |
| </div> | |
| </div> | |
| <div class="flex-1"> | |
| <p id="target-filename" class="text-sm font-medium text-gray-800 truncate"></p> | |
| <p id="target-filesize" class="text-xs text-gray-500"></p> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Face Detection Options --> | |
| <div class="bg-white p-6 rounded-xl shadow-md mb-8"> | |
| <h3 class="text-xl font-semibold text-gray-800 mb-4">Face Detection Settings</h3> | |
| <div class="grid grid-cols-1 md:grid-cols-3 gap-6"> | |
| <div> | |
| <label class="block text-sm font-medium text-gray-700 mb-1">Detection Model</label> | |
| <select class="w-full border border-gray-300 rounded-lg px-3 py-2 focus:outline-none focus:ring-2 focus:ring-blue-500"> | |
| <option>RetinaFace (Recommended)</option> | |
| <option>MTCNN</option> | |
| <option>DLib</option> | |
| </select> | |
| </div> | |
| <div> | |
| <label class="block text-sm font-medium text-gray-700 mb-1">Detection Threshold</label> | |
| <input type="range" min="0" max="100" value="85" 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>Low</span> | |
| <span>Medium</span> | |
| <span>High</span> | |
| </div> | |
| </div> | |
| <div> | |
| <label class="block text-sm font-medium text-gray-700 mb-1">Face Alignment</label> | |
| <div class="flex items-center space-x-4"> | |
| <label class="inline-flex items-center"> | |
| <input type="radio" name="alignment" checked class="h-4 w-4 text-blue-600"> | |
| <span class="ml-2 text-gray-700">Automatic</span> | |
| </label> | |
| <label class="inline-flex items-center"> | |
| <input type="radio" name="alignment" class="h-4 w-4 text-blue-600"> | |
| <span class="ml-2 text-gray-700">Manual</span> | |
| </label> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Processing Options --> | |
| <div class="bg-white p-6 rounded-xl shadow-md mb-8"> | |
| <h3 class="text-xl font-semibold text-gray-800 mb-4">Processing Options</h3> | |
| <div class="grid grid-cols-1 md:grid-cols-2 gap-6"> | |
| <div> | |
| <label class="block text-sm font-medium text-gray-700 mb-1">Output Quality</label> | |
| <select class="w-full border border-gray-300 rounded-lg px-3 py-2 focus:outline-none focus:ring-2 focus:ring-blue-500"> | |
| <option>High (Best quality, larger file)</option> | |
| <option selected>Medium (Good balance)</option> | |
| <option>Low (Smaller file)</option> | |
| </select> | |
| </div> | |
| <div> | |
| <label class="block text-sm font-medium text-gray-700 mb-1">Frame Rate</label> | |
| <select class="w-full border border-gray-300 rounded-lg px-3 py-2 focus:outline-none focus:ring-2 focus:ring-blue-500"> | |
| <option>Original</option> | |
| <option selected>30 FPS</option> | |
| <option>24 FPS</option> | |
| <option>15 FPS</option> | |
| </select> | |
| </div> | |
| </div> | |
| <div class="mt-4"> | |
| <label class="inline-flex items-center"> | |
| <input type="checkbox" checked class="h-4 w-4 text-blue-600"> | |
| <span class="ml-2 text-gray-700">Enhance face details</span> | |
| </label> | |
| <span class="tooltip ml-1"> | |
| <i class="fas fa-info-circle text-gray-400"></i> | |
| <span class="tooltip-text">Improves facial features for more realistic results</span> | |
| </span> | |
| </div> | |
| <div class="mt-2"> | |
| <label class="inline-flex items-center"> | |
| <input type="checkbox" class="h-4 w-4 text-blue-600"> | |
| <span class="ml-2 text-gray-700">Match skin tones</span> | |
| </label> | |
| <span class="tooltip ml-1"> | |
| <i class="fas fa-info-circle text-gray-400"></i> | |
| <span class="tooltip-text">Automatically adjusts skin color for better blending</span> | |
| </span> | |
| </div> | |
| </div> | |
| <!-- Process Button --> | |
| <div class="text-center"> | |
| <button id="process-btn" class="px-8 py-3 bg-gradient-to-r from-blue-500 to-purple-600 text-white rounded-full font-semibold text-lg hover:from-blue-600 hover:to-purple-700 transition-all transform hover:scale-105 shadow-lg"> | |
| <i class="fas fa-magic mr-2"></i> Start Face Swap | |
| </button> | |
| </div> | |
| <!-- Processing Status (Hidden by default) --> | |
| <div id="processing-status" class="hidden mt-8 bg-white p-6 rounded-xl shadow-md"> | |
| <h3 class="text-xl font-semibold text-gray-800 mb-4">Processing Your Video</h3> | |
| <div class="mb-4"> | |
| <div class="flex justify-between mb-1"> | |
| <span class="text-sm font-medium text-gray-700">Progress</span> | |
| <span id="progress-percent" class="text-sm font-medium text-gray-700">0%</span> | |
| </div> | |
| <div class="w-full bg-gray-200 rounded-full h-2.5"> | |
| <div id="progress-bar" class="progress-bar bg-blue-600 h-2.5 rounded-full" style="width: 0%"></div> | |
| </div> | |
| </div> | |
| <div class="grid grid-cols-1 md:grid-cols-3 gap-4 text-center"> | |
| <div class="bg-blue-50 p-3 rounded-lg"> | |
| <div class="text-blue-500 mb-1"> | |
| <i class="fas fa-cogs text-xl"></i> | |
| </div> | |
| <p class="text-sm font-medium text-gray-700">Face Detection</p> | |
| <p id="detection-status" class="text-xs text-gray-500">Pending</p> | |
| </div> | |
| <div class="bg-blue-50 p-3 rounded-lg"> | |
| <div class="text-blue-500 mb-1"> | |
| <i class="fas fa-exchange-alt text-xl"></i> | |
| </div> | |
| <p class="text-sm font-medium text-gray-700">Face Swapping</p> | |
| <p id="swap-status" class="text-xs text-gray-500">Pending</p> | |
| </div> | |
| <div class="bg-blue-50 p-3 rounded-lg"> | |
| <div class="text-blue-500 mb-1"> | |
| <i class="fas fa-film text-xl"></i> | |
| </div> | |
| <p class="text-sm font-medium text-gray-700">Video Rendering</p> | |
| <p id="render-status" class="text-xs text-gray-500">Pending</p> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Result Preview (Hidden by default) --> | |
| <div id="result-preview" class="hidden mt-8"> | |
| <div class="flex justify-between items-center mb-4"> | |
| <h3 class="text-xl font-semibold text-gray-800">Your Face Swap Result</h3> | |
| <div class="flex space-x-2"> | |
| <button class="px-4 py-2 bg-blue-500 text-white rounded-lg hover:bg-blue-600 transition"> | |
| <i class="fas fa-download mr-2"></i>Download | |
| </button> | |
| <button class="px-4 py-2 border border-gray-300 text-gray-700 rounded-lg hover:bg-gray-50 transition"> | |
| <i class="fas fa-redo mr-2"></i>Try Again | |
| </button> | |
| </div> | |
| </div> | |
| <div class="bg-white p-4 rounded-xl shadow-md"> | |
| <div class="aspect-w-16 aspect-h-9 bg-black rounded-lg overflow-hidden"> | |
| <video controls class="w-full h-full"> | |
| <source src="" type="video/mp4"> | |
| Your browser does not support the video tag. | |
| </video> | |
| </div> | |
| <div class="mt-4 grid grid-cols-1 md:grid-cols-3 gap-4"> | |
| <div class="bg-gray-100 p-3 rounded-lg"> | |
| <p class="text-sm font-medium text-gray-700 mb-1">Original Video</p> | |
| <div class="aspect-w-16 aspect-h-9 bg-black rounded overflow-hidden"> | |
| <video class="w-full h-full object-cover"> | |
| <source src="" type="video/mp4"> | |
| </video> | |
| </div> | |
| </div> | |
| <div class="bg-gray-100 p-3 rounded-lg"> | |
| <p class="text-sm font-medium text-gray-700 mb-1">Source Face</p> | |
| <div class="aspect-w-16 aspect-h-9 bg-black rounded overflow-hidden"> | |
| <img src="" alt="Source face" class="w-full h-full object-cover"> | |
| </div> | |
| </div> | |
| <div class="bg-gray-100 p-3 rounded-lg"> | |
| <p class="text-sm font-medium text-gray-700 mb-1">Result Preview</p> | |
| <div class="aspect-w-16 aspect-h-9 bg-black rounded overflow-hidden"> | |
| <video class="w-full h-full object-cover"> | |
| <source src="" type="video/mp4"> | |
| </video> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| </main> | |
| <footer class="bg-gray-800 text-white py-8"> | |
| <div class="container mx-auto px-4"> | |
| <div class="grid grid-cols-1 md:grid-cols-4 gap-8"> | |
| <div> | |
| <h4 class="text-lg font-semibold mb-4">Video Face Swap</h4> | |
| <p class="text-gray-400">Swap faces in videos with our advanced AI technology. Simple, fast, and realistic results.</p> | |
| </div> | |
| <div> | |
| <h4 class="text-lg font-semibold mb-4">Quick Links</h4> | |
| <ul class="space-y-2"> | |
| <li><a href="#" class="text-gray-400 hover:text-white transition">Home</a></li> | |
| <li><a href="#" class="text-gray-400 hover:text-white transition">How it works</a></li> | |
| <li><a href="#" class="text-gray-400 hover:text-white transition">Pricing</a></li> | |
| <li><a href="#" class="text-gray-400 hover:text-white transition">Examples</a></li> | |
| </ul> | |
| </div> | |
| <div> | |
| <h4 class="text-lg font-semibold mb-4">Legal</h4> | |
| <ul class="space-y-2"> | |
| <li><a href="#" class="text-gray-400 hover:text-white transition">Terms of Service</a></li> | |
| <li><a href="#" class="text-gray-400 hover:text-white transition">Privacy Policy</a></li> | |
| <li><a href="#" class="text-gray-400 hover:text-white transition">Cookie Policy</a></li> | |
| </ul> | |
| </div> | |
| <div> | |
| <h4 class="text-lg font-semibold mb-4">Connect</h4> | |
| <div class="flex space-x-4"> | |
| <a href="#" class="w-10 h-10 bg-gray-700 rounded-full flex items-center justify-center hover:bg-blue-600 transition"> | |
| <i class="fab fa-facebook-f"></i> | |
| </a> | |
| <a href="#" class="w-10 h-10 bg-gray-700 rounded-full flex items-center justify-center hover:bg-blue-400 transition"> | |
| <i class="fab fa-twitter"></i> | |
| </a> | |
| <a href="#" class="w-10 h-10 bg-gray-700 rounded-full flex items-center justify-center hover:bg-pink-600 transition"> | |
| <i class="fab fa-instagram"></i> | |
| </a> | |
| <a href="#" class="w-10 h-10 bg-gray-700 rounded-full flex items-center justify-center hover:bg-red-600 transition"> | |
| <i class="fab fa-youtube"></i> | |
| </a> | |
| </div> | |
| </div> | |
| </div> | |
| <div class="border-t border-gray-700 mt-8 pt-6 text-center text-gray-400"> | |
| <p>© 2023 Video Face Swap. All rights reserved.</p> | |
| </div> | |
| </div> | |
| </footer> | |
| <script> | |
| document.addEventListener('DOMContentLoaded', function() { | |
| // Dropzone functionality | |
| const sourceDropzone = document.getElementById('source-dropzone'); | |
| const targetDropzone = document.getElementById('target-dropzone'); | |
| const sourceInput = document.getElementById('source-input'); | |
| const targetInput = document.getElementById('target-input'); | |
| const sourcePreview = document.getElementById('source-preview'); | |
| const targetPreview = document.getElementById('target-preview'); | |
| const processBtn = document.getElementById('process-btn'); | |
| const processingStatus = document.getElementById('processing-status'); | |
| const resultPreview = document.getElementById('result-preview'); | |
| // Handle drag and drop for source | |
| ['dragenter', 'dragover', 'dragleave', 'drop'].forEach(eventName => { | |
| sourceDropzone.addEventListener(eventName, preventDefaults, false); | |
| targetDropzone.addEventListener(eventName, preventDefaults, false); | |
| }); | |
| function preventDefaults(e) { | |
| e.preventDefault(); | |
| e.stopPropagation(); | |
| } | |
| ['dragenter', 'dragover'].forEach(eventName => { | |
| sourceDropzone.addEventListener(eventName, highlightSource, false); | |
| targetDropzone.addEventListener(eventName, highlightTarget, false); | |
| }); | |
| ['dragleave', 'drop'].forEach(eventName => { | |
| sourceDropzone.addEventListener(eventName, unhighlightSource, false); | |
| targetDropzone.addEventListener(eventName, unhighlightTarget, false); | |
| }); | |
| function highlightSource() { | |
| sourceDropzone.classList.add('active'); | |
| } | |
| function unhighlightSource() { | |
| sourceDropzone.classList.remove('active'); | |
| } | |
| function highlightTarget() { | |
| targetDropzone.classList.add('active'); | |
| } | |
| function unhighlightTarget() { | |
| targetDropzone.classList.remove('active'); | |
| } | |
| // Handle drop for source | |
| sourceDropzone.addEventListener('drop', handleDropSource, false); | |
| targetDropzone.addEventListener('drop', handleDropTarget, false); | |
| function handleDropSource(e) { | |
| const dt = e.dataTransfer; | |
| const files = dt.files; | |
| handleSourceFile(files[0]); | |
| } | |
| function handleDropTarget(e) { | |
| const dt = e.dataTransfer; | |
| const files = dt.files; | |
| handleTargetFile(files[0]); | |
| } | |
| // Handle click for source | |
| sourceDropzone.addEventListener('click', () => sourceInput.click()); | |
| targetDropzone.addEventListener('click', () => targetInput.click()); | |
| sourceInput.addEventListener('change', function() { | |
| if (this.files.length) { | |
| handleSourceFile(this.files[0]); | |
| } | |
| }); | |
| targetInput.addEventListener('change', function() { | |
| if (this.files.length) { | |
| handleTargetFile(this.files[0]); | |
| } | |
| }); | |
| // Clear buttons | |
| document.getElementById('clear-source').addEventListener('click', function(e) { | |
| e.stopPropagation(); | |
| sourcePreview.classList.add('hidden'); | |
| sourceInput.value = ''; | |
| }); | |
| document.getElementById('clear-target').addEventListener('click', function(e) { | |
| e.stopPropagation(); | |
| targetPreview.classList.add('hidden'); | |
| targetInput.value = ''; | |
| }); | |
| // Handle file preview | |
| function handleSourceFile(file) { | |
| const validImageTypes = ['image/jpeg', 'image/png', 'image/gif']; | |
| const validVideoTypes = ['video/mp4', 'video/webm', 'video/ogg']; | |
| if (!validImageTypes.includes(file.type) && !validVideoTypes.includes(file.type)) { | |
| alert('Please upload an image or video file'); | |
| return; | |
| } | |
| sourcePreview.classList.remove('hidden'); | |
| document.getElementById('source-filename').textContent = file.name; | |
| document.getElementById('source-filesize').textContent = formatFileSize(file.size); | |
| if (validImageTypes.includes(file.type)) { | |
| const reader = new FileReader(); | |
| reader.onload = function(e) { | |
| document.getElementById('source-thumbnail').src = e.target.result; | |
| }; | |
| reader.readAsDataURL(file); | |
| } else if (validVideoTypes.includes(file.type)) { | |
| // For video, we'll just show a generic thumbnail | |
| document.getElementById('source-thumbnail').src = 'https://via.placeholder.com/64x64?text=Video'; | |
| } | |
| } | |
| function handleTargetFile(file) { | |
| const validVideoTypes = ['video/mp4', 'video/webm', 'video/ogg']; | |
| if (!validVideoTypes.includes(file.type)) { | |
| alert('Please upload a video file'); | |
| return; | |
| } | |
| targetPreview.classList.remove('hidden'); | |
| document.getElementById('target-filename').textContent = file.name; | |
| document.getElementById('target-filesize').textContent = formatFileSize(file.size); | |
| const video = document.getElementById('target-thumbnail'); | |
| const fileURL = URL.createObjectURL(file); | |
| video.src = fileURL; | |
| // Generate thumbnail | |
| video.addEventListener('loadedmetadata', function() { | |
| video.currentTime = Math.min(1, video.duration); | |
| }); | |
| video.addEventListener('seeked', function() { | |
| const canvas = document.createElement('canvas'); | |
| canvas.width = video.videoWidth; | |
| canvas.height = video.videoHeight; | |
| const ctx = canvas.getContext('2d'); | |
| ctx.drawImage(video, 0, 0, canvas.width, canvas.height); | |
| document.getElementById('target-thumbnail').src = canvas.toDataURL('image/jpeg'); | |
| }); | |
| } | |
| 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(2)) + ' ' + sizes[i]; | |
| } | |
| // Process button click | |
| processBtn.addEventListener('click', function() { | |
| if (!sourceInput.files.length || !targetInput.files.length) { | |
| alert('Please upload both source face and target video'); | |
| return; | |
| } | |
| processingStatus.classList.remove('hidden'); | |
| resultPreview.classList.add('hidden'); | |
| // Simulate processing | |
| simulateProcessing(); | |
| }); | |
| function simulateProcessing() { | |
| let progress = 0; | |
| const progressBar = document.getElementById('progress-bar'); | |
| const progressPercent = document.getElementById('progress-percent'); | |
| const detectionStatus = document.getElementById('detection-status'); | |
| const swapStatus = document.getElementById('swap-status'); | |
| const renderStatus = document.getElementById('render-status'); | |
| const interval = setInterval(() => { | |
| progress += Math.random() * 10; | |
| if (progress > 100) progress = 100; | |
| progressBar.style.width = progress + '%'; | |
| progressPercent.textContent = Math.round(progress) + '%'; | |
| // Update statuses | |
| if (progress >= 30) detectionStatus.textContent = 'Completed'; | |
| if (progress >= 60) swapStatus.textContent = 'Completed'; | |
| if (progress >= 90) renderStatus.textContent = 'Completed'; | |
| if (progress >= 100) { | |
| clearInterval(interval); | |
| setTimeout(() => { | |
| processingStatus.classList.add('hidden'); | |
| resultPreview.classList.remove('hidden'); | |
| }, 1000); | |
| } | |
| }, 500); | |
| } | |
| }); | |
| </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=Rayan545454/f44ff444" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body> | |
| </html> |