Download index.html from tgatech/dsa: direct link, hf CLI and curl.
- Browser
- Download file 20.9 kB
-
https://huggingface.co/spaces/tgatech/dsa/resolve/main/index.html
- Command line
-
hf download hf://spaces/tgatech/dsa/index.html
-
curl -L -o index.html https://huggingface.co/spaces/tgatech/dsa/resolve/main/index.html
20.9 kB
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>Flask Video İşleme API</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=Orbitron:wght@400;700&family=Rajdhani:wght@300;500;700&display=swap'); | |
| :root { | |
| --space-purple: #5d3fd3; | |
| --deep-space: #1a103d; | |
| --neon-purple: #9c27b0; | |
| --cosmic-pink: #e91e63; | |
| --starry-night: #0f0524; | |
| } | |
| body { | |
| font-family: 'Rajdhani', sans-serif; | |
| background: linear-gradient(135deg, var(--deep-space), var(--starry-night)); | |
| color: white; | |
| min-height: 100vh; | |
| background-image: | |
| radial-gradient(circle at 10% 20%, rgba(156, 39, 176, 0.15) 0%, transparent 20%), | |
| radial-gradient(circle at 90% 30%, rgba(93, 63, 211, 0.15) 0%, transparent 25%), | |
| radial-gradient(circle at 50% 80%, rgba(233, 30, 99, 0.15) 0%, transparent 30%); | |
| } | |
| h1, h2, h3 { | |
| font-family: 'Orbitron', sans-serif; | |
| text-transform: uppercase; | |
| } | |
| .container { | |
| max-width: 1200px; | |
| } | |
| .section { | |
| background: rgba(26, 16, 61, 0.7); | |
| backdrop-filter: blur(10px); | |
| border: 1px solid rgba(156, 39, 176, 0.3); | |
| border-radius: 16px; | |
| box-shadow: 0 0 20px rgba(156, 39, 176, 0.3); | |
| transition: all 0.3s ease; | |
| } | |
| .section:hover { | |
| box-shadow: 0 0 30px rgba(156, 39, 176, 0.5); | |
| transform: translateY(-2px); | |
| } | |
| input, button, select, textarea { | |
| background: rgba(26, 16, 61, 0.5); | |
| border: 1px solid var(--space-purple); | |
| color: white; | |
| transition: all 0.3s ease; | |
| } | |
| input:focus, button:focus, select:focus, textarea:focus { | |
| outline: none; | |
| border-color: var(--neon-purple); | |
| box-shadow: 0 0 10px rgba(156, 39, 176, 0.5); | |
| } | |
| button { | |
| background: linear-gradient(45deg, var(--space-purple), var(--neon-purple)); | |
| text-transform: uppercase; | |
| letter-spacing: 1px; | |
| font-weight: bold; | |
| } | |
| button:hover { | |
| background: linear-gradient(45deg, var(--neon-purple), var(--cosmic-pink)); | |
| transform: translateY(-2px); | |
| box-shadow: 0 5px 15px rgba(156, 39, 176, 0.4); | |
| } | |
| .status-processing { | |
| color: #ff9800; | |
| } | |
| .status-completed { | |
| color: #4caf50; | |
| } | |
| .status-failed { | |
| color: #f44336; | |
| } | |
| .status-queued { | |
| color: #2196f3; | |
| } | |
| .download-link { | |
| color: var(--neon-purple); | |
| text-decoration: none; | |
| font-weight: bold; | |
| } | |
| .download-link:hover { | |
| color: var(--cosmic-pink); | |
| text-decoration: underline; | |
| } | |
| table { | |
| border-collapse: separate; | |
| border-spacing: 0; | |
| width: 100%; | |
| } | |
| th { | |
| background: rgba(93, 63, 211, 0.2); | |
| position: sticky; | |
| top: 0; | |
| backdrop-filter: blur(5px); | |
| } | |
| td, th { | |
| padding: 12px 15px; | |
| text-align: left; | |
| border-bottom: 1px solid rgba(156, 39, 176, 0.2); | |
| } | |
| tr:hover { | |
| background: rgba(93, 63, 211, 0.1); | |
| } | |
| .glow-text { | |
| text-shadow: 0 0 10px rgba(156, 39, 176, 0.7); | |
| } | |
| .file-input-wrapper { | |
| position: relative; | |
| overflow: hidden; | |
| display: inline-block; | |
| width: 100%; | |
| } | |
| .file-input-wrapper input[type=file] { | |
| position: absolute; | |
| left: 0; | |
| top: 0; | |
| opacity: 0; | |
| width: 100%; | |
| height: 100%; | |
| cursor: pointer; | |
| } | |
| .file-input-label { | |
| display: flex; | |
| align-items: center; | |
| justify-content: center; | |
| padding: 12px; | |
| border: 2px dashed var(--space-purple); | |
| border-radius: 8px; | |
| cursor: pointer; | |
| transition: all 0.3s ease; | |
| } | |
| .file-input-label:hover { | |
| border-color: var(--neon-purple); | |
| background: rgba(93, 63, 211, 0.1); | |
| } | |
| .file-input-label i { | |
| margin-right: 10px; | |
| color: var(--neon-purple); | |
| } | |
| .pulse { | |
| animation: pulse 2s infinite; | |
| } | |
| @keyframes pulse { | |
| 0% { | |
| box-shadow: 0 0 0 0 rgba(156, 39, 176, 0.4); | |
| } | |
| 70% { | |
| box-shadow: 0 0 0 10px rgba(156, 39, 176, 0); | |
| } | |
| 100% { | |
| box-shadow: 0 0 0 0 rgba(156, 39, 176, 0); | |
| } | |
| } | |
| .cosmic-divider { | |
| height: 2px; | |
| background: linear-gradient(90deg, transparent, var(--space-purple), var(--neon-purple), transparent); | |
| margin: 20px 0; | |
| border: none; | |
| } | |
| @media (max-width: 768px) { | |
| .section { | |
| padding: 15px; | |
| } | |
| table { | |
| display: block; | |
| overflow-x: auto; | |
| } | |
| } | |
| </style> | |
| </head> | |
| <body class="p-4 md:p-8"> | |
| <div class="container mx-auto"> | |
| <div class="text-center mb-10"> | |
| <h1 class="text-4xl md:text-5xl font-bold mb-4 glow-text text-purple-400"> | |
| <i class="fas fa-rocket mr-3"></i>Flask Video İşleme API | |
| </h1> | |
| <p class="text-lg text-purple-200">Uzay temalı video işleme platformu</p> | |
| </div> | |
| <!-- Video Yükle ve İşle Section --> | |
| <div class="section p-6 mb-8"> | |
| <h2 class="text-2xl font-bold mb-6 text-purple-300 flex items-center"> | |
| <i class="fas fa-upload mr-3"></i>Video Yükle ve İşle | |
| </h2> | |
| <form id="uploadForm" enctype="multipart/form-data" class="space-y-6"> | |
| <div class="file-input-wrapper"> | |
| <label for="videoFile" class="file-input-label"> | |
| <i class="fas fa-video text-xl"></i> | |
| <span id="fileName">Video Dosyası Seçin</span> | |
| </label> | |
| <input type="file" id="videoFile" name="video" accept="video/*" required> | |
| </div> | |
| <button type="submit" class="w-full py-3 px-6 rounded-lg font-bold pulse"> | |
| <i class="fas fa-cogs mr-2"></i>Yükle ve İşle | |
| </button> | |
| </form> | |
| <div id="uploadStatus" class="mt-4 p-3 rounded-lg"></div> | |
| </div> | |
| <hr class="cosmic-divider my-10"> | |
| <!-- İşlem Durumu Sorgula Section --> | |
| <div class="section p-6 mb-8"> | |
| <h2 class="text-2xl font-bold mb-6 text-purple-300 flex items-center"> | |
| <i class="fas fa-search mr-3"></i>İşlem Durumu Sorgula | |
| </h2> | |
| <div class="flex flex-col md:flex-row gap-4"> | |
| <div class="flex-grow relative"> | |
| <i class="fas fa-id-card absolute left-3 top-3 text-purple-400"></i> | |
| <input type="text" id="taskIdInput" placeholder="İşlem ID'sini buraya yapıştır" | |
| class="w-full pl-10 pr-4 py-2 rounded-lg"> | |
| </div> | |
| <button onclick="checkStatus()" class="md:w-auto py-2 px-6 rounded-lg font-bold"> | |
| <i class="fas fa-sync-alt mr-2"></i>Durumu Sorgula | |
| </button> | |
| </div> | |
| <div id="taskStatus" class="mt-4 p-4 rounded-lg bg-gray-800 bg-opacity-50"></div> | |
| </div> | |
| <hr class="cosmic-divider my-10"> | |
| <!-- Tüm İşlem Durumları Section --> | |
| <div class="section p-6"> | |
| <h2 class="text-2xl font-bold mb-6 text-purple-300 flex items-center"> | |
| <i class="fas fa-list-alt mr-3"></i>Tüm İşlem Durumları <span class="text-sm ml-2 text-purple-200">(Otomatik Yenilenir)</span> | |
| </h2> | |
| <div class="overflow-x-auto rounded-lg"> | |
| <table id="allStatusesTable" class="w-full"> | |
| <thead> | |
| <tr class="text-purple-300"> | |
| <th class="py-3"><i class="fas fa-fingerprint mr-2"></i>ID</th> | |
| <th class="py-3"><i class="fas fa-file-video mr-2"></i>Orijinal Dosya</th> | |
| <th class="py-3"><i class="fas fa-clock mr-2"></i>Yükleme Zamanı</th> | |
| <th class="py-3"><i class="fas fa-info-circle mr-2"></i>Durum</th> | |
| <th class="py-3"><i class="fas fa-stopwatch mr-2"></i>İşlem Süresi (s)</th> | |
| <th class="py-3"><i class="fas fa-exclamation-triangle mr-2"></i>Hata</th> | |
| <th class="py-3"><i class="fas fa-download mr-2"></i>İndir</th> | |
| </tr> | |
| </thead> | |
| <tbody> | |
| <tr><td colspan="7" class="text-center py-4 text-red-400"><i class="fas fa-exclamation-circle mr-2"></i>Tüm işlem durumları yüklenemedi. Sunucu hatası olabilir.</td></tr> | |
| </tbody> | |
| </table> | |
| </div> | |
| </div> | |
| </div> | |
| <script> | |
| const uploadForm = document.getElementById('uploadForm'); | |
| const videoFile = document.getElementById('videoFile'); | |
| const uploadStatusDiv = document.getElementById('uploadStatus'); | |
| const taskIdInput = document.getElementById('taskIdInput'); | |
| const taskStatusDiv = document.getElementById('taskStatus'); | |
| const allStatusesTableBody = document.querySelector('#allStatusesTable tbody'); | |
| const fileNameSpan = document.getElementById('fileName'); | |
| // Update filename display when file is selected | |
| videoFile.addEventListener('change', function() { | |
| if (this.files.length) { | |
| fileNameSpan.textContent = this.files[0].name; | |
| } else { | |
| fileNameSpan.textContent = 'Video Dosyası Seçin'; | |
| } | |
| }); | |
| // Video Yükleme Formu | |
| uploadForm.addEventListener('submit', async (e) => { | |
| e.preventDefault(); | |
| if (!videoFile.files.length) { | |
| uploadStatusDiv.innerHTML = '<i class="fas fa-exclamation-circle mr-2"></i>Lütfen bir video dosyası seçin.'; | |
| uploadStatusDiv.className = 'mt-4 p-3 rounded-lg bg-red-900 bg-opacity-30 text-red-300'; | |
| return; | |
| } | |
| const formData = new FormData(); | |
| formData.append('video', videoFile.files[0]); | |
| uploadStatusDiv.innerHTML = '<i class="fas fa-spinner fa-spin mr-2"></i>Video yükleniyor ve işleniyor... Lütfen bekleyin.'; | |
| uploadStatusDiv.className = 'mt-4 p-3 rounded-lg bg-blue-900 bg-opacity-30 text-blue-300'; | |
| try { | |
| const response = await fetch('/upload-and-process', { | |
| method: 'POST', | |
| body: formData | |
| }); | |
| const result = await response.json(); | |
| if (response.ok) { | |
| uploadStatusDiv.innerHTML = `<i class="fas fa-check-circle mr-2"></i>Başarılı! İşlem ID: <strong>${result.task_id}</strong>. Durum: <span class="status-${result.status}">${result.status}</span>`; | |
| uploadStatusDiv.className = 'mt-4 p-3 rounded-lg bg-green-900 bg-opacity-30 text-green-300'; | |
| taskIdInput.value = result.task_id; // Otomatik olarak ID'yi doldur | |
| fetchAllStatuses(); // Tabloyu güncelle | |
| } else { | |
| uploadStatusDiv.innerHTML = `<i class="fas fa-times-circle mr-2"></i>Hata: ${result.error || 'Bilinmeyen hata'}`; | |
| uploadStatusDiv.className = 'mt-4 p-3 rounded-lg bg-red-900 bg-opacity-30 text-red-300'; | |
| } | |
| } catch (error) { | |
| uploadStatusDiv.innerHTML = `<i class="fas fa-times-circle mr-2"></i>Ağ hatası: ${error.message}`; | |
| uploadStatusDiv.className = 'mt-4 p-3 rounded-lg bg-red-900 bg-opacity-30 text-red-300'; | |
| console.error('Upload Error:', error); | |
| } | |
| }); | |
| // Tekil İşlem Durumu Sorgulama | |
| async function checkStatus() { | |
| const taskId = taskIdInput.value.trim(); | |
| if (!taskId) { | |
| taskStatusDiv.innerHTML = '<i class="fas fa-exclamation-circle mr-2"></i>Lütfen bir İşlem ID girin.'; | |
| taskStatusDiv.className = 'mt-4 p-4 rounded-lg bg-red-900 bg-opacity-30 text-red-300'; | |
| return; | |
| } | |
| taskStatusDiv.innerHTML = '<i class="fas fa-spinner fa-spin mr-2"></i>Durum sorgulanıyor...'; | |
| taskStatusDiv.className = 'mt-4 p-4 rounded-lg bg-blue-900 bg-opacity-30 text-blue-300'; | |
| try { | |
| const response = await fetch(`/status/${taskId}`); | |
| const status = await response.json(); | |
| if (response.ok) { | |
| taskStatusDiv.innerHTML = ` | |
| <div class="space-y-2"> | |
| <div><i class="fas fa-info-circle mr-2 text-purple-400"></i><strong>Durum:</strong> <span class="status-${status.status}">${status.status}</span></div> | |
| <div><i class="fas fa-file-video mr-2 text-purple-400"></i><strong>Orijinal Dosya:</strong> ${status.original_filename}</div> | |
| <div><i class="fas fa-calendar-alt mr-2 text-purple-400"></i><strong>Yükleme Zamanı:</strong> ${status.uploaded_at_readable || 'N/A'}</div> | |
| ${status.start_time_readable ? `<div><i class="fas fa-play mr-2 text-purple-400"></i><strong>Başlama Zamanı:</strong> ${status.start_time_readable}</div>` : ''} | |
| ${status.end_time_readable ? `<div><i class="fas fa-stop mr-2 text-purple-400"></i><strong>Bitiş Zamanı:</strong> ${status.end_time_readable}</div>` : ''} | |
| ${status.duration_seconds !== null ? `<div><i class="fas fa-hourglass-half mr-2 text-purple-400"></i><strong>İşlem Süresi:</strong> ${status.duration_seconds} saniye</div>` : ''} | |
| ${status.error ? `<div><i class="fas fa-exclamation-triangle mr-2 text-red-400"></i><strong>Hata:</strong> <span class="text-red-300">${status.error}</span></div>` : ''} | |
| ${status.status === 'completed' ? `<div class="mt-3"><a href="/download/${status.output_filename}" target="_blank" class="download-link py-2 px-4 rounded-lg inline-block"><i class="fas fa-download mr-2"></i>İndir (${status.output_filename})</a></div>` : ''} | |
| </div> | |
| `; | |
| taskStatusDiv.className = 'mt-4 p-4 rounded-lg bg-gray-800 bg-opacity-50'; | |
| } else { | |
| taskStatusDiv.innerHTML = `<i class="fas fa-times-circle mr-2"></i>Hata: ${status.error || 'İşlem ID bulunamadı.'}`; | |
| taskStatusDiv.className = 'mt-4 p-4 rounded-lg bg-red-900 bg-opacity-30 text-red-300'; | |
| } | |
| } catch (error) { | |
| taskStatusDiv.innerHTML = `<i class="fas fa-times-circle mr-2"></i>Ağ hatası: ${error.message}`; | |
| taskStatusDiv.className = 'mt-4 p-4 rounded-lg bg-red-900 bg-opacity-30 text-red-300'; | |
| console.error('Status Check Error:', error); | |
| } | |
| } | |
| // Tüm İşlem Durumlarını Çek ve Tabloyu Doldur | |
| async function fetchAllStatuses() { | |
| try { | |
| const response = await fetch('/all-statuses'); | |
| const statuses = await response.json(); | |
| allStatusesTableBody.innerHTML = ''; // Tabloyu temizle | |
| if (statuses.length === 0) { | |
| const row = allStatusesTableBody.insertRow(); | |
| const cell = row.insertCell(0); | |
| cell.colSpan = 7; | |
| cell.className = 'text-center py-4 text-purple-300'; | |
| cell.innerHTML = '<i class="fas fa-info-circle mr-2"></i>Henüz işlenmiş video yok.'; | |
| return; | |
| } | |
| statuses.forEach(status => { | |
| const row = allStatusesTableBody.insertRow(); | |
| row.className = 'hover:bg-purple-900 hover:bg-opacity-10'; | |
| // ID | |
| const idCell = row.insertCell(0); | |
| idCell.className = 'font-mono text-purple-300'; | |
| idCell.textContent = status.id.substring(0, 8) + '...'; | |
| // Original Filename | |
| row.insertCell(1).textContent = status.original_filename; | |
| // Upload Time | |
| row.insertCell(2).textContent = status.uploaded_at_readable || 'N/A'; | |
| // Status | |
| const statusCell = row.insertCell(3); | |
| statusCell.textContent = status.status; | |
| statusCell.className = `status-${status.status} font-bold`; | |
| // Duration | |
| const durationCell = row.insertCell(4); | |
| durationCell.className = 'text-center'; | |
| durationCell.textContent = status.duration_seconds !== null ? status.duration_seconds : '-'; | |
| // Error | |
| const errorCell = row.insertCell(5); | |
| errorCell.textContent = status.error || '-'; | |
| if (status.error) { | |
| errorCell.className = 'text-red-400'; | |
| } | |
| // Download | |
| const downloadCell = row.insertCell(6); | |
| downloadCell.className = 'text-center'; | |
| if (status.status === 'completed' && status.output_filename) { | |
| const downloadLink = document.createElement('a'); | |
| downloadLink.href = `/download/${status.output_filename}`; | |
| downloadLink.className = 'download-link px-3 py-1 rounded-lg inline-block'; | |
| downloadLink.innerHTML = '<i class="fas fa-download mr-1"></i>İndir'; | |
| downloadLink.target = '_blank'; | |
| downloadCell.appendChild(downloadLink); | |
| } else { | |
| downloadCell.textContent = '-'; | |
| } | |
| }); | |
| } catch (error) { | |
| console.error('Tüm durumları getirirken hata oluştu:', error); | |
| const row = allStatusesTableBody.insertRow(); | |
| const cell = row.insertCell(0); | |
| cell.colSpan = 7; | |
| cell.className = 'text-center py-4 text-red-400'; | |
| cell.innerHTML = '<i class="fas fa-exclamation-circle mr-2"></i>Tüm işlem durumları yüklenemedi. Sunucu hatası olabilir.'; | |
| } | |
| } | |
| // Sayfa yüklendiğinde ve belirli aralıklarla durumları güncelle | |
| document.addEventListener('DOMContentLoaded', () => { | |
| fetchAllStatuses(); | |
| setInterval(fetchAllStatuses, 5000); // Her 5 saniyede bir yenile | |
| }); | |
| </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=tgatech/dsa" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body> | |
| </html> |