Spaces:
Runtime error
Runtime error
Download templates/index.html from cytopa99/universal-fast-dubbing: direct link, hf CLI and curl.
- Browser
- Download file 12.7 kB
-
https://huggingface.co/spaces/cytopa99/universal-fast-dubbing/resolve/e25b15a24b18f9f4a89101efe078dfd7fee15b62/templates/index.html
- Command line
-
hf download hf://spaces/cytopa99/universal-fast-dubbing@e25b15a24b18f9f4a89101efe078dfd7fee15b62/templates/index.html
-
curl -L -o index.html https://huggingface.co/spaces/cytopa99/universal-fast-dubbing/resolve/e25b15a24b18f9f4a89101efe078dfd7fee15b62/templates/index.html
12.7 kB
| <html lang="zh-CN"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>{{ title }}</title> | |
| <link href="https://cdn.jsdelivr.net/npm/tailwindcss@2.2.19/dist/tailwind.min.css" rel="stylesheet"> | |
| <style> | |
| .gradient-bg { | |
| background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); | |
| } | |
| .card { | |
| backdrop-filter: blur(10px); | |
| background: rgba(255, 255, 255, 0.1); | |
| border: 1px solid rgba(255, 255, 255, 0.2); | |
| } | |
| .progress-bar { | |
| transition: width 0.3s ease; | |
| } | |
| </style> | |
| </head> | |
| <body class="gradient-bg min-h-screen"> | |
| <div class="container mx-auto px-4 py-8"> | |
| <!-- 头部 --> | |
| <div class="text-center mb-8"> | |
| <h1 class="text-4xl font-bold text-white mb-2">🎬 Universal Fast Dubbing</h1> | |
| <p class="text-xl text-gray-200">AI驱动的视频配音系统 v{{ version }}</p> | |
| </div> | |
| <!-- 主要内容区域 --> | |
| <div class="max-w-4xl mx-auto"> | |
| <!-- 配音处理卡片 --> | |
| <div class="card rounded-lg p-6 mb-6"> | |
| <h2 class="text-2xl font-semibold text-white mb-4">配音处理</h2> | |
| <form id="dubbingForm" class="space-y-4"> | |
| <!-- 处理模式选择 --> | |
| <div> | |
| <label class="block text-white text-sm font-medium mb-2">处理模式</label> | |
| <div class="flex space-x-4"> | |
| <label class="flex items-center text-white"> | |
| <input type="radio" name="mode" value="auto" checked class="mr-2"> | |
| 自动检测 | |
| </label> | |
| <label class="flex items-center text-white"> | |
| <input type="radio" name="mode" value="url" class="mr-2"> | |
| URL模式 | |
| </label> | |
| <label class="flex items-center text-white"> | |
| <input type="radio" name="mode" value="record" class="mr-2"> | |
| 录制模式 | |
| </label> | |
| </div> | |
| </div> | |
| <!-- URL 输入 --> | |
| <div id="urlInput"> | |
| <label class="block text-white text-sm font-medium mb-2">视频URL</label> | |
| <input type="url" name="url" placeholder="https://www.youtube.com/watch?v=..." | |
| class="w-full px-3 py-2 bg-white bg-opacity-20 border border-gray-300 rounded-md text-white placeholder-gray-300 focus:outline-none focus:ring-2 focus:ring-blue-500"> | |
| </div> | |
| <!-- 音频文件上传 --> | |
| <div id="audioInput" style="display: none;"> | |
| <label class="block text-white text-sm font-medium mb-2">录制音频</label> | |
| <input type="file" name="audio_file" accept="audio/*" | |
| class="w-full px-3 py-2 bg-white bg-opacity-20 border border-gray-300 rounded-md text-white file:mr-4 file:py-2 file:px-4 file:rounded-full file:border-0 file:text-sm file:font-semibold file:bg-blue-50 file:text-blue-700 hover:file:bg-blue-100"> | |
| </div> | |
| <!-- 客户端配置(隐藏) --> | |
| <input type="hidden" name="client_config" value="{}"> | |
| <!-- 提交按钮 --> | |
| <button type="submit" id="processBtn" | |
| class="w-full bg-blue-600 hover:bg-blue-700 text-white font-bold py-3 px-4 rounded-lg transition duration-200"> | |
| 🎬 开始配音 | |
| </button> | |
| </form> | |
| <!-- 进度条 --> | |
| <div id="progressContainer" class="mt-4" style="display: none;"> | |
| <div class="bg-gray-200 rounded-full h-2"> | |
| <div id="progressBar" class="progress-bar bg-blue-600 h-2 rounded-full" style="width: 0%"></div> | |
| </div> | |
| <p id="progressText" class="text-white text-sm mt-2">处理中...</p> | |
| </div> | |
| <!-- 结果显示 --> | |
| <div id="resultContainer" class="mt-4" style="display: none;"> | |
| <div class="bg-green-100 border border-green-400 text-green-700 px-4 py-3 rounded mb-4"> | |
| <p id="resultMessage">配音完成!</p> | |
| </div> | |
| <audio id="resultAudio" controls class="w-full"> | |
| 您的浏览器不支持音频播放。 | |
| </audio> | |
| </div> | |
| <!-- 错误显示 --> | |
| <div id="errorContainer" class="mt-4" style="display: none;"> | |
| <div class="bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded"> | |
| <p id="errorMessage">处理失败</p> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- 系统状态卡片 --> | |
| <div class="card rounded-lg p-6 mb-6"> | |
| <h2 class="text-2xl font-semibold text-white mb-4">系统状态</h2> | |
| <button id="refreshStatusBtn" | |
| class="bg-gray-600 hover:bg-gray-700 text-white font-bold py-2 px-4 rounded mb-4"> | |
| 🔄 刷新状态 | |
| </button> | |
| <div id="statusContainer" class="grid grid-cols-1 md:grid-cols-2 gap-4"> | |
| <div class="bg-white bg-opacity-10 rounded p-4"> | |
| <h3 class="text-white font-semibold mb-2">系统健康</h3> | |
| <p id="healthStatus" class="text-gray-200">检查中...</p> | |
| </div> | |
| <div class="bg-white bg-opacity-10 rounded p-4"> | |
| <h3 class="text-white font-semibold mb-2">内存使用</h3> | |
| <p id="memoryUsage" class="text-gray-200">-- MB</p> | |
| </div> | |
| <div class="bg-white bg-opacity-10 rounded p-4"> | |
| <h3 class="text-white font-semibold mb-2">CPU使用率</h3> | |
| <p id="cpuUsage" class="text-gray-200">--%</p> | |
| </div> | |
| <div class="bg-white bg-opacity-10 rounded p-4"> | |
| <h3 class="text-white font-semibold mb-2">成功率</h3> | |
| <p id="successRate" class="text-gray-200">--%</p> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- API 文档卡片 --> | |
| <div class="card rounded-lg p-6"> | |
| <h2 class="text-2xl font-semibold text-white mb-4">API 文档</h2> | |
| <div class="text-gray-200 space-y-4"> | |
| <div> | |
| <h3 class="text-lg font-semibold text-white">主要端点</h3> | |
| <ul class="list-disc list-inside mt-2 space-y-1"> | |
| <li><code class="bg-gray-800 px-2 py-1 rounded">POST /api/process</code> - 配音处理</li> | |
| <li><code class="bg-gray-800 px-2 py-1 rounded">POST /api/ping</code> - 连接测试</li> | |
| <li><code class="bg-gray-800 px-2 py-1 rounded">GET /api/status</code> - 系统状态</li> | |
| <li><code class="bg-gray-800 px-2 py-1 rounded">GET /api/config</code> - 后端配置</li> | |
| </ul> | |
| </div> | |
| <div> | |
| <h3 class="text-lg font-semibold text-white">支持平台</h3> | |
| <p class="mt-2">YouTube ✓ | Bilibili ✓ | Netflix (录制模式) | TikTok ✓ | Twitter/X ✓</p> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <script> | |
| // DOM 元素 | |
| const form = document.getElementById('dubbingForm'); | |
| const modeRadios = document.querySelectorAll('input[name="mode"]'); | |
| const urlInput = document.getElementById('urlInput'); | |
| const audioInput = document.getElementById('audioInput'); | |
| const processBtn = document.getElementById('processBtn'); | |
| const progressContainer = document.getElementById('progressContainer'); | |
| const progressBar = document.getElementById('progressBar'); | |
| const progressText = document.getElementById('progressText'); | |
| const resultContainer = document.getElementById('resultContainer'); | |
| const errorContainer = document.getElementById('errorContainer'); | |
| const refreshStatusBtn = document.getElementById('refreshStatusBtn'); | |
| // 模式切换处理 | |
| modeRadios.forEach(radio => { | |
| radio.addEventListener('change', function() { | |
| if (this.value === 'record') { | |
| urlInput.style.display = 'none'; | |
| audioInput.style.display = 'block'; | |
| } else { | |
| urlInput.style.display = 'block'; | |
| audioInput.style.display = 'none'; | |
| } | |
| }); | |
| }); | |
| // 表单提交处理 | |
| form.addEventListener('submit', async function(e) { | |
| e.preventDefault(); | |
| const formData = new FormData(form); | |
| // 显示进度条 | |
| progressContainer.style.display = 'block'; | |
| resultContainer.style.display = 'none'; | |
| errorContainer.style.display = 'none'; | |
| processBtn.disabled = true; | |
| processBtn.textContent = '处理中...'; | |
| try { | |
| const response = await fetch('/api/process', { | |
| method: 'POST', | |
| body: formData | |
| }); | |
| const result = await response.json(); | |
| if (result.success) { | |
| // 显示成功结果 | |
| document.getElementById('resultMessage').textContent = | |
| `配音完成!处理时间: ${result.processing_time?.toFixed(1) || 0}秒`; | |
| if (result.audio_url) { | |
| document.getElementById('resultAudio').src = result.audio_url; | |
| } | |
| resultContainer.style.display = 'block'; | |
| } else { | |
| // 显示错误 | |
| document.getElementById('errorMessage').textContent = result.error || '处理失败'; | |
| errorContainer.style.display = 'block'; | |
| } | |
| } catch (error) { | |
| console.error('处理失败:', error); | |
| document.getElementById('errorMessage').textContent = '网络错误: ' + error.message; | |
| errorContainer.style.display = 'block'; | |
| } finally { | |
| progressContainer.style.display = 'none'; | |
| processBtn.disabled = false; | |
| processBtn.textContent = '🎬 开始配音'; | |
| } | |
| }); | |
| // 刷新系统状态 | |
| refreshStatusBtn.addEventListener('click', async function() { | |
| try { | |
| const response = await fetch('/api/status'); | |
| const status = await response.json(); | |
| document.getElementById('healthStatus').textContent = | |
| status.healthy ? '✓ 正常' : '✗ 异常'; | |
| document.getElementById('memoryUsage').textContent = | |
| `${status.performance?.memory_mb || 0} MB`; | |
| document.getElementById('cpuUsage').textContent = | |
| `${status.performance?.cpu_percent || 0}%`; | |
| document.getElementById('successRate').textContent = | |
| `${(status.performance?.success_rate * 100 || 0).toFixed(1)}%`; | |
| } catch (error) { | |
| console.error('获取状态失败:', error); | |
| } | |
| }); | |
| // 页面加载时获取状态 | |
| refreshStatusBtn.click(); | |
| </script> | |
| </body> | |
| </html> |