Download index.html from geadmin/ideas: direct link, hf CLI and curl.
- Browser
- Download file 27.8 kB
-
https://huggingface.co/spaces/geadmin/ideas/resolve/main/index.html
- Command line
-
hf download hf://spaces/geadmin/ideas/index.html
-
curl -L -o index.html https://huggingface.co/spaces/geadmin/ideas/resolve/main/index.html
27.8 kB
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>ElevenLabs AI Voice Cloning Studio</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'); | |
| body { | |
| font-family: 'Inter', sans-serif; | |
| background-color: #f8fafc; | |
| } | |
| .gradient-bg { | |
| background: linear-gradient(135deg, #6366f1 0%, #8b5cf6 50%, #d946ef 100%); | |
| } | |
| .waveform { | |
| background: repeating-linear-gradient( | |
| 90deg, | |
| #e2e8f0, | |
| #e2e8f0 2px, | |
| transparent 2px, | |
| transparent 4px | |
| ); | |
| height: 60px; | |
| } | |
| .voice-card:hover { | |
| transform: translateY(-5px); | |
| box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04); | |
| } | |
| .recording { | |
| animation: pulse 1.5s infinite; | |
| } | |
| @keyframes pulse { | |
| 0% { box-shadow: 0 0 0 0 rgba(239, 68, 68, 0.7); } | |
| 70% { box-shadow: 0 0 0 10px rgba(239, 68, 68, 0); } | |
| 100% { box-shadow: 0 0 0 0 rgba(239, 68, 68, 0); } | |
| } | |
| .play-btn { | |
| transition: all 0.3s ease; | |
| } | |
| .play-btn:hover { | |
| transform: scale(1.1); | |
| } | |
| /* Audio visualization */ | |
| .audio-visualizer { | |
| display: flex; | |
| align-items: flex-end; | |
| height: 60px; | |
| gap: 2px; | |
| margin-top: 10px; | |
| } | |
| .audio-bar { | |
| background-color: #6366f1; | |
| width: 4px; | |
| border-radius: 2px; | |
| transition: height 0.1s ease; | |
| } | |
| /* Progress bar */ | |
| .progress-container { | |
| width: 100%; | |
| height: 4px; | |
| background-color: #e2e8f0; | |
| border-radius: 2px; | |
| margin-top: 10px; | |
| } | |
| .progress-bar { | |
| height: 100%; | |
| background-color: #6366f1; | |
| border-radius: 2px; | |
| width: 0%; | |
| transition: width 0.1s linear; | |
| } | |
| </style> | |
| </head> | |
| <body> | |
| <div class="min-h-screen"> | |
| <!-- Header --> | |
| <header class="gradient-bg text-white"> | |
| <div class="container mx-auto px-4 py-6"> | |
| <div class="flex justify-between items-center"> | |
| <div class="flex items-center space-x-2"> | |
| <i class="fas fa-robot text-3xl"></i> | |
| <h1 class="text-2xl font-bold">ElevenLabs Voice Studio</h1> | |
| </div> | |
| <div class="flex items-center space-x-4"> | |
| <button class="px-4 py-2 bg-white text-indigo-600 rounded-lg font-medium hover:bg-gray-100 transition"> | |
| <i class="fas fa-key mr-2"></i>API Key | |
| </button> | |
| <button class="px-4 py-2 bg-indigo-700 text-white rounded-lg font-medium hover:bg-indigo-800 transition"> | |
| <i class="fas fa-user mr-2"></i>Account | |
| </button> | |
| </div> | |
| </div> | |
| </div> | |
| </header> | |
| <!-- Main Content --> | |
| <main class="container mx-auto px-4 py-8"> | |
| <div class="grid grid-cols-1 lg:grid-cols-3 gap-8"> | |
| <!-- Left Sidebar - Voice Management --> | |
| <div class="lg:col-span-1 bg-white rounded-xl shadow-md p-6"> | |
| <div class="flex justify-between items-center mb-6"> | |
| <h2 class="text-xl font-semibold text-gray-800">My Voices</h2> | |
| <button id="newVoiceBtn" class="px-3 py-1 bg-indigo-600 text-white rounded-lg text-sm hover:bg-indigo-700 transition"> | |
| <i class="fas fa-plus mr-1"></i> New | |
| </button> | |
| </div> | |
| <div class="space-y-4"> | |
| <!-- Voice Cards --> | |
| <div class="voice-card bg-gray-50 rounded-lg p-4 border border-gray-200 transition duration-300 cursor-pointer" data-voice="Professional Male"> | |
| <div class="flex items-center space-x-3"> | |
| <div class="w-12 h-12 rounded-full bg-indigo-100 flex items-center justify-center"> | |
| <i class="fas fa-user text-indigo-600"></i> | |
| </div> | |
| <div> | |
| <h3 class="font-medium text-gray-800">Professional Male</h3> | |
| <p class="text-xs text-gray-500">English • Standard</p> | |
| </div> | |
| </div> | |
| <div class="mt-3 flex justify-between items-center"> | |
| <span class="text-xs px-2 py-1 bg-green-100 text-green-800 rounded">Active</span> | |
| <div class="flex space-x-2"> | |
| <button class="text-gray-500 hover:text-indigo-600 play-voice-btn"> | |
| <i class="fas fa-play play-btn"></i> | |
| </button> | |
| <button class="text-gray-500 hover:text-indigo-600"> | |
| <i class="fas fa-edit"></i> | |
| </button> | |
| </div> | |
| </div> | |
| </div> | |
| <div class="voice-card bg-gray-50 rounded-lg p-4 border border-gray-200 transition duration-300 cursor-pointer" data-voice="Friendly Female"> | |
| <div class="flex items-center space-x-3"> | |
| <div class="w-12 h-12 rounded-full bg-pink-100 flex items-center justify-center"> | |
| <i class="fas fa-user text-pink-600"></i> | |
| </div> | |
| <div> | |
| <h3 class="font-medium text-gray-800">Friendly Female</h3> | |
| <p class="text-xs text-gray-500">English • Conversational</p> | |
| </div> | |
| </div> | |
| <div class="mt-3 flex justify-between items-center"> | |
| <span class="text-xs px-2 py-1 bg-gray-100 text-gray-800 rounded">Inactive</span> | |
| <div class="flex space-x-2"> | |
| <button class="text-gray-500 hover:text-indigo-600 play-voice-btn"> | |
| <i class="fas fa-play play-btn"></i> | |
| </button> | |
| <button class="text-gray-500 hover:text-indigo-600"> | |
| <i class="fas fa-edit"></i> | |
| </button> | |
| </div> | |
| </div> | |
| </div> | |
| <div class="voice-card bg-gray-50 rounded-lg p-4 border border-gray-200 transition duration-300 cursor-pointer" data-voice="British Narrator"> | |
| <div class="flex items-center space-x-3"> | |
| <div class="w-12 h-12 rounded-full bg-purple-100 flex items-center justify-center"> | |
| <i class="fas fa-user text-purple-600"></i> | |
| </div> | |
| <div> | |
| <h3 class="font-medium text-gray-800">British Narrator</h3> | |
| <p class="text-xs text-gray-500">English • British</p> | |
| </div> | |
| </div> | |
| <div class="mt-3 flex justify-between items-center"> | |
| <span class="text-xs px-2 py-1 bg-gray-100 text-gray-800 rounded">Inactive</span> | |
| <div class="flex space-x-2"> | |
| <button class="text-gray-500 hover:text-indigo-600 play-voice-btn"> | |
| <i class="fas fa-play play-btn"></i> | |
| </button> | |
| <button class="text-gray-500 hover:text-indigo-600"> | |
| <i class="fas fa-edit"></i> | |
| </button> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Add Voice Modal (hidden by default) --> | |
| <div id="addVoiceModal" class="hidden fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50"> | |
| <div class="bg-white rounded-xl p-6 w-full max-w-md"> | |
| <div class="flex justify-between items-center mb-4"> | |
| <h3 class="text-lg font-semibold">Create New Voice</h3> | |
| <button id="closeModalBtn" class="text-gray-500 hover:text-gray-700"> | |
| <i class="fas fa-times"></i> | |
| </button> | |
| </div> | |
| <div class="space-y-4"> | |
| <div> | |
| <label class="block text-sm font-medium text-gray-700 mb-1">Voice Name</label> | |
| <input type="text" class="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-indigo-500 focus:border-indigo-500"> | |
| </div> | |
| <div> | |
| <label class="block text-sm font-medium text-gray-700 mb-1">Voice Type</label> | |
| <select class="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-indigo-500 focus:border-indigo-500"> | |
| <option>Clone from audio</option> | |
| <option>Use preset voice</option> | |
| <option>Generate random voice</option> | |
| </select> | |
| </div> | |
| <div id="audioUploadSection"> | |
| <label class="block text-sm font-medium text-gray-700 mb-1">Upload Audio Samples</label> | |
| <div class="border-2 border-dashed border-gray-300 rounded-lg p-6 text-center"> | |
| <i class="fas fa-microphone text-3xl text-gray-400 mb-2"></i> | |
| <p class="text-sm text-gray-500">Drag & drop audio files here or click to browse</p> | |
| <input type="file" class="hidden" accept="audio/*"> | |
| </div> | |
| <p class="mt-1 text-xs text-gray-500">Upload at least 30 seconds of clear speech for best results</p> | |
| </div> | |
| <div class="flex justify-end space-x-3 pt-4"> | |
| <button class="px-4 py-2 border border-gray-300 rounded-lg text-gray-700 hover:bg-gray-50">Cancel</button> | |
| <button class="px-4 py-2 bg-indigo-600 text-white rounded-lg hover:bg-indigo-700">Create Voice</button> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Main Content - Text to Speech --> | |
| <div class="lg:col-span-2 space-y-6"> | |
| <div class="bg-white rounded-xl shadow-md p-6"> | |
| <h2 class="text-xl font-semibold text-gray-800 mb-4">Text to Speech</h2> | |
| <div class="mb-4"> | |
| <label class="block text-sm font-medium text-gray-700 mb-1">Select Voice</label> | |
| <div class="flex items-center space-x-3"> | |
| <select id="voiceSelect" class="flex-1 px-3 py-2 border border-gray-300 rounded-lg focus:ring-indigo-500 focus:border-indigo-500"> | |
| <option value="Professional Male">Professional Male</option> | |
| <option value="Friendly Female">Friendly Female</option> | |
| <option value="British Narrator">British Narrator</option> | |
| </select> | |
| <button class="px-3 py-2 bg-gray-100 text-gray-700 rounded-lg hover:bg-gray-200"> | |
| <i class="fas fa-random"></i> | |
| </button> | |
| </div> | |
| </div> | |
| <div class="mb-4"> | |
| <label class="block text-sm font-medium text-gray-700 mb-1">Enter Text</label> | |
| <textarea id="textInput" rows="5" class="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-indigo-500 focus:border-indigo-500" placeholder="Type or paste your text here...">Hello, this is a demonstration of the ElevenLabs AI voice cloning technology. The voice you're hearing has been generated by artificial intelligence.</textarea> | |
| </div> | |
| <div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-4"> | |
| <div> | |
| <label class="block text-sm font-medium text-gray-700 mb-1">Stability</label> | |
| <input type="range" min="0" max="100" value="75" class="w-full h-2 bg-gray-200 rounded-lg appearance-none cursor-pointer"> | |
| <div class="flex justify-between text-xs text-gray-500 mt-1"> | |
| <span>More variable</span> | |
| <span>More stable</span> | |
| </div> | |
| </div> | |
| <div> | |
| <label class="block text-sm font-medium text-gray-700 mb-1">Clarity + Similarity</label> | |
| <input type="range" min="0" max="100" value="65" class="w-full h-2 bg-gray-200 rounded-lg appearance-none cursor-pointer"> | |
| <div class="flex justify-between text-xs text-gray-500 mt-1"> | |
| <span>More clear</span> | |
| <span>More similar</span> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Audio Visualization --> | |
| <div id="audioVisualization" class="hidden"> | |
| <div class="audio-visualizer" id="visualizer"> | |
| <!-- Bars will be added dynamically --> | |
| </div> | |
| <div class="progress-container"> | |
| <div class="progress-bar" id="progressBar"></div> | |
| </div> | |
| </div> | |
| <div class="flex flex-wrap gap-3"> | |
| <button id="generateBtn" class="px-4 py-2 bg-indigo-600 text-white rounded-lg hover:bg-indigo-700 flex items-center"> | |
| <i class="fas fa-play mr-2"></i> Generate | |
| </button> | |
| <button id="downloadBtn" class="px-4 py-2 border border-gray-300 text-gray-700 rounded-lg hover:bg-gray-50 flex items-center"> | |
| <i class="fas fa-download mr-2"></i> Download | |
| </button> | |
| <button class="px-4 py-2 border border-gray-300 text-gray-700 rounded-lg hover:bg-gray-50 flex items-center"> | |
| <i class="fas fa-share-alt mr-2"></i> Share | |
| </button> | |
| <button id="stopBtn" class="px-4 py-2 border border-gray-300 text-gray-700 rounded-lg hover:bg-gray-50 flex items-center hidden"> | |
| <i class="fas fa-stop mr-2"></i> Stop | |
| </button> | |
| </div> | |
| </div> | |
| <!-- Output Section --> | |
| <div class="bg-white rounded-xl shadow-md p-6"> | |
| <h2 class="text-xl font-semibold text-gray-800 mb-4">Generated Output</h2> | |
| <div id="outputContainer" class="bg-gray-50 rounded-lg p-4 min-h-32"> | |
| <p class="text-gray-500 italic" id="outputPlaceholder">Your generated voice will appear here...</p> | |
| <audio id="audioPlayer" controls class="w-full mt-4 hidden"></audio> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| </main> | |
| </div> | |
| <script> | |
| document.addEventListener('DOMContentLoaded', function() { | |
| // Modal functionality | |
| const newVoiceBtn = document.getElementById('newVoiceBtn'); | |
| const closeModalBtn = document.getElementById('closeModalBtn'); | |
| const addVoiceModal = document.getElementById('addVoiceModal'); | |
| newVoiceBtn.addEventListener('click', () => { | |
| addVoiceModal.classList.remove('hidden'); | |
| }); | |
| closeModalBtn.addEventListener('click', () => { | |
| addVoiceModal.classList.add('hidden'); | |
| }); | |
| // Voice synthesis functionality | |
| const generateBtn = document.getElementById('generateBtn'); | |
| const stopBtn = document.getElementById('stopBtn'); | |
| const downloadBtn = document.getElementById('downloadBtn'); | |
| const textInput = document.getElementById('textInput'); | |
| const voiceSelect = document.getElementById('voiceSelect'); | |
| const outputPlaceholder = document.getElementById('outputPlaceholder'); | |
| const audioPlayer = document.getElementById('audioPlayer'); | |
| const audioVisualization = document.getElementById('audioVisualization'); | |
| const visualizer = document.getElementById('visualizer'); | |
| const progressBar = document.getElementById('progressBar'); | |
| let speechSynthesis = window.speechSynthesis; | |
| let utterance = null; | |
| let isPlaying = false; | |
| // Create audio visualization bars | |
| for (let i = 0; i < 50; i++) { | |
| const bar = document.createElement('div'); | |
| bar.className = 'audio-bar'; | |
| bar.style.height = `${Math.random() * 30 + 10}px`; | |
| visualizer.appendChild(bar); | |
| } | |
| // Animate visualization bars | |
| function animateBars() { | |
| const bars = visualizer.querySelectorAll('.audio-bar'); | |
| bars.forEach(bar => { | |
| const newHeight = Math.random() * 30 + 10; | |
| bar.style.height = `${newHeight}px`; | |
| }); | |
| if (isPlaying) { | |
| requestAnimationFrame(animateBars); | |
| } | |
| } | |
| // Generate voice | |
| generateBtn.addEventListener('click', () => { | |
| const text = textInput.value.trim(); | |
| if (!text) return; | |
| const selectedVoice = voiceSelect.value; | |
| // Update UI | |
| outputPlaceholder.textContent = `Generating "${selectedVoice}" voice...`; | |
| audioVisualization.classList.remove('hidden'); | |
| generateBtn.classList.add('hidden'); | |
| stopBtn.classList.remove('hidden'); | |
| isPlaying = true; | |
| // Create speech synthesis utterance | |
| utterance = new SpeechSynthesisUtterance(text); | |
| // Set voice properties based on selection | |
| switch(selectedVoice) { | |
| case 'Professional Male': | |
| utterance.rate = 1.0; | |
| utterance.pitch = 0.9; | |
| break; | |
| case 'Friendly Female': | |
| utterance.rate = 1.1; | |
| utterance.pitch = 1.2; | |
| break; | |
| case 'British Narrator': | |
| utterance.rate = 0.95; | |
| utterance.pitch = 0.85; | |
| break; | |
| } | |
| // Start animation | |
| animateBars(); | |
| // Update progress bar | |
| let startTime = Date.now(); | |
| let estimatedDuration = text.length * 50; // Rough estimate (ms) | |
| const progressInterval = setInterval(() => { | |
| const elapsed = Date.now() - startTime; | |
| const progress = Math.min(elapsed / estimatedDuration * 100, 100); | |
| progressBar.style.width = `${progress}%`; | |
| if (progress >= 100) { | |
| clearInterval(progressInterval); | |
| } | |
| }, 100); | |
| // On speech end | |
| utterance.onend = () => { | |
| isPlaying = false; | |
| generateBtn.classList.remove('hidden'); | |
| stopBtn.classList.add('hidden'); | |
| outputPlaceholder.textContent = `Voice generation complete for "${selectedVoice}"`; | |
| clearInterval(progressInterval); | |
| }; | |
| // On speech error | |
| utterance.onerror = (event) => { | |
| console.error('Speech synthesis error:', event); | |
| isPlaying = false; | |
| generateBtn.classList.remove('hidden'); | |
| stopBtn.classList.add('hidden'); | |
| outputPlaceholder.textContent = 'Error generating voice. Please try again.'; | |
| clearInterval(progressInterval); | |
| }; | |
| // Speak the text | |
| speechSynthesis.speak(utterance); | |
| }); | |
| // Stop generation | |
| stopBtn.addEventListener('click', () => { | |
| if (speechSynthesis.speaking) { | |
| speechSynthesis.cancel(); | |
| isPlaying = false; | |
| generateBtn.classList.remove('hidden'); | |
| stopBtn.classList.add('hidden'); | |
| outputPlaceholder.textContent = 'Voice generation stopped'; | |
| } | |
| }); | |
| // Play voice samples from cards | |
| const playButtons = document.querySelectorAll('.play-voice-btn'); | |
| playButtons.forEach(button => { | |
| button.addEventListener('click', (e) => { | |
| e.stopPropagation(); | |
| const card = button.closest('.voice-card'); | |
| const voiceName = card.dataset.voice; | |
| const sampleText = `This is a sample of the ${voiceName} voice from ElevenLabs.`; | |
| const utterance = new SpeechSynthesisUtterance(sampleText); | |
| // Set voice properties based on selection | |
| switch(voiceName) { | |
| case 'Professional Male': | |
| utterance.rate = 1.0; | |
| utterance.pitch = 0.9; | |
| break; | |
| case 'Friendly Female': | |
| utterance.rate = 1.1; | |
| utterance.pitch = 1.2; | |
| break; | |
| case 'British Narrator': | |
| utterance.rate = 0.95; | |
| utterance.pitch = 0.85; | |
| break; | |
| } | |
| speechSynthesis.speak(utterance); | |
| }); | |
| }); | |
| // Download functionality (simulated) | |
| downloadBtn.addEventListener('click', () => { | |
| const text = textInput.value.trim(); | |
| if (!text) return; | |
| const selectedVoice = voiceSelect.value; | |
| outputPlaceholder.textContent = `Preparing download for "${selectedVoice}" voice...`; | |
| // Simulate download preparation | |
| setTimeout(() => { | |
| outputPlaceholder.textContent = `Download ready for "${selectedVoice}" (simulated)`; | |
| // In a real implementation, this would download the audio file | |
| // For now, we'll just show a message | |
| alert('In a real implementation, this would download the generated voice as an MP3 file.'); | |
| }, 1500); | |
| }); | |
| // Voice card selection | |
| const voiceCards = document.querySelectorAll('.voice-card'); | |
| voiceCards.forEach(card => { | |
| card.addEventListener('click', () => { | |
| const voiceName = card.dataset.voice; | |
| voiceSelect.value = voiceName; | |
| // Update active state | |
| voiceCards.forEach(c => { | |
| c.querySelector('span').className = 'text-xs px-2 py-1 bg-gray-100 text-gray-800 rounded'; | |
| }); | |
| card.querySelector('span').className = 'text-xs px-2 py-1 bg-green-100 text-green-800 rounded'; | |
| }); | |
| }); | |
| }); | |
| </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=geadmin/ideas" style="color: #fff;text-decoration: underline;" target="_blank" >🧬 Remix</a></p></body> | |
| </html> |