f44ff444 / index.html
Rayan545454's picture
tonyassi/video-face-swap - Initial Deployment
366993d verified
<!DOCTYPE html>
<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>&copy; 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>