| <!DOCTYPE html> |
| <html lang="en"> |
| <head> |
| <meta charset="utf-8" /> |
| <meta name="viewport" content="width=device-width, initial-scale=1.0" /> |
| <title>Indic TTS — Swadesh</title> |
| <style> |
| * { margin: 0; padding: 0; box-sizing: border-box; } |
| body { |
| font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; |
| background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); |
| min-height: 100vh; |
| display: flex; |
| align-items: center; |
| justify-content: center; |
| padding: 20px; |
| } |
| .container { |
| background: white; |
| border-radius: 16px; |
| padding: 32px; |
| max-width: 600px; |
| width: 100%; |
| box-shadow: 0 20px 60px rgba(0,0,0,0.3); |
| } |
| h1 { |
| text-align: center; |
| margin-bottom: 8px; |
| color: #333; |
| font-size: 1.6em; |
| } |
| .subtitle { |
| text-align: center; |
| color: #888; |
| margin-bottom: 24px; |
| font-size: 0.9em; |
| } |
| label { |
| display: block; |
| margin-bottom: 6px; |
| font-weight: 600; |
| color: #555; |
| font-size: 0.9em; |
| } |
| textarea { |
| width: 100%; |
| padding: 12px; |
| border: 2px solid #e0e0e0; |
| border-radius: 8px; |
| font-size: 16px; |
| resize: vertical; |
| min-height: 100px; |
| font-family: inherit; |
| transition: border-color 0.2s; |
| } |
| textarea:focus { outline: none; border-color: #667eea; } |
| select { |
| width: 100%; |
| padding: 12px; |
| border: 2px solid #e0e0e0; |
| border-radius: 8px; |
| font-size: 16px; |
| background: white; |
| cursor: pointer; |
| margin-bottom: 20px; |
| } |
| select:focus { outline: none; border-color: #667eea; } |
| .btn { |
| width: 100%; |
| padding: 14px; |
| background: linear-gradient(135deg, #667eea, #764ba2); |
| color: white; |
| border: none; |
| border-radius: 8px; |
| font-size: 16px; |
| font-weight: 600; |
| cursor: pointer; |
| transition: opacity 0.2s; |
| } |
| .btn:hover { opacity: 0.9; } |
| .btn:disabled { opacity: 0.5; cursor: not-allowed; } |
| .status { |
| margin-top: 16px; |
| padding: 12px; |
| border-radius: 8px; |
| text-align: center; |
| font-size: 0.9em; |
| display: none; |
| } |
| .status.loading { display: block; background: #fff3cd; color: #856404; } |
| .status.error { display: block; background: #f8d7da; color: #721c24; } |
| .status.success { display: block; background: #d4edda; color: #155724; } |
| audio { |
| width: 100%; |
| margin-top: 16px; |
| display: none; |
| } |
| .footer { |
| text-align: center; |
| margin-top: 20px; |
| color: #aaa; |
| font-size: 0.8em; |
| } |
| </style> |
| </head> |
| <body> |
| <div class="container"> |
| <h1>Indic TTS — Swadesh</h1> |
| <p class="subtitle">21 Indian Languages — AI4Bharat Model</p> |
|
|
| <label for="text">Text</label> |
| <textarea id="text" placeholder="Type text here... / yahan text likhein..."></textarea> |
|
|
| <label for="lang">Language</label> |
| <select id="lang"> |
| <option value="hi">Hindi</option> |
| <option value="bn">Bengali</option> |
| <option value="ta">Tamil</option> |
| <option value="te">Telugu</option> |
| <option value="mr">Marathi</option> |
| <option value="kn">Kannada</option> |
| <option value="ml">Malayalam</option> |
| <option value="gu">Gujarati</option> |
| <option value="or">Odia</option> |
| <option value="ur">Urdu</option> |
| <option value="en">English</option> |
| <option value="as">Assamese</option> |
| <option value="ne">Nepali</option> |
| <option value="sa">Sanskrit</option> |
| <option value="mai">Maithili</option> |
| <option value="brx">Bodo</option> |
| <option value="doi">Dogri</option> |
| <option value="kok">Konkani</option> |
| <option value="mni">Manipuri</option> |
| <option value="sat">Santali</option> |
| <option value="sd">Sindhi</option> |
| </select> |
|
|
| <button class="btn" id="btn" onclick="generate()">Generate Speech</button> |
|
|
| <div class="status" id="status"></div> |
| <audio id="audio" controls></audio> |
|
|
| <p class="footer">Powered by <a href="https://huggingface.co/spaces/ai4bharat/indic-parler-tts" target="_blank">AI4Bharat Indic Parler-TTS</a></p> |
| </div> |
|
|
| <script type="module"> |
| import { Client } from "https://cdn.jsdelivr.net/npm/@gradio/client/dist/index.min.js"; |
| |
| const LANG_NAMES = { |
| as:"Assamese", bn:"Bengali", brx:"Bodo", doi:"Dogri", |
| en:"English", gu:"Gujarati", hi:"Hindi", kn:"Kannada", |
| kok:"Konkani", mai:"Maithili", ml:"Malayalam", mni:"Manipuri", |
| mr:"Marathi", ne:"Nepali", or:"Odia", sa:"Sanskrit", |
| sat:"Santali", sd:"Sindhi", ta:"Tamil", te:"Telugu", ur:"Urdu" |
| }; |
| const SPEAKER_NAMES = { |
| as:"Sita", bn:"Aditi", brx:"Maya", doi:"Karan", |
| en:"Mary", gu:"Neha", hi:"Divya", kn:"Anu", |
| kok:"Sita", mai:"Sita", ml:"Anjali", mni:"Laishram", |
| mr:"Sunita", ne:"Amrita", or:"Debjani", sa:"Aryan", |
| sat:"Sita", sd:"Sita", ta:"Jaya", te:"Lalitha", ur:"Sita" |
| }; |
| |
| let client = null; |
| |
| async function getClient() { |
| if (!client) { |
| const status = document.getElementById("status"); |
| status.className = "status loading"; |
| status.textContent = "Connecting to AI4Bharat server..."; |
| status.style.display = "block"; |
| client = await Client.connect("https://indic-tts-api.onrender.com/"); |
| status.style.display = "none"; |
| } |
| return client; |
| } |
| |
| window.generate = async function() { |
| const text = document.getElementById("text").value.trim(); |
| const lang = document.getElementById("lang").value; |
| const btn = document.getElementById("btn"); |
| const status = document.getElementById("status"); |
| const audio = document.getElementById("audio"); |
| |
| if (!text) { |
| status.className = "status error"; |
| status.textContent = "Please enter some text."; |
| status.style.display = "block"; |
| return; |
| } |
| |
| btn.disabled = true; |
| btn.textContent = "Generating..."; |
| audio.style.display = "none"; |
| status.className = "status loading"; |
| status.textContent = "Loading model & generating speech... This may take 30-60 seconds on first use."; |
| status.style.display = "block"; |
| |
| try { |
| const c = await getClient(); |
| const speaker = SPEAKER_NAMES[lang] || "Divya"; |
| const langName = LANG_NAMES[lang] || "Hindi"; |
| const description = speaker + " speaks " + langName + " fluently with a native accent. Her voice is clear, warm, and expressive, with a moderate pace and pitch, using a friendly storytelling tone suited for children. The recording is of very high quality, with the speaker's voice sounding close up and easy to understand, in a quiet room with no background noise."; |
| |
| const result = await c.predict("/generate_tts", [text, description]); |
| |
| if (result.data && result.data[0]) { |
| const audioData = result.data[0]; |
| let audioUrl; |
| if (typeof audioData === "object" && audioData.url) { |
| audioUrl = audioData.url; |
| } else if (typeof audioData === "string") { |
| audioUrl = audioData; |
| } else { |
| audioUrl = URL.createObjectURL(new Blob([new Uint8Array(audioData)], { type: "audio/wav" })); |
| } |
| audio.src = audioUrl; |
| audio.style.display = "block"; |
| audio.play(); |
| status.className = "status success"; |
| status.textContent = "Audio generated successfully!"; |
| } else { |
| throw new Error("No audio data received"); |
| } |
| } catch (err) { |
| status.className = "status error"; |
| status.textContent = "Error: " + err.message + ". The AI4Bharat server may be temporarily down. Try again later."; |
| console.error(err); |
| } finally { |
| btn.disabled = false; |
| btn.textContent = "Generate Speech"; |
| } |
| }; |
| </script> |
| </body> |
| </html> |
|
|