from src.config import ELEVENLABS_API_KEY DESCRIPTION_JS = """function createGradioAnimation() { // Create main container var container = document.createElement('div'); container.id = 'gradio-animation'; container.style.padding = '2rem'; container.style.background = 'transparent'; container.style.borderRadius = '12px'; container.style.margin = '0 0 2rem 0'; container.style.maxWidth = '100%'; container.style.transition = 'all 0.3s ease'; // Create header section var header = document.createElement('div'); header.style.textAlign = 'center'; header.style.marginBottom = '2rem'; container.appendChild(header); // Title with spaces var titleText = 'AI Audio Books 📕👨‍💻🎧'; var title = document.createElement('h1'); title.style.fontSize = '2.5rem'; title.style.fontWeight = '700'; title.style.color = '#f1f1f1'; title.style.marginBottom = '1.5rem'; title.style.opacity = '0'; // Start with opacity 0 title.style.transition = 'opacity 0.5s ease'; // Add transition title.innerText = titleText; header.appendChild(title); // Add description var description = document.createElement('p'); description.innerHTML = `
Create an audiobook from the input text automatically, using Gen-AI!
All you need to do - is to input the book text or select it from the provided Sample Inputs.
`; description.style.opacity = '0'; description.style.transition = 'opacity 0.5s ease'; header.appendChild(description); // Create process section var processSection = document.createElement('div'); processSection.style.backgroundColor = 'rgba(255, 255, 255, 0.05)'; processSection.style.padding = '1.5rem'; processSection.style.borderRadius = '8px'; processSection.style.marginTop = '1rem'; container.appendChild(processSection); // Add "AI will do the rest:" header var processHeader = document.createElement('div'); processHeader.style.fontSize = '1.2rem'; processHeader.style.fontWeight = '600'; processHeader.style.color = '#e0e0e0'; processHeader.style.marginBottom = '1rem'; processHeader.innerHTML = 'AI will do the rest:'; processHeader.style.opacity = '0'; processHeader.style.transition = 'opacity 0.5s ease'; processSection.appendChild(processHeader); // Define steps with icons var steps = [ { text: 'Split text into characters', icon: '📚' }, { text: 'Select voice for each character', icon: '🎭' }, { text: 'Enhance text to convey emotions and intonations during Text-to-Speech', icon: '😊' }, { text: 'Generate audiobook using Text-to-Speech model', icon: '🎧' }, { text: 'Generate sound effects to create immersive atmosphere (optional)', icon: '🎵' }, { text: 'Clone your voice to generate the audiobook (optional)', icon: '💥' }, ]; // Create steps list var stepsList = document.createElement('div'); stepsList.style.opacity = '0'; stepsList.style.transition = 'opacity 0.5s ease'; processSection.appendChild(stepsList); steps.forEach(function(step, index) { var stepElement = document.createElement('div'); stepElement.style.display = 'flex'; stepElement.style.alignItems = 'center'; stepElement.style.padding = '0.8rem'; stepElement.style.marginBottom = '0.5rem'; stepElement.style.backgroundColor = 'rgba(255, 255, 255, 0.03)'; stepElement.style.borderRadius = '6px'; stepElement.style.transform = 'translateX(-20px)'; stepElement.style.opacity = '0'; stepElement.style.transition = 'all 0.3s ease'; // Add hover effect stepElement.onmouseover = function() { this.style.backgroundColor = 'rgba(255, 255, 255, 0.07)'; }; stepElement.onmouseout = function() { this.style.backgroundColor = 'rgba(255, 255, 255, 0.03)'; }; var icon = document.createElement('span'); icon.style.marginRight = '1rem'; icon.style.fontSize = '1.2rem'; icon.innerText = step.icon; stepElement.appendChild(icon); var text = document.createElement('span'); text.style.color = '#c0c0c0'; text.style.fontSize = '1rem'; text.innerText = step.text; stepElement.appendChild(text); stepsList.appendChild(stepElement); }); // Insert into Gradio container var gradioContainer = document.querySelector('.gradio-container'); gradioContainer.insertBefore(container, gradioContainer.firstChild); // New timing for animations setTimeout(function() { title.style.opacity = '1'; }, 250); // Show description after 1 second setTimeout(function() { description.style.opacity = '1'; processHeader.style.opacity = '1'; }, 700); // Show steps after 2 seconds setTimeout(function() { stepsList.style.opacity = '1'; stepsList.querySelectorAll('div').forEach(function(step, index) { setTimeout(function() { step.style.transform = 'translateX(0)'; step.style.opacity = '1'; }, index * 100); }); }, 1100); async function playAudio(url) { try { const audio = new Audio(url); await audio.play(); } catch (error) { console.error('Error playing audio:', error); } } // Add click handler to all audio links document.addEventListener('click', function(e) { if (e.target.classList.contains('audio-link')) { e.preventDefault(); playAudio(e.target.getAttribute('data-audio-url')); } }); return 'Animation created'; }""" STATUS_DISPLAY_HTML = '''

Status: Waiting to Start

Enter text or upload a file to begin.

''' GRADIO_THEME = "freddyaboulton/dracula_revamped" VOICE_UPLOAD_JS = f""" async function createVoiceUploadPopup() {{ try {{ let savedVoiceId = null; const result = await new Promise((resolve, reject) => {{ // Create overlay with soft animation const overlay = document.createElement('div'); Object.assign(overlay.style, {{ position: 'fixed', top: '0', left: '0', width: '100%', height: '100%', backgroundColor: 'rgba(0, 0, 0, 0.8)', display: 'flex', justifyContent: 'center', alignItems: 'center', zIndex: '1000', opacity: '0', transition: 'opacity 0.3s ease-in-out' }}); overlay.offsetHeight; // Trigger reflow for transition overlay.style.opacity = '1'; // Create popup container with modern design const popup = document.createElement('div'); Object.assign(popup.style, {{ backgroundColor: '#3b4c63', padding: '30px', borderRadius: '12px', width: '450px', maxWidth: '95%', position: 'relative', boxShadow: '0 10px 25px rgba(0, 0, 0, 0.3)', transform: 'scale(0.9)', transition: 'transform 0.3s ease-out', display: 'flex', flexDirection: 'column', alignItems: 'center' }}); popup.offsetHeight; // Trigger reflow popup.style.transform = 'scale(1)'; // Create close button const closeBtn = document.createElement('button'); Object.assign(closeBtn.style, {{ position: 'absolute', right: '15px', top: '15px', border: 'none', background: 'none', fontSize: '24px', cursor: 'pointer', color: '#d3d3d3', transition: 'color 0.2s ease' }}); closeBtn.innerHTML = '✕'; closeBtn.onmouseover = () => closeBtn.style.color = '#ffffff'; closeBtn.onmouseout = () => closeBtn.style.color = '#d3d3d3'; // Create content const content = document.createElement('div'); content.innerHTML = `

Upload Voice Sample

Select an audio file to create audiobook with your unique voice.

`; // Add elements to DOM popup.appendChild(closeBtn); popup.appendChild(content); overlay.appendChild(popup); document.body.appendChild(overlay); // Button effects const uploadBtn = popup.querySelector('#uploadBtn'); uploadBtn.onmouseover = () => uploadBtn.style.backgroundColor = '#3b5c77'; uploadBtn.onmouseout = () => uploadBtn.style.backgroundColor = '#4a6f91'; uploadBtn.onmousedown = () => uploadBtn.style.transform = 'scale(0.98)'; uploadBtn.onmouseup = () => uploadBtn.style.transform = 'scale(1)'; // Handle close const handleClose = () => {{ overlay.style.opacity = '0'; setTimeout(() => {{ overlay.remove(); resolve(savedVoiceId); }}, 300); }}; closeBtn.onclick = handleClose; overlay.onclick = (e) => {{ if (e.target === overlay) {{ handleClose(); }} }}; // Handle file upload const statusDiv = popup.querySelector('#uploadStatus'); const fileInput = popup.querySelector('#voiceFile'); uploadBtn.onclick = async () => {{ const file = fileInput.files[0]; if (!file) {{ statusDiv.textContent = 'Please select a file first.'; statusDiv.style.color = '#e74c3c'; return; }} const API_KEY = "{ELEVENLABS_API_KEY}"; statusDiv.textContent = 'Uploading...'; statusDiv.style.color = '#4a6f91'; uploadBtn.disabled = true; uploadBtn.style.backgroundColor = '#6c8091'; const formData = new FormData(); formData.append('files', file); formData.append('name', `voice_${{Date.now()}}`); try {{ const response = await fetch('https://api.elevenlabs.io/v1/voices/add', {{ method: 'POST', headers: {{ 'Accept': 'application/json', 'xi-api-key': API_KEY }}, body: formData }}); const result = await response.json(); if (response.ok) {{ savedVoiceId = result.voice_id statusDiv.innerHTML = `
Voice uploaded successfully!
Your Voice ID: ${{result.voice_id}}
`; // Update the visible HTML panel const voiceIdPanel = document.querySelector('#voice_id_panel'); if (voiceIdPanel) {{ voiceIdPanel.innerHTML = `Your voice_id from uploaded audio is ${{result.voice_id}}`; }} setTimeout(() => {{ overlay.style.opacity = '0'; setTimeout(() => {{ overlay.remove(); resolve(result.voice_id); // Resolve with the voice ID }}, 300); }}, 3000); }} else {{ throw new Error(result.detail?.message || 'Upload failed'); }} }} catch (error) {{ statusDiv.innerHTML = `
Error: ${{error.message}}
`; uploadBtn.disabled = false; uploadBtn.style.backgroundColor = '#4a6f91'; }} }}; }}); return result; // Return the voice ID from the Promise }} catch (error) {{ console.error('Error in createVoiceUploadPopup:', error); return null; }} }} """ EFFECT_CSS = """\ """