Spaces:
Running
Running
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>VideoMerge Pro - Combine Videos in 4K</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 #6366f1; | |
| border-radius: 0.5rem; | |
| transition: all 0.3s ease; | |
| } | |
| .dropzone.active { | |
| border-color: #10b981; | |
| background-color: rgba(16, 185, 129, 0.05); | |
| } | |
| .video-preview { | |
| aspect-ratio: 16/9; | |
| background-color: #1e293b; | |
| } | |
| .progress-bar { | |
| height: 6px; | |
| transition: width 0.3s ease; | |
| } | |
| .timeline-track { | |
| height: 60px; | |
| background-color: #1e293b; | |
| overflow-x: auto; | |
| } | |
| .video-clip { | |
| min-width: 120px; | |
| height: 50px; | |
| background-color: #6366f1; | |
| border-radius: 4px; | |
| position: relative; | |
| } | |
| .clip-handle { | |
| width: 6px; | |
| height: 100%; | |
| background-color: rgba(255, 255, 255, 0.5); | |
| position: absolute; | |
| top: 0; | |
| cursor: ew-resize; | |
| } | |
| .clip-handle.left { | |
| left: 0; | |
| border-top-left-radius: 4px; | |
| border-bottom-left-radius: 4px; | |
| } | |
| .clip-handle.right { | |
| right: 0; | |
| border-top-right-radius: 4px; | |
| border-bottom-right-radius: 4px; | |
| } | |
| .settings-panel { | |
| transition: all 0.3s ease; | |
| max-height: 0; | |
| overflow: hidden; | |
| } | |
| .settings-panel.open { | |
| max-height: 500px; | |
| } | |
| </style> | |
| </head> | |
| <body class="bg-gray-900 text-gray-100 min-h-screen"> | |
| <div class="container mx-auto px-4 py-8"> | |
| <!-- Header --> | |
| <header class="mb-8"> | |
| <div class="flex items-center justify-between"> | |
| <div class="flex items-center space-x-2"> | |
| <i class="fas fa-film text-indigo-500 text-2xl"></i> | |
| <h1 class="text-2xl font-bold">VideoMerge <span class="text-indigo-500">Pro</span></h1> | |
| </div> | |
| <div> | |
| <button class="bg-indigo-600 hover:bg-indigo-700 text-white px-4 py-2 rounded-lg flex items-center space-x-2"> | |
| <i class="fas fa-user"></i> | |
| <span>Sign In</span> | |
| </button> | |
| </div> | |
| </div> | |
| <p class="text-gray-400 mt-2">Combine multiple videos seamlessly and export in stunning 4K quality</p> | |
| </header> | |
| <!-- Main Content --> | |
| <main> | |
| <!-- Upload Section --> | |
| <section class="mb-8"> | |
| <div class="dropzone p-8 text-center cursor-pointer" id="dropzone"> | |
| <div class="flex flex-col items-center justify-center space-y-4"> | |
| <i class="fas fa-cloud-upload-alt text-indigo-500 text-5xl"></i> | |
| <h2 class="text-xl font-semibold">Drag & Drop Video Files</h2> | |
| <p class="text-gray-400">or click to browse files (MP4, MOV, AVI supported)</p> | |
| <input type="file" id="fileInput" class="hidden" accept="video/*" multiple> | |
| <button id="browseBtn" class="bg-indigo-600 hover:bg-indigo-700 text-white px-6 py-2 rounded-lg"> | |
| Select Videos | |
| </button> | |
| </div> | |
| </div> | |
| </section> | |
| <!-- Video Timeline --> | |
| <section class="mb-8 bg-gray-800 rounded-lg p-4"> | |
| <div class="flex justify-between items-center mb-4"> | |
| <h3 class="text-lg font-semibold">Video Timeline</h3> | |
| <div class="flex space-x-2"> | |
| <button id="clearAllBtn" class="bg-gray-700 hover:bg-gray-600 text-white px-3 py-1 rounded"> | |
| <i class="fas fa-trash mr-1"></i> Clear All | |
| </button> | |
| <button id="addTransitionBtn" class="bg-indigo-600 hover:bg-indigo-700 text-white px-3 py-1 rounded"> | |
| <i class="fas fa-random mr-1"></i> Add Transition | |
| </button> | |
| </div> | |
| </div> | |
| <div class="timeline-track rounded p-2 mb-4" id="timeline"> | |
| <div class="flex space-x-2" id="videoClipsContainer"> | |
| <!-- Video clips will be added here dynamically --> | |
| <div class="text-gray-400 flex items-center justify-center w-full" id="emptyTimelineMessage"> | |
| <p>Add videos to start creating your timeline</p> | |
| </div> | |
| </div> | |
| </div> | |
| <div class="flex justify-between items-center"> | |
| <div class="text-sm text-gray-400"> | |
| <span id="totalDuration">Total Duration: 0:00</span> | |
| </div> | |
| <div> | |
| <button id="playAllBtn" class="bg-green-600 hover:bg-green-700 text-white px-4 py-2 rounded-lg mr-2"> | |
| <i class="fas fa-play mr-1"></i> Play All | |
| </button> | |
| <button id="previewBtn" class="bg-blue-600 hover:bg-blue-700 text-white px-4 py-2 rounded-lg"> | |
| <i class="fas fa-eye mr-1"></i> Preview | |
| </button> | |
| </div> | |
| </div> | |
| </section> | |
| <!-- Preview Section --> | |
| <section class="mb-8 bg-gray-800 rounded-lg p-4 hidden" id="previewSection"> | |
| <div class="flex justify-between items-center mb-4"> | |
| <h3 class="text-lg font-semibold">Preview</h3> | |
| <button id="closePreviewBtn" class="text-gray-400 hover:text-white"> | |
| <i class="fas fa-times"></i> | |
| </button> | |
| </div> | |
| <div class="video-preview rounded-lg overflow-hidden relative" id="previewVideo"> | |
| <video controls class="w-full h-full" id="mergedPreview"></video> | |
| <div class="absolute inset-0 flex items-center justify-center bg-black bg-opacity-50 hidden" id="previewOverlay"> | |
| <i class="fas fa-play text-white text-4xl"></i> | |
| </div> | |
| </div> | |
| </section> | |
| <!-- Export Settings --> | |
| <section class="mb-8 bg-gray-800 rounded-lg overflow-hidden"> | |
| <div class="p-4 cursor-pointer flex justify-between items-center" id="settingsToggle"> | |
| <h3 class="text-lg font-semibold"> | |
| <i class="fas fa-cog text-indigo-500 mr-2"></i> Export Settings | |
| </h3> | |
| <i class="fas fa-chevron-down text-gray-400 transition-transform" id="settingsChevron"></i> | |
| </div> | |
| <div class="settings-panel bg-gray-700" id="settingsPanel"> | |
| <div class="p-4 grid grid-cols-1 md:grid-cols-2 gap-6"> | |
| <!-- Resolution --> | |
| <div> | |
| <label class="block text-sm font-medium mb-2">Resolution</label> | |
| <div class="flex space-x-2"> | |
| <button class="resolution-btn px-3 py-1 rounded border border-gray-600 hover:bg-gray-600" data-resolution="720p">720p</button> | |
| <button class="resolution-btn px-3 py-1 rounded border border-gray-600 hover:bg-gray-600" data-resolution="1080p">1080p</button> | |
| <button class="resolution-btn px-3 py-1 rounded bg-indigo-600 border-indigo-600 text-white" data-resolution="4k">4K (3840x2160)</button> | |
| </div> | |
| </div> | |
| <!-- Frame Rate --> | |
| <div> | |
| <label class="block text-sm font-medium mb-2">Frame Rate</label> | |
| <div class="flex space-x-2"> | |
| <button class="fps-btn px-3 py-1 rounded border border-gray-600 hover:bg-gray-600" data-fps="24">24fps</button> | |
| <button class="fps-btn px-3 py-1 rounded bg-indigo-600 border-indigo-600 text-white" data-fps="30">30fps</button> | |
| <button class="fps-btn px-3 py-1 rounded border border-gray-600 hover:bg-gray-600" data-fps="60">60fps</button> | |
| </div> | |
| </div> | |
| <!-- Format --> | |
| <div> | |
| <label class="block text-sm font-medium mb-2">Format</label> | |
| <div class="flex space-x-2"> | |
| <button class="format-btn px-3 py-1 rounded bg-indigo-600 border-indigo-600 text-white" data-format="mp4">MP4</button> | |
| <button class="format-btn px-3 py-1 rounded border border-gray-600 hover:bg-gray-600" data-format="mov">MOV</button> | |
| <button class="format-btn px-3 py-1 rounded border border-gray-600 hover:bg-gray-600" data-format="avi">AVI</button> | |
| </div> | |
| </div> | |
| <!-- Quality --> | |
| <div> | |
| <label class="block text-sm font-medium mb-2">Quality</label> | |
| <div class="flex items-center space-x-2"> | |
| <input type="range" min="1" max="100" value="90" class="w-full" id="qualitySlider"> | |
| <span class="text-sm w-12 text-center" id="qualityValue">90%</span> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| </section> | |
| <!-- Export Button --> | |
| <section class="text-center"> | |
| <button id="exportBtn" class="bg-gradient-to-r from-purple-600 to-indigo-600 hover:from-purple-700 hover:to-indigo-700 text-white px-8 py-3 rounded-lg text-lg font-semibold shadow-lg"> | |
| <i class="fas fa-file-export mr-2"></i> Export Merged Video (4K 30fps) | |
| </button> | |
| </section> | |
| </main> | |
| <!-- Processing Modal --> | |
| <div class="fixed inset-0 bg-black bg-opacity-75 flex items-center justify-center z-50 hidden" id="processingModal"> | |
| <div class="bg-gray-800 rounded-lg p-6 max-w-md w-full"> | |
| <div class="flex justify-between items-center mb-4"> | |
| <h3 class="text-lg font-semibold">Processing Your Video</h3> | |
| <div class="text-sm text-gray-400" id="processingStep">Step 1/3: Preparing files</div> | |
| </div> | |
| <div class="w-full bg-gray-700 rounded-full h-2.5 mb-4"> | |
| <div class="progress-bar bg-indigo-600 rounded-full h-2.5" id="progressBar" style="width: 0%"></div> | |
| </div> | |
| <div class="text-center py-4"> | |
| <i class="fas fa-cog fa-spin text-indigo-500 text-4xl mb-3"></i> | |
| <p class="text-gray-300" id="processingMessage">Combining your videos and optimizing for 4K quality...</p> | |
| </div> | |
| <div class="text-right"> | |
| <button id="cancelProcessingBtn" class="text-gray-400 hover:text-white"> | |
| Cancel Processing | |
| </button> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Success Modal --> | |
| <div class="fixed inset-0 bg-black bg-opacity-75 flex items-center justify-center z-50 hidden" id="successModal"> | |
| <div class="bg-gray-800 rounded-lg p-6 max-w-md w-full text-center"> | |
| <div class="text-green-500 text-5xl mb-4"> | |
| <i class="fas fa-check-circle"></i> | |
| </div> | |
| <h3 class="text-xl font-semibold mb-2">Export Complete!</h3> | |
| <p class="text-gray-300 mb-6">Your 4K 30fps video is ready to download.</p> | |
| <div class="flex justify-center space-x-4"> | |
| <button id="downloadBtn" class="bg-green-600 hover:bg-green-700 text-white px-6 py-2 rounded-lg"> | |
| <i class="fas fa-download mr-2"></i> Download | |
| </button> | |
| <button id="newProjectBtn" class="bg-gray-700 hover:bg-gray-600 text-white px-6 py-2 rounded-lg"> | |
| <i class="fas fa-plus mr-2"></i> New Project | |
| </button> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <script> | |
| document.addEventListener('DOMContentLoaded', function() { | |
| // DOM Elements | |
| const dropzone = document.getElementById('dropzone'); | |
| const fileInput = document.getElementById('fileInput'); | |
| const browseBtn = document.getElementById('browseBtn'); | |
| const videoClipsContainer = document.getElementById('videoClipsContainer'); | |
| const emptyTimelineMessage = document.getElementById('emptyTimelineMessage'); | |
| const totalDuration = document.getElementById('totalDuration'); | |
| const clearAllBtn = document.getElementById('clearAllBtn'); | |
| const playAllBtn = document.getElementById('playAllBtn'); | |
| const previewBtn = document.getElementById('previewBtn'); | |
| const previewSection = document.getElementById('previewSection'); | |
| const closePreviewBtn = document.getElementById('closePreviewBtn'); | |
| const mergedPreview = document.getElementById('mergedPreview'); | |
| const previewOverlay = document.getElementById('previewOverlay'); | |
| const exportBtn = document.getElementById('exportBtn'); | |
| const processingModal = document.getElementById('processingModal'); | |
| const successModal = document.getElementById('successModal'); | |
| const progressBar = document.getElementById('progressBar'); | |
| const processingStep = document.getElementById('processingStep'); | |
| const processingMessage = document.getElementById('processingMessage'); | |
| const downloadBtn = document.getElementById('downloadBtn'); | |
| const newProjectBtn = document.getElementById('newProjectBtn'); | |
| const cancelProcessingBtn = document.getElementById('cancelProcessingBtn'); | |
| const settingsToggle = document.getElementById('settingsToggle'); | |
| const settingsPanel = document.getElementById('settingsPanel'); | |
| const settingsChevron = document.getElementById('settingsChevron'); | |
| const qualitySlider = document.getElementById('qualitySlider'); | |
| const qualityValue = document.getElementById('qualityValue'); | |
| // State | |
| let videoFiles = []; | |
| let totalDurationSeconds = 0; | |
| // Initialize settings panel | |
| settingsToggle.addEventListener('click', () => { | |
| settingsPanel.classList.toggle('open'); | |
| settingsChevron.classList.toggle('rotate-180'); | |
| }); | |
| // Quality slider | |
| qualitySlider.addEventListener('input', () => { | |
| qualityValue.textContent = `${qualitySlider.value}%`; | |
| }); | |
| // Dropzone functionality | |
| ['dragenter', 'dragover', 'dragleave', 'drop'].forEach(eventName => { | |
| dropzone.addEventListener(eventName, preventDefaults, false); | |
| }); | |
| function preventDefaults(e) { | |
| e.preventDefault(); | |
| e.stopPropagation(); | |
| } | |
| ['dragenter', 'dragover'].forEach(eventName => { | |
| dropzone.addEventListener(eventName, highlight, false); | |
| }); | |
| ['dragleave', 'drop'].forEach(eventName => { | |
| dropzone.addEventListener(eventName, unhighlight, false); | |
| }); | |
| function highlight() { | |
| dropzone.classList.add('active'); | |
| } | |
| function unhighlight() { | |
| dropzone.classList.remove('active'); | |
| } | |
| dropzone.addEventListener('drop', handleDrop, false); | |
| function handleDrop(e) { | |
| const dt = e.dataTransfer; | |
| const files = dt.files; | |
| handleFiles(files); | |
| } | |
| browseBtn.addEventListener('click', () => { | |
| fileInput.click(); | |
| }); | |
| fileInput.addEventListener('change', () => { | |
| handleFiles(fileInput.files); | |
| }); | |
| function handleFiles(files) { | |
| for (let i = 0; i < files.length; i++) { | |
| const file = files[i]; | |
| if (file.type.startsWith('video/')) { | |
| videoFiles.push(file); | |
| addVideoToTimeline(file); | |
| } | |
| } | |
| if (videoFiles.length > 0) { | |
| emptyTimelineMessage.classList.add('hidden'); | |
| updateTotalDuration(); | |
| } | |
| } | |
| function addVideoToTimeline(file) { | |
| const videoClip = document.createElement('div'); | |
| videoClip.className = 'video-clip flex-shrink-0 relative group'; | |
| videoClip.draggable = true; | |
| videoClip.dataset.filename = file.name; | |
| // Create video element to get duration | |
| const video = document.createElement('video'); | |
| video.src = URL.createObjectURL(file); | |
| video.onloadedmetadata = function() { | |
| const duration = video.duration; | |
| totalDurationSeconds += duration; | |
| updateTotalDuration(); | |
| // Set clip width based on duration (120px = 10 seconds) | |
| const width = Math.max(120, (duration / 10) * 120); | |
| videoClip.style.width = `${width}px`; | |
| // Add clip info | |
| const clipInfo = document.createElement('div'); | |
| clipInfo.className = 'absolute inset-0 flex items-center justify-center text-white text-xs font-medium truncate px-2'; | |
| clipInfo.textContent = `${file.name} (${formatDuration(duration)})`; | |
| videoClip.appendChild(clipInfo); | |
| // Add resize handles | |
| const leftHandle = document.createElement('div'); | |
| leftHandle.className = 'clip-handle left opacity-0 group-hover:opacity-100'; | |
| videoClip.appendChild(leftHandle); | |
| const rightHandle = document.createElement('div'); | |
| rightHandle.className = 'clip-handle right opacity-0 group-hover:opacity-100'; | |
| videoClip.appendChild(rightHandle); | |
| // Add drag and drop functionality | |
| videoClip.addEventListener('dragstart', handleDragStart); | |
| videoClip.addEventListener('dragover', handleDragOver); | |
| videoClip.addEventListener('drop', handleDropClip); | |
| }; | |
| videoClipsContainer.appendChild(videoClip); | |
| } | |
| function updateTotalDuration() { | |
| const minutes = Math.floor(totalDurationSeconds / 60); | |
| const seconds = Math.floor(totalDurationSeconds % 60); | |
| totalDuration.textContent = `Total Duration: ${minutes}:${seconds.toString().padStart(2, '0')}`; | |
| } | |
| function formatDuration(seconds) { | |
| const mins = Math.floor(seconds / 60); | |
| const secs = Math.floor(seconds % 60); | |
| return `${mins}:${secs.toString().padStart(2, '0')}`; | |
| } | |
| // Timeline functionality | |
| function handleDragStart(e) { | |
| e.dataTransfer.setData('text/plain', e.target.dataset.filename); | |
| e.target.classList.add('opacity-50'); | |
| } | |
| function handleDragOver(e) { | |
| e.preventDefault(); | |
| const afterElement = getDragAfterElement(videoClipsContainer, e.clientX); | |
| const draggable = document.querySelector('.dragging'); | |
| if (afterElement == null) { | |
| videoClipsContainer.appendChild(draggable); | |
| } else { | |
| videoClipsContainer.insertBefore(draggable, afterElement); | |
| } | |
| } | |
| function handleDropClip(e) { | |
| e.preventDefault(); | |
| e.target.classList.remove('opacity-50'); | |
| } | |
| function getDragAfterElement(container, x) { | |
| const draggableElements = [...container.querySelectorAll('.video-clip:not(.dragging)')]; | |
| return draggableElements.reduce((closest, child) => { | |
| const box = child.getBoundingClientRect(); | |
| const offset = x - box.left - box.width / 2; | |
| if (offset < 0 && offset > closest.offset) { | |
| return { offset: offset, element: child }; | |
| } else { | |
| return closest; | |
| } | |
| }, { offset: Number.NEGATIVE_INFINITY }).element; | |
| } | |
| // Clear all button | |
| clearAllBtn.addEventListener('click', () => { | |
| videoFiles = []; | |
| totalDurationSeconds = 0; | |
| videoClipsContainer.innerHTML = ''; | |
| emptyTimelineMessage.classList.remove('hidden'); | |
| updateTotalDuration(); | |
| }); | |
| // Preview functionality | |
| previewBtn.addEventListener('click', () => { | |
| if (videoFiles.length === 0) return; | |
| previewSection.classList.remove('hidden'); | |
| // In a real app, we would actually merge the videos here | |
| // For this demo, we'll just show the first video | |
| mergedPreview.src = URL.createObjectURL(videoFiles[0]); | |
| mergedPreview.load(); | |
| }); | |
| closePreviewBtn.addEventListener('click', () => { | |
| previewSection.classList.add('hidden'); | |
| mergedPreview.pause(); | |
| }); | |
| previewOverlay.addEventListener('click', () => { | |
| mergedPreview.play(); | |
| previewOverlay.classList.add('hidden'); | |
| }); | |
| mergedPreview.addEventListener('pause', () => { | |
| previewOverlay.classList.remove('hidden'); | |
| }); | |
| // Export functionality | |
| exportBtn.addEventListener('click', () => { | |
| if (videoFiles.length === 0) return; | |
| processingModal.classList.remove('hidden'); | |
| let progress = 0; | |
| const interval = setInterval(() => { | |
| progress += 5; | |
| progressBar.style.width = `${progress}%`; | |
| if (progress <= 30) { | |
| processingStep.textContent = 'Step 1/3: Preparing files'; | |
| processingMessage.textContent = 'Analyzing video files and preparing for merge...'; | |
| } else if (progress <= 70) { | |
| processingStep.textContent = 'Step 2/3: Merging videos'; | |
| processingMessage.textContent = 'Combining your videos and applying transitions...'; | |
| } else { | |
| processingStep.textContent = 'Step 3/3: Rendering 4K output'; | |
| processingMessage.textContent = 'Optimizing for 4K quality at 30fps...'; | |
| } | |
| if (progress >= 100) { | |
| clearInterval(interval); | |
| setTimeout(() => { | |
| processingModal.classList.add('hidden'); | |
| successModal.classList.remove('hidden'); | |
| }, 500); | |
| } | |
| }, 200); | |
| cancelProcessingBtn.addEventListener('click', () => { | |
| clearInterval(interval); | |
| processingModal.classList.add('hidden'); | |
| }, { once: true }); | |
| }); | |
| // Success modal buttons | |
| downloadBtn.addEventListener('click', () => { | |
| // In a real app, this would download the merged video | |
| alert('Download would start here in a real application'); | |
| }); | |
| newProjectBtn.addEventListener('click', () => { | |
| successModal.classList.add('hidden'); | |
| clearAllBtn.click(); | |
| }); | |
| // Resolution, FPS, and Format buttons | |
| document.querySelectorAll('.resolution-btn').forEach(btn => { | |
| btn.addEventListener('click', () => { | |
| document.querySelectorAll('.resolution-btn').forEach(b => { | |
| b.classList.remove('bg-indigo-600', 'border-indigo-600', 'text-white'); | |
| b.classList.add('border-gray-600', 'hover:bg-gray-600'); | |
| }); | |
| btn.classList.add('bg-indigo-600', 'border-indigo-600', 'text-white'); | |
| btn.classList.remove('border-gray-600', 'hover:bg-gray-600'); | |
| // Update export button text | |
| if (btn.dataset.resolution === '4k') { | |
| exportBtn.innerHTML = `<i class="fas fa-file-export mr-2"></i> Export Merged Video (4K 30fps)`; | |
| } else { | |
| exportBtn.innerHTML = `<i class="fas fa-file-export mr-2"></i> Export Merged Video (${btn.dataset.resolution.toUpperCase()} 30fps)`; | |
| } | |
| }); | |
| }); | |
| document.querySelectorAll('.fps-btn').forEach(btn => { | |
| btn.addEventListener('click', () => { | |
| document.querySelectorAll('.fps-btn').forEach(b => { | |
| b.classList.remove('bg-indigo-600', 'border-indigo-600', 'text-white'); | |
| b.classList.add('border-gray-600', 'hover:bg-gray-600'); | |
| }); | |
| btn.classList.add('bg-indigo-600', 'border-indigo-600', 'text-white'); | |
| btn.classList.remove('border-gray-600', 'hover:bg-gray-600'); | |
| }); | |
| }); | |
| document.querySelectorAll('.format-btn').forEach(btn => { | |
| btn.addEventListener('click', () => { | |
| document.querySelectorAll('.format-btn').forEach(b => { | |
| b.classList.remove('bg-indigo-600', 'border-indigo-600', 'text-white'); | |
| b.classList.add('border-gray-600', 'hover:bg-gray-600'); | |
| }); | |
| btn.classList.add('bg-indigo-600', 'border-indigo-600', 'text-white'); | |
| btn.classList.remove('border-gray-600', 'hover:bg-gray-600'); | |
| }); | |
| }); | |
| }); | |
| </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=tsbetterworkpmo/videomerger" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body> | |
| </html> |