Spaces:
Running
Running
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>YTDownloader - Free YouTube Video Downloader</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"> | |
| <script> | |
| tailwind.config = { | |
| darkMode: 'class', | |
| theme: { | |
| extend: { | |
| animation: { | |
| 'pulse-slow': 'pulse 3s cubic-bezier(0.4, 0, 0.6, 1) infinite', | |
| 'bounce-slow': 'bounce 2s infinite' | |
| }, | |
| colors: { | |
| primary: { | |
| light: '#FF0000', | |
| dark: '#FF3333' | |
| } | |
| } | |
| } | |
| } | |
| } | |
| </script> | |
| <style> | |
| .gradient-bg { | |
| background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%); | |
| } | |
| .dark .gradient-bg { | |
| background: linear-gradient(135deg, #1a1a2e 0%, #16213e 100%); | |
| } | |
| .video-card { | |
| transition: all 0.3s ease; | |
| } | |
| .video-card:hover { | |
| transform: translateY(-5px); | |
| box-shadow: 0 10px 25px rgba(0, 0, 0, 0.1); | |
| } | |
| .dark .video-card:hover { | |
| box-shadow: 0 10px 25px rgba(0, 0, 0, 0.3); | |
| } | |
| .loader { | |
| border-top-color: #FF0000; | |
| -webkit-animation: spinner 1.5s linear infinite; | |
| animation: spinner 1.5s linear infinite; | |
| } | |
| @-webkit-keyframes spinner { | |
| 0% { -webkit-transform: rotate(0deg); } | |
| 100% { -webkit-transform: rotate(360deg); } | |
| } | |
| @keyframes spinner { | |
| 0% { transform: rotate(0deg); } | |
| 100% { transform: rotate(360deg); } | |
| } | |
| </style> | |
| </head> | |
| <body class="gradient-bg min-h-screen transition-colors duration-300"> | |
| <div class="container mx-auto px-4 py-8"> | |
| <!-- Header --> | |
| <header class="flex justify-between items-center mb-10"> | |
| <div class="flex items-center"> | |
| <i class="fab fa-youtube text-4xl mr-3 text-primary-light dark:text-primary-dark"></i> | |
| <h1 class="text-3xl font-bold text-gray-800 dark:text-white"> | |
| <span class="text-primary-light dark:text-primary-dark">YT</span>Downloader | |
| </h1> | |
| </div> | |
| <button id="themeToggle" class="p-2 rounded-full bg-gray-200 dark:bg-gray-700 text-gray-700 dark:text-gray-200"> | |
| <i class="fas fa-moon dark:hidden"></i> | |
| <i class="fas fa-sun hidden dark:block"></i> | |
| </button> | |
| </header> | |
| <!-- Main Content --> | |
| <main> | |
| <div class="max-w-3xl mx-auto"> | |
| <!-- Search Box --> | |
| <div class="bg-white dark:bg-gray-800 rounded-xl shadow-lg p-6 mb-8 transition-all duration-300 hover:shadow-xl"> | |
| <h2 class="text-xl font-semibold mb-4 text-gray-800 dark:text-white">Download YouTube Videos</h2> | |
| <div class="flex flex-col md:flex-row gap-4"> | |
| <input | |
| type="text" | |
| id="videoUrl" | |
| placeholder="Paste YouTube or YouTube Music URL here..." | |
| class="flex-grow px-4 py-3 rounded-lg border border-gray-300 dark:border-gray-600 focus:outline-none focus:ring-2 focus:ring-primary-light dark:focus:ring-primary-dark bg-white dark:bg-gray-700 text-gray-800 dark:text-white" | |
| > | |
| <button | |
| id="downloadBtn" | |
| class="px-6 py-3 bg-primary-light dark:bg-primary-dark text-white rounded-lg font-medium hover:opacity-90 transition-opacity flex items-center justify-center" | |
| > | |
| <i class="fas fa-download mr-2"></i> Download | |
| </button> | |
| </div> | |
| <p class="text-sm text-gray-500 dark:text-gray-400 mt-3">Supports YouTube & YouTube Music - All formats: MP4, WEBM, 3GP, MP3 and more</p> | |
| </div> | |
| <!-- How It Works --> | |
| <div class="bg-white dark:bg-gray-800 rounded-xl shadow-lg p-6 mb-8"> | |
| <h2 class="text-xl font-semibold mb-4 text-gray-800 dark:text-white">How to Download</h2> | |
| <div class="grid grid-cols-1 md:grid-cols-3 gap-6"> | |
| <div class="flex flex-col items-center text-center"> | |
| <div class="w-16 h-16 bg-blue-100 dark:bg-blue-900 rounded-full flex items-center justify-center mb-3"> | |
| <i class="fas fa-link text-blue-600 dark:text-blue-300 text-2xl"></i> | |
| </div> | |
| <h3 class="font-medium text-gray-800 dark:text-white mb-1">1. Paste URL</h3> | |
| <p class="text-gray-600 dark:text-gray-400 text-sm">Copy and paste the YouTube video URL</p> | |
| </div> | |
| <div class="flex flex-col items-center text-center"> | |
| <div class="w-16 h-16 bg-purple-100 dark:bg-purple-900 rounded-full flex items-center justify-center mb-3"> | |
| <i class="fas fa-cog text-purple-600 dark:text-purple-300 text-2xl"></i> | |
| </div> | |
| <h3 class="font-medium text-gray-800 dark:text-white mb-1">2. Process</h3> | |
| <p class="text-gray-600 dark:text-gray-400 text-sm">Our system will analyze the video</p> | |
| </div> | |
| <div class="flex flex-col items-center text-center"> | |
| <div class="w-16 h-16 bg-green-100 dark:bg-green-900 rounded-full flex items-center justify-center mb-3"> | |
| <i class="fas fa-download text-green-600 dark:text-green-300 text-2xl"></i> | |
| </div> | |
| <h3 class="font-medium text-gray-800 dark:text-white mb-1">3. Download</h3> | |
| <p class="text-gray-600 dark:text-gray-400 text-sm">Choose format and download</p> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Results Section (Initially Hidden) --> | |
| <div id="resultsSection" class="hidden bg-white dark:bg-gray-800 rounded-xl shadow-lg p-6 mb-8"> | |
| <div class="flex justify-between items-center mb-4"> | |
| <h2 class="text-xl font-semibold text-gray-800 dark:text-white">Download Options</h2> | |
| <button id="newDownloadBtn" class="text-sm text-primary-light dark:text-primary-dark hover:underline"> | |
| <i class="fas fa-redo mr-1"></i> New Download | |
| </button> | |
| </div> | |
| <!-- Video Info --> | |
| <div id="videoInfo" class="flex flex-col md:flex-row gap-4 mb-6"> | |
| <div class="w-full md:w-1/3"> | |
| <div class="relative pb-[56.25%] bg-gray-200 dark:bg-gray-700 rounded-lg overflow-hidden"> | |
| <img id="videoThumbnail" src="" alt="Video thumbnail" class="absolute h-full w-full object-cover"> | |
| <div class="absolute inset-0 flex items-center justify-center bg-black bg-opacity-30"> | |
| <i class="fab fa-youtube text-5xl text-white opacity-80"></i> | |
| </div> | |
| </div> | |
| </div> | |
| <div class="w-full md:w-2/3"> | |
| <h3 id="videoTitle" class="text-lg font-medium text-gray-800 dark:text-white mb-2"></h3> | |
| <p id="videoDuration" class="text-sm text-gray-600 dark:text-gray-400 mb-3"></p> | |
| <div class="flex flex-wrap gap-2"> | |
| <span id="videoViews" class="px-3 py-1 bg-gray-100 dark:bg-gray-700 rounded-full text-xs text-gray-800 dark:text-gray-300"></span> | |
| <span id="videoUploadDate" class="px-3 py-1 bg-gray-100 dark:bg-gray-700 rounded-full text-xs text-gray-800 dark:text-gray-300"></span> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Loading State --> | |
| <div id="loadingState" class="flex flex-col items-center justify-center py-8"> | |
| <div class="loader ease-linear rounded-full border-4 border-t-4 border-gray-200 h-12 w-12 mb-4"></div> | |
| <p class="text-gray-600 dark:text-gray-400">Processing video, please wait...</p> | |
| </div> | |
| <!-- Download Options --> | |
| <div id="downloadOptions" class="hidden"> | |
| <div class="mb-4"> | |
| <div class="flex items-center mb-2"> | |
| <h3 class="font-medium text-gray-800 dark:text-white">Video Formats</h3> | |
| <span class="ml-2 px-2 py-1 bg-gray-100 dark:bg-gray-700 rounded-full text-xs text-gray-800 dark:text-gray-300">MP4</span> | |
| </div> | |
| <div class="grid grid-cols-1 md:grid-cols-2 gap-3 mb-4" id="videoFormats"> | |
| <!-- Dynamically populated --> | |
| </div> | |
| </div> | |
| <div> | |
| <div class="flex items-center mb-2"> | |
| <h3 class="font-medium text-gray-800 dark:text-white">Audio Only</h3> | |
| <span class="ml-2 px-2 py-1 bg-gray-100 dark:bg-gray-700 rounded-full text-xs text-gray-800 dark:text-gray-300">MP3</span> | |
| </div> | |
| <div class="grid grid-cols-1 md:grid-cols-2 gap-3" id="audioFormats"> | |
| <!-- Dynamically populated --> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Features --> | |
| <div class="bg-white dark:bg-gray-800 rounded-xl shadow-lg p-6"> | |
| <h2 class="text-xl font-semibold mb-4 text-gray-800 dark:text-white">Why Choose Us?</h2> | |
| <div class="space-y-4"> | |
| <div class="flex items-start"> | |
| <div class="flex-shrink-0 mt-1"> | |
| <div class="w-8 h-8 bg-primary-light dark:bg-primary-dark rounded-full flex items-center justify-center"> | |
| <i class="fas fa-bolt text-white text-sm"></i> | |
| </div> | |
| </div> | |
| <div class="ml-3"> | |
| <h3 class="font-medium text-gray-800 dark:text-white">Fast Downloads</h3> | |
| <p class="text-gray-600 dark:text-gray-400 text-sm">Our servers provide high-speed downloads for all your videos.</p> | |
| </div> | |
| </div> | |
| <div class="flex items-start"> | |
| <div class="flex-shrink-0 mt-1"> | |
| <div class="w-8 h-8 bg-primary-light dark:bg-primary-dark rounded-full flex items-center justify-center"> | |
| <i class="fas fa-lock text-white text-sm"></i> | |
| </div> | |
| </div> | |
| <div class="ml-3"> | |
| <h3 class="font-medium text-gray-800 dark:text-white">Secure & Private</h3> | |
| <p class="text-gray-600 dark:text-gray-400 text-sm">We don't store your videos or track your downloads.</p> | |
| </div> | |
| </div> | |
| <div class="flex items-start"> | |
| <div class="flex-shrink-0 mt-1"> | |
| <div class="w-8 h-8 bg-primary-light dark:bg-primary-dark rounded-full flex items-center justify-center"> | |
| <i class="fas fa-mobile-alt text-white text-sm"></i> | |
| </div> | |
| </div> | |
| <div class="ml-3"> | |
| <h3 class="font-medium text-gray-800 dark:text-white">All Devices Supported</h3> | |
| <p class="text-gray-600 dark:text-gray-400 text-sm">Download videos compatible with any device or platform.</p> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| </main> | |
| <!-- Footer --> | |
| <footer class="mt-16 text-center text-gray-600 dark:text-gray-400 text-sm"> | |
| <p>© 2023 YTDownloader. All rights reserved.</p> | |
| <p class="mt-1">This service is for educational purposes only.</p> | |
| </footer> | |
| </div> | |
| <script> | |
| // Theme toggle | |
| const themeToggle = document.getElementById('themeToggle'); | |
| themeToggle.addEventListener('click', () => { | |
| document.documentElement.classList.toggle('dark'); | |
| localStorage.setItem('darkMode', document.documentElement.classList.contains('dark')); | |
| }); | |
| // Check for saved theme preference | |
| if (localStorage.getItem('darkMode') === 'true') { | |
| document.documentElement.classList.add('dark'); | |
| } | |
| // Mock download functionality (in a real app, this would connect to a backend service) | |
| const downloadBtn = document.getElementById('downloadBtn'); | |
| const videoUrl = document.getElementById('videoUrl'); | |
| const resultsSection = document.getElementById('resultsSection'); | |
| const loadingState = document.getElementById('loadingState'); | |
| const downloadOptions = document.getElementById('downloadOptions'); | |
| const newDownloadBtn = document.getElementById('newDownloadBtn'); | |
| const videoInfo = document.getElementById('videoInfo'); | |
| const videoTitle = document.getElementById('videoTitle'); | |
| const videoThumbnail = document.getElementById('videoThumbnail'); | |
| const videoDuration = document.getElementById('videoDuration'); | |
| const videoViews = document.getElementById('videoViews'); | |
| const videoUploadDate = document.getElementById('videoUploadDate'); | |
| const videoFormats = document.getElementById('videoFormats'); | |
| const audioFormats = document.getElementById('audioFormats'); | |
| downloadBtn.addEventListener('click', () => { | |
| const url = videoUrl.value.trim(); | |
| // Basic URL validation | |
| if (!url || (!url.includes('youtube.com') && !url.includes('youtu.be') && !url.includes('music.youtube.com'))) { | |
| alert('Please enter a valid YouTube URL'); | |
| return; | |
| } | |
| // Show loading state | |
| resultsSection.classList.remove('hidden'); | |
| loadingState.classList.remove('hidden'); | |
| downloadOptions.classList.add('hidden'); | |
| videoInfo.classList.add('hidden'); | |
| // Simulate API call delay | |
| setTimeout(() => { | |
| // Mock data - in a real app, this would come from your backend | |
| const videoData = { | |
| title: "How to Build a YouTube Downloader", | |
| thumbnail: "https://i.ytimg.com/vi/dQw4w9WgXcQ/maxresdefault.jpg", | |
| duration: "12:34", | |
| views: "1.2M views", | |
| uploadDate: "Uploaded 2 weeks ago", | |
| formats: [ | |
| { quality: "1080p", type: "MP4", size: "45.2 MB", url: "#" }, | |
| { quality: "720p", type: "MP4", size: "28.7 MB", url: "#" }, | |
| { quality: "480p", type: "MP4", size: "15.3 MB", url: "#" }, | |
| { quality: "360p", type: "MP4", size: "9.8 MB", url: "#" }, | |
| { quality: "144p", type: "MP4", size: "3.2 MB", url: "#" }, | |
| { quality: "High", type: "MP3", size: "5.6 MB", url: "#" }, | |
| { quality: "Medium", type: "MP3", size: "3.8 MB", url: "#" }, | |
| { quality: "Low", type: "MP3", size: "2.1 MB", url: "#" } | |
| ] | |
| }; | |
| // Populate video info | |
| videoTitle.textContent = videoData.title; | |
| videoThumbnail.src = videoData.thumbnail; | |
| videoDuration.textContent = videoData.duration; | |
| videoViews.textContent = videoData.views; | |
| videoUploadDate.textContent = videoData.uploadDate; | |
| // Populate video formats | |
| videoFormats.innerHTML = ''; | |
| audioFormats.innerHTML = ''; | |
| videoData.formats.forEach(format => { | |
| const formatElement = document.createElement('div'); | |
| formatElement.className = 'video-card bg-gray-50 dark:bg-gray-700 p-4 rounded-lg'; | |
| const isAudio = format.type === 'MP3'; | |
| const icon = isAudio ? 'fas fa-music' : 'fas fa-video'; | |
| const bgColor = isAudio ? 'bg-purple-100 dark:bg-purple-900' : 'bg-blue-100 dark:bg-blue-900'; | |
| const textColor = isAudio ? 'text-purple-600 dark:text-purple-300' : 'text-blue-600 dark:text-blue-300'; | |
| formatElement.innerHTML = ` | |
| <div class="flex items-center justify-between"> | |
| <div class="flex items-center"> | |
| <div class="w-10 h-10 ${bgColor} rounded-full flex items-center justify-center mr-3"> | |
| <i class="${icon} ${textColor}"></i> | |
| </div> | |
| <div> | |
| <h4 class="font-medium text-gray-800 dark:text-white">${format.quality}</h4> | |
| <p class="text-xs text-gray-600 dark:text-gray-400">${format.type} • ${format.size}</p> | |
| </div> | |
| </div> | |
| <a href="${format.url}" class="px-3 py-1 bg-primary-light dark:bg-primary-dark text-white text-sm rounded hover:opacity-90 transition-opacity"> | |
| Download | |
| </a> | |
| </div> | |
| `; | |
| if (isAudio) { | |
| audioFormats.appendChild(formatElement); | |
| } else { | |
| videoFormats.appendChild(formatElement); | |
| } | |
| }); | |
| // Hide loading, show results | |
| loadingState.classList.add('hidden'); | |
| videoInfo.classList.remove('hidden'); | |
| downloadOptions.classList.remove('hidden'); | |
| }, 2000); | |
| }); | |
| // New download button | |
| newDownloadBtn.addEventListener('click', () => { | |
| resultsSection.classList.add('hidden'); | |
| videoUrl.value = ''; | |
| }); | |
| // Example URLs for demo purposes | |
| videoUrl.addEventListener('focus', () => { | |
| if (!videoUrl.value) { | |
| videoUrl.value = 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'; | |
| } | |
| }); | |
| </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=AgentP23/yt-downloader" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body> | |
| </html> |