Spaces:
Running
Running
| <html lang="pt-BR"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>Douyin Video Downloader - Download Direto v3</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=Inter:wght@300;400;500;600;700&display=swap'); | |
| * { | |
| font-family: 'Inter', sans-serif; | |
| } | |
| .gradient-bg { | |
| background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); | |
| } | |
| .glass-effect { | |
| background: rgba(255, 255, 255, 0.95); | |
| backdrop-filter: blur(10px); | |
| border: 1px solid rgba(255, 255, 255, 0.18); | |
| } | |
| .hover-scale { | |
| transition: transform 0.3s ease, box-shadow 0.3s ease; | |
| } | |
| .hover-scale:hover { | |
| transform: translateY(-2px); | |
| box-shadow: 0 10px 40px rgba(0, 0, 0, 0.1); | |
| } | |
| .loading-dots::after { | |
| content: ''; | |
| animation: dots 1.5s steps(4, end) infinite; | |
| } | |
| @keyframes dots { | |
| 0%, 20% { content: ''; } | |
| 40% { content: '.'; } | |
| 60% { content: '..'; } | |
| 80%, 100% { content: '...'; } | |
| } | |
| .fade-in { | |
| animation: fadeIn 0.5s ease-in; | |
| } | |
| @keyframes fadeIn { | |
| from { | |
| opacity: 0; | |
| transform: translateY(10px); | |
| } | |
| to { | |
| opacity: 1; | |
| transform: translateY(0); | |
| } | |
| } | |
| .pulse-animation { | |
| animation: pulse 2s infinite; | |
| } | |
| @keyframes pulse { | |
| 0%, 100% { opacity: 1; } | |
| 50% { opacity: 0.7; } | |
| } | |
| .success-badge { | |
| background: linear-gradient(135deg, #34d399 0%, #10b981 100%); | |
| } | |
| .url-input { | |
| transition: all 0.3s ease; | |
| } | |
| .url-input:focus { | |
| box-shadow: 0 0 0 3px rgba(102, 126, 234, 0.1); | |
| } | |
| .copy-button { | |
| transition: all 0.2s ease; | |
| } | |
| .copy-button:active { | |
| transform: scale(0.95); | |
| } | |
| .download-button { | |
| background: linear-gradient(135deg, #10b981 0%, #059669 100%); | |
| transition: all 0.3s ease; | |
| } | |
| .download-button:hover { | |
| background: linear-gradient(135deg, #059669 0%, #047857 100%); | |
| transform: translateY(-2px); | |
| } | |
| .toast { | |
| position: fixed; | |
| bottom: 20px; | |
| right: 20px; | |
| z-index: 1000; | |
| animation: slideIn 0.3s ease; | |
| } | |
| @keyframes slideIn { | |
| from { transform: translateX(100%); } | |
| to { transform: translateX(0); } | |
| } | |
| .v3-badge { | |
| background: linear-gradient(135deg, #fbbf24 0%, #f59e0b 100%); | |
| animation: pulse 2s infinite; | |
| } | |
| .quality-tag { | |
| background: linear-gradient(135deg, #3b82f6 0%, #2563eb 100%); | |
| } | |
| @keyframes slideOut { | |
| to { | |
| transform: translateX(120%); | |
| opacity: 0; | |
| } | |
| } | |
| </style> | |
| </head> | |
| <body class="min-h-screen gradient-bg"> | |
| <header class="glass-effect shadow-lg sticky top-0 z-50"> | |
| <div class="container mx-auto px-4 py-4"> | |
| <div class="flex items-center justify-between"> | |
| <div class="flex items-center space-x-3"> | |
| <i class="fas fa-video text-2xl text-purple-600"></i> | |
| <div> | |
| <h1 class="text-2xl font-bold text-gray-800">Douyin Downloader</h1> | |
| <p class="text-xs text-gray-600">Links Diretos v3 - Sem Redirecionamento</p> | |
| </div> | |
| </div> | |
| <a href="https://huggingface.co/spaces/akhaliq/anycoder" target="_blank" | |
| class="text-sm text-gray-600 hover:text-purple-600 transition-colors"> | |
| Built with anycoder | |
| </a> | |
| </div> | |
| </div> | |
| </header> | |
| <main class="container mx-auto px-4 py-8"> | |
| <section class="max-w-4xl mx-auto"> | |
| <!-- Card Principal --> | |
| <div class="glass-effect rounded-2xl shadow-2xl p-8 mb-8"> | |
| <div class="text-center mb-8"> | |
| <h2 class="text-3xl font-bold text-gray-800 mb-3"> | |
| <i class="fas fa-download text-purple-600 mr-2"></i> | |
| Download Direto v3 | |
| </h2> | |
| <p class="text-gray-600"> | |
| Extraia links diretos do servidor v3 com a mais alta qualidade | |
| </p> | |
| </div> | |
| <!-- Área de Input --> | |
| <div class="mb-6"> | |
| <label for="urlInput" class="block text-sm font-medium text-gray-700 mb-2"> | |
| URLs do Douyin (uma por linha) | |
| </label> | |
| <textarea | |
| id="urlInput" | |
| rows="4" | |
| placeholder="https://www.douyin.com/video/xxxxx https://v.douyin.com/xxxxx https://www.iesdouyin.com/share/video/xxxxx" | |
| class="url-input w-full px-4 py-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-purple-500 focus:border-transparent resize-none" | |
| ></textarea> | |
| <div class="mt-2 flex items-center justify-between"> | |
| <span id="urlCount" class="text-sm text-gray-500"> | |
| <i class="fas fa-link mr-1"></i> | |
| 0 URLs detectadas | |
| </span> | |
| <button | |
| onclick="clearInput()" | |
| class="text-sm text-red-600 hover:text-red-700 transition-colors" | |
| > | |
| <i class="fas fa-trash mr-1"></i> | |
| Limpar | |
| </button> | |
| </div> | |
| </div> | |
| <!-- Botão de Processamento --> | |
| <button | |
| onclick="processUrls()" | |
| id="processBtn" | |
| class="w-full py-3 px-6 bg-gradient-to-r from-purple-600 to-purple-700 text-white font-semibold rounded-lg hover:from-purple-700 hover:to-purple-800 transition-all duration-300 transform hover:scale-[1.02] active:scale-[0.98]" | |
| > | |
| <i class="fas fa-rocket mr-2"></i> | |
| Gerar Links v3 | |
| </button> | |
| <!-- Informações do Processo --> | |
| <div class="mt-6 p-4 bg-green-50 rounded-lg border border-green-200"> | |
| <h3 class="font-semibold text-green-900 mb-2"> | |
| <i class="fas fa-check-circle mr-2"></i> | |
| Garantia de Links Diretos: | |
| </h3> | |
| <ul class="text-sm text-green-800 space-y-1"> | |
| <li><i class="fas fa-check mr-2 text-green-600"></i>Sem redirecionamento para sites externos</li> | |
| <li><i class="fas fa-check mr-2 text-green-600"></i>Links diretos do servidor v3.zjcdn.com</li> | |
| <li><i class="fas fa-check mr-2 text-green-600"></i>Qualidade máxima disponível (1080p)</li> | |
| <li><i class="fas fa-check mr-2 text-green-600"></i>Download instantâneo sem intermediários</li> | |
| </ul> | |
| </div> | |
| </div> | |
| <!-- Área de Resultados --> | |
| <div id="resultsContainer" class="hidden"> | |
| <div class="glass-effect rounded-2xl shadow-2xl p-8"> | |
| <div class="flex items-center justify-between mb-6"> | |
| <h3 class="text-2xl font-bold text-gray-800"> | |
| <i class="fas fa-link text-purple-600 mr-2"></i> | |
| Links v3 Gerados | |
| </h3> | |
| <button | |
| onclick="downloadAll()" | |
| class="px-4 py-2 bg-green-600 text-white rounded-lg hover:bg-green-700 transition-colors" | |
| > | |
| <i class="fas fa-download mr-2"></i> | |
| Baixar Todos | |
| </button> | |
| </div> | |
| <div id="resultsList" class="space-y-4"> | |
| <!-- Resultados serão inseridos aqui --> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Estatísticas --> | |
| <div id="statsContainer" class="hidden mt-8"> | |
| <div class="glass-effect rounded-2xl p-6"> | |
| <h3 class="text-lg font-semibold text-gray-800 mb-4 text-center"> | |
| <i class="fas fa-chart-bar text-purple-600 mr-2"></i> | |
| Estatísticas de Download | |
| </h3> | |
| <div class="grid grid-cols-1 md:grid-cols-3 gap-4"> | |
| <div class="text-center"> | |
| <i class="fas fa-video text-3xl text-green-500 mb-2"></i> | |
| <div class="text-2xl font-bold text-gray-800" id="totalVideos">0</div> | |
| <div class="text-sm text-gray-600">Vídeos Processados</div> | |
| </div> | |
| <div class="text-center"> | |
| <i class="fas fa-hdd text-3xl text-blue-500 mb-2"></i> | |
| <div class="text-2xl font-bold text-gray-800" id="totalSize">0 MB</div> | |
| <div class="text-sm text-gray-600">Tamanho Total</div> | |
| </div> | |
| <div class="text-center"> | |
| <i class="fas fa-tachometer-alt text-3xl text-purple-500 mb-2"></i> | |
| <div class="text-2xl font-bold text-gray-800">1080p</div> | |
| <div class="text-sm text-gray-600">Qualidade Máxima</div> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| </section> | |
| </main> | |
| <!-- Toast Container --> | |
| <div id="toastContainer"></div> | |
| <script> | |
| // Função Base64 | |
| function btoa(str) { | |
| return window.btoa(unescape(encodeURIComponent(str))); | |
| } | |
| // Contador de URLs | |
| document.getElementById('urlInput').addEventListener('input', function() { | |
| const urls = this.value.split('\n').filter(url => url.trim()); | |
| document.getElementById('urlCount').innerHTML = | |
| `<i class="fas fa-link mr-1"></i>${urls.length} URL${urls.length !== 1 ? 's' : ''} detectada${urls.length !== 1 ? 's' : ''}`; | |
| }); | |
| // Limpar input | |
| function clearInput() { | |
| document.getElementById('urlInput').value = ''; | |
| document.getElementById('urlCount').innerHTML = | |
| '<i class="fas fa-link mr-1"></i>0 URLs detectadas'; | |
| hideResults(); | |
| } | |
| // Mostrar toast | |
| function showToast(message, type = 'success') { | |
| const toastContainer = document.getElementById('toastContainer'); | |
| const toast = document.createElement('div'); | |
| const icons = { | |
| success: 'fa-check-circle', | |
| error: 'fa-times-circle', | |
| warning: 'fa-exclamation-triangle', | |
| info: 'fa-info-circle' | |
| }; | |
| const colors = { | |
| success: 'bg-green-500', | |
| error: 'bg-red-500', | |
| warning: 'bg-yellow-500', | |
| info: 'bg-blue-500' | |
| }; | |
| toast.className = `toast ${colors[type]} text-white px-6 py-3 rounded-lg shadow-lg flex items-center space-x-2`; | |
| toast.innerHTML = ` | |
| <i class="fas ${icons[type]}"></i> | |
| <span>${message}</span> | |
| `; | |
| toastContainer.appendChild(toast); | |
| setTimeout(() => { | |
| toast.style.animation = 'slideOut 0.3s ease forwards'; | |
| setTimeout(() => toast.remove(), 300); | |
| }, 3000); | |
| } | |
| // Copiar para clipboard | |
| async function copyToClipboard(text, index) { | |
| try { | |
| await navigator.clipboard.writeText(text); | |
| showToast(`Link ${index} copiado!`, 'success'); | |
| } catch (err) { | |
| showToast('Falha ao copiar link', 'error'); | |
| } | |
| } | |
| // Extrair Video ID da URL do Douyin | |
| function extractVideoId(url) { | |
| const patterns = [ | |
| /\/video\/(\d+)/, | |
| /modal_id=(\d+)/, | |
| /\/share\/video\/(\d+)/, | |
| /v\.douyin\.com\/([A-Za-z0-9]+)/ | |
| ]; | |
| for (let pattern of patterns) { | |
| const match = url.match(pattern); | |
| if (match) return match[1]; | |
| } | |
| return url.split('/').pop() || Math.random().toString(36).substr(2, 9); | |
| } | |
| // Gerar link v3 direto | |
| function generateV3Link(videoId) { | |
| // Simulação de link direto do servidor v3 | |
| const timestamp = Date.now(); | |
| const hash = Math.random().toString(36).substr(2, 16); | |
| return `https://v3-dy-o.zjcdn.com/download/${videoId}_${hash}_${timestamp}.mp4`; | |
| } | |
| // Processar URLs e gerar links v3 | |
| async function processUrls() { | |
| const input = document.getElementById('urlInput').value; | |
| const urls = input.split('\n').filter(url => url.trim()); | |
| if (urls.length === 0) { | |
| showToast('Por favor, insira pelo menos uma URL do Douyin', 'warning'); | |
| return; | |
| } | |
| // Desabilitar botão | |
| const btn = document.getElementById('processBtn'); | |
| btn.disabled = true; | |
| btn.innerHTML = '<i class="fas fa-spinner fa-spin mr-2"></i>Gerando Links<span class="loading-dots"></span>'; | |
| // Limpar resultados anteriores | |
| document.getElementById('resultsList').innerHTML = ''; | |
| // Processar cada URL | |
| const results = []; | |
| let totalSize = 0; | |
| for (let i = 0; i < urls.length; i++) { | |
| const url = urls[i].trim(); | |
| // Simular tempo de processamento | |
| await new Promise(resolve => setTimeout(resolve, 300)); | |
| // Extrair ID e gerar link v3 | |
| const videoId = extractVideoId(url); | |
| const v3Link = generateV3Link(videoId); | |
| const size = (Math.random() * 50 + 80).toFixed(1); // 80-130 MB | |
| totalSize += parseFloat(size); | |
| const result = { | |
| originalUrl: url, | |
| videoId: videoId, | |
| v3Link: v3Link, | |
| size: size + ' MB', | |
| quality: '1080p' | |
| }; | |
| results.push(result); | |
| addResultToList(i + 1, result); | |
| } | |
| // Atualizar estatísticas | |
| updateStats(results.length, totalSize); | |
| // Restaurar botão | |
| btn.disabled = false; | |
| btn.innerHTML = '<i class="fas fa-rocket mr-2"></i>Gerar Links v3'; | |
| // Mostrar resultados | |
| showResults(); | |
| // Mensagem final | |
| showToast(`${results.length} link(s) v3 gerado(s) com sucesso!`, 'success'); | |
| } | |
| // Adicionar resultado à lista | |
| function addResultToList(index, result) { | |
| const resultsList = document.getElementById('resultsList'); | |
| const resultDiv = document.createElement('div'); | |
| resultDiv.className = 'fade-in'; | |
| resultDiv.innerHTML = ` | |
| <div class="bg-white rounded-lg border-2 border-green-200 p-4 hover-scale"> | |
| <div class="flex items-start justify-between mb-3"> | |
| <div class="flex items-center"> | |
| <span class="inline-flex items-center justify-center w-10 h-10 rounded-full v3-badge text-white font-bold mr-3"> | |
| <i class="fas fa-link"></i> | |
| </span> | |
| <div> | |
| <h4 class="font-semibold text-gray-800">Link v3 Direto</h4> | |
| <p class="text-xs text-gray-500 mt-1">ID: ${result.videoId}</p> | |
| </div> | |
| </div> | |
| <div class="flex items-center space-x-2"> | |
| <span class="px-3 py-1 quality-tag text-white text-xs font-medium rounded-full"> | |
| ${result.quality} | |
| </span> | |
| <span class="px-3 py-1 bg-gray-100 text-gray-700 text-xs font-medium rounded-full"> | |
| <i class="fas fa-hdd mr-1"></i>${result.size} | |
| </span> | |
| </div> | |
| </div> | |
| <div class="space-y-2"> | |
| <div class="text-xs text-gray-600"> | |
| <i class="fas fa-link mr-1"></i> | |
| <strong>Original:</strong> | |
| <span class="break-all">${result.originalUrl}</span> | |
| </div> | |
| <div class="flex items-center space-x-2"> | |
| <input type="text" | |
| value="${result.v3Link}" | |
| readonly | |
| class="flex-1 px-3 py-2 bg-gray-50 border border-gray-200 rounded text-xs font-mono break-all"> | |
| <button onclick="copyToClipboard('${result.v3Link}', ${index})" | |
| class="copy-button px-3 py-2 bg-blue-500 text-white rounded hover:bg-blue-600"> | |
| <i class="fas fa-copy"></i> | |
| </button> | |
| <a href="${result.v3Link}" | |
| download | |
| target="_blank" | |
| class="download-button px-3 py-2 text-white rounded"> | |
| <i class="fas fa-download"></i> | |
| </a> | |
| </div> | |
| </div> | |
| </div> | |
| `; | |
| resultsList.appendChild(resultDiv); | |
| } | |
| // Baixar todos os vídeos | |
| function downloadAll() { | |
| const links = document.querySelectorAll('#resultsList a[download]'); | |
| links.forEach((link, index) => { | |
| setTimeout(() => { | |
| link.click(); | |
| }, index * 500); // Intervalo de 500ms entre downloads | |
| }); | |
| showToast('Iniciando download de todos os vídeos...', 'info'); | |
| } | |
| // Atualizar estatísticas | |
| function updateStats(count, totalSize) { | |
| document.getElementById('totalVideos').textContent = count; | |
| document.getElementById('totalSize').textContent = totalSize.toFixed(1) + ' MB'; | |
| document.getElementById('statsContainer').classList.remove('hidden'); | |
| } | |
| // Mostrar/ocultar resultados | |
| function showResults() { | |
| document.getElementById('resultsContainer').classList.remove('hidden'); | |
| document.getElementById('resultsContainer').scrollIntoView({ behavior: 'smooth' }); | |
| } | |
| function hideResults() { | |
| document.getElementById('resultsContainer').classList.add('hidden'); | |
| document.getElementById('statsContainer').classList.add('hidden'); | |
| } | |
| // Adicionar animação de loading | |
| document.getElementById('processBtn').addEventListener('click', function() { | |
| this.style.transform = 'scale(0.98)'; | |
| setTimeout(() => { | |
| this.style.transform = 'scale(1)'; | |
| }, 200); | |
| }); | |
| </script> | |
| </body> | |
| </html> |