11lab_via_api / index.html
Offex's picture
Update index.html
5169bfd verified
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>11Labs Safe TTS Tool</title>
<style>
body { font-family: Arial, sans-serif; max-width: 600px; margin: 40px auto; padding: 20px; background-color: #f4f4f9; }
.container { background: white; padding: 20px; border-radius: 10px; box-shadow: 0 4px 8px rgba(0,0,0,0.1); }
h2 { text-align: center; color: #333; }
label { font-weight: bold; display: block; margin-top: 15px; }
input, textarea, select { width: 100%; padding: 10px; margin-top: 5px; border: 1px solid #ccc; border-radius: 5px; box-sizing: border-box; }
.btn { width: 100%; color: white; padding: 12px; border: none; border-radius: 5px; margin-top: 15px; cursor: pointer; font-size: 16px; font-weight: bold; transition: 0.3s; }
.btn-blue { background-color: #007bff; }
.btn-blue:hover { background-color: #0056b3; }
.btn-green { background-color: #28a745; }
.btn-green:hover:not(:disabled) { background-color: #218838; }
.btn:disabled { background-color: #6c757d; cursor: not-allowed; }
#audioContainer { margin-top: 20px; text-align: center; display: none; padding: 15px; background: #e9ecef; border-radius: 8px; }
.status-box { text-align: center; margin-top: 15px; padding: 10px; border-radius: 5px; font-weight: bold; display: none; transition: 0.3s; }
.status-loading { background-color: #fff3cd; color: #856404; display: block; }
.status-success { background-color: #d4edda; color: #155724; display: block; }
.status-error { background-color: #f8d7da; color: #721c24; display: block; }
#customVoiceDiv { display: none; margin-top: 10px; padding: 10px; background: #fff8e1; border-left: 4px solid #ffc107; border-radius: 4px; }
</style>
</head>
<body>
<div class="container">
<h2>11Labs Safe TTS (No IP Block)</h2>
<label for="apiKey">ElevenLabs API Key:</label>
<input type="password" id="apiKey" placeholder="Apni API key yahan daalein..." required>
<button class="btn btn-blue" onclick="connectAPI()" id="connectBtn">Connect API & Load Voices</button>
<label for="voiceDropdown">Select Voice:</label>
<select id="voiceDropdown" onchange="toggleCustomVoice()">
<option value="">-- Pehle API Connect Karein --</option>
<option value="custom">✏️ Enter Custom Voice ID</option>
</select>
<div id="customVoiceDiv">
<label for="customVoiceId">Custom Voice ID:</label>
<input type="text" id="customVoiceId" placeholder="Voice ID paste karein (e.g., EXAVITQu4vr4xnSDxMaL)">
</div>
<label for="modelSelect">Select Model:</label>
<select id="modelSelect">
<option value="eleven_multilingual_v2">Multilingual v2 (Best for most)</option>
<option value="eleven_multilingual_v1">Multilingual v1</option>
<option value="eleven_monolingual_v1">Monolingual v1 (English only)</option>
</select>
<label for="text">Text to Speech:</label>
<textarea id="text" rows="5" placeholder="Jo bulwana hai yahan type karein..." required></textarea>
<button class="btn btn-green" onclick="generateAudio()" id="generateBtn">Generate Audio</button>
<div id="statusBox" class="status-box"></div>
<div id="audioContainer">
<audio id="audioPlayer" controls style="width: 100%;"></audio>
<br><br>
<a id="downloadLink" download="generated_audio.mp3" style="text-decoration: none; background: #007bff; color: white; padding: 10px 20px; border-radius: 5px; display: inline-block;">Download MP3</a>
</div>
</div>
<script>
// API Connect karke Voices load karna
async function connectAPI() {
const apiKey = document.getElementById('apiKey').value.trim();
const connectBtn = document.getElementById('connectBtn');
const voiceDropdown = document.getElementById('voiceDropdown');
if (!apiKey) {
showStatus('कृपया पहले API Key डालें!', 'error');
return;
}
showStatus('Voices लोड हो रही हैं... ⏳', 'loading');
connectBtn.disabled = true;
try {
const response = await fetch('https://api.elevenlabs.io/v1/voices', {
method: 'GET',
headers: { 'xi-api-key': apiKey }
});
if (!response.ok) {
throw new Error("API Key गलत है या नेटवर्क समस्या है!");
}
const data = await response.json();
// Dropdown clear karke naye options daalna
voiceDropdown.innerHTML = '<option value="custom">✏️ Enter Custom Voice ID</option>';
data.voices.forEach(voice => {
const option = document.createElement('option');
option.value = voice.voice_id;
option.textContent = voice.name;
voiceDropdown.appendChild(option);
});
// Default pehli voice select karna agar available ho
if (data.voices.length > 0) {
voiceDropdown.value = data.voices[0].voice_id;
}
toggleCustomVoice(); // Custom box ko hide karne ke liye
showStatus('API Connected! ' + data.voices.length + ' Voices लोड हो गईं ✅', 'success');
} catch (error) {
showStatus('Error: ' + error.message, 'error');
} finally {
connectBtn.disabled = false;
}
}
// Custom Voice ID box ko dikhana ya chhupana
function toggleCustomVoice() {
const dropdown = document.getElementById('voiceDropdown');
const customDiv = document.getElementById('customVoiceDiv');
if (dropdown.value === 'custom') {
customDiv.style.display = 'block';
} else {
customDiv.style.display = 'none';
}
}
// Audio Generate karna
async function generateAudio() {
const apiKey = document.getElementById('apiKey').value.trim();
const modelId = document.getElementById('modelSelect').value;
const text = document.getElementById('text').value.trim();
const dropdown = document.getElementById('voiceDropdown');
let voiceId = dropdown.value;
if (voiceId === 'custom') {
voiceId = document.getElementById('customVoiceId').value.trim();
}
const audioContainer = document.getElementById('audioContainer');
const audioPlayer = document.getElementById('audioPlayer');
const downloadLink = document.getElementById('downloadLink');
const generateBtn = document.getElementById('generateBtn');
if (!apiKey || !text || !voiceId) {
showStatus('कृपया API Key, Voice ID और Text भरें!', 'error');
return;
}
audioContainer.style.display = "none";
showStatus('Audio जनरेट हो रहा है, कृपया प्रतीक्षा करें... ⏳', 'loading');
generateBtn.disabled = true;
generateBtn.innerText = "Processing...";
try {
const response = await fetch(`https://api.elevenlabs.io/v1/text-to-speech/${voiceId}`, {
method: 'POST',
headers: {
'Accept': 'audio/mpeg',
'xi-api-key': apiKey,
'Content-Type': 'application/json'
},
body: JSON.stringify({
text: text,
model_id: modelId,
voice_settings: {
stability: 0.5,
similarity_boost: 0.5
}
})
});
if (!response.ok) {
const errData = await response.json();
throw new Error(errData.detail.message || "API request फेल हो गई!");
}
const blob = await response.blob();
const audioUrl = URL.createObjectURL(blob);
audioPlayer.src = audioUrl;
downloadLink.href = audioUrl;
audioContainer.style.display = "block";
showStatus('Audio तैयार है! 🎉', 'success');
} catch (error) {
showStatus('Error: ' + error.message, 'error');
} finally {
generateBtn.disabled = false;
generateBtn.innerText = "Generate Audio";
}
}
function showStatus(message, type) {
const statusBox = document.getElementById('statusBox');
statusBox.innerText = message;
statusBox.className = 'status-box';
if(type === 'loading') statusBox.classList.add('status-loading');
if(type === 'success') statusBox.classList.add('status-success');
if(type === 'error') statusBox.classList.add('status-error');
}
</script>
</body>
</html>