TTSFM_LAGECY / static /index.html
NitinBot001's picture
Upload 28 files
64cfce9 verified
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>ttsfm</title>
<link rel="stylesheet" href="styles.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/themes/prism-tomorrow.min.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/prism.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/components/prism-python.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/components/prism-json.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/components/prism-javascript.min.js"></script>
</head>
<body>
<div class="app-container">
<div class="content-wrapper">
<!-- Header Section -->
<header class="main-header">
<div class="header-top">
<h1>ttsfm</h1>
<a href="https://github.com/dbccccccc/ttsfm" target="_blank" class="github-link">
<i class="fab fa-github"></i>
<span>GitHub</span>
</a>
</div>
<p class="subtitle">Text-to-Speech API with Multiple Voice Options</p>
<div class="header-bottom">
<div class="version-badge">
<span>Version: <strong id="version">1.3.0</strong></span>
</div>
<div class="language-selector">
<button class="lang-btn active" data-lang="en">English</button>
<a href="index_zh.html" class="lang-btn">中文</a>
</div>
</div>
</header>
<!-- Disclaimer Section -->
<section class="content-section disclaimer-notice">
<div class="disclaimer-container">
<div class="disclaimer-icon">
<i class="fas fa-info-circle"></i>
</div>
<div class="disclaimer-content">
<h2>Disclaimer</h2>
<p>This project is for learning & testing purposes only. For production use, please use the official OpenAI TTS service at <a href="https://platform.openai.com/docs/guides/audio" target="_blank">https://platform.openai.com/docs/guides/audio</a>.</p>
</div>
</div>
</section>
<!-- Status Section -->
<section class="content-section status-section">
<h2>Service Status</h2>
<div class="status-container">
<div class="status-card">
<div class="status-header">
<h3>Queue Status</h3>
<div class="status-indicator" id="status-indicator"></div>
</div>
<div class="queue-stats">
<div class="stat-item">
<span class="stat-label">Active Requests:</span>
<span class="stat-value" id="queue-size">0</span>
</div>
<div class="stat-item">
<span class="stat-label">Maximum Capacity:</span>
<span class="stat-value" id="max-queue-size">-</span>
</div>
</div>
<div class="queue-progress-container">
<div class="queue-progress-bar" id="queue-progress-bar"></div>
</div>
<div class="queue-load-text" id="queue-load-text">No Load</div>
</div>
</div>
</section>
<!-- Playground Section -->
<section class="content-section playground-section">
<h2>Try It Out</h2>
<div class="playground-container">
<div class="playground-form">
<div class="form-group">
<label for="playground-text">Text to Convert</label>
<textarea id="playground-text" rows="4" placeholder="Enter the text you want to convert to speech..."></textarea>
</div>
<div class="form-group">
<label for="playground-instructions">Instructions</label>
<textarea id="playground-instructions" rows="2" placeholder="e.g., Speak in a cheerful and upbeat tone"></textarea>
</div>
<div class="form-group">
<label for="playground-voice">Voice</label>
<select id="playground-voice">
<option value="alloy">Alloy</option>
<option value="ash">Ash</option>
<option value="ballad">Ballad</option>
<option value="coral">Coral</option>
<option value="echo">Echo</option>
<option value="fable">Fable</option>
<option value="onyx">Onyx</option>
<option value="nova">Nova</option>
<option value="sage">Sage</option>
<option value="shimmer">Shimmer</option>
<option value="verse">Verse</option>
</select>
</div>
<div class="form-group">
<label for="playground-format">Response Format</label>
<select id="playground-format">
<option value="mp3">MP3</option>
<option value="opus">Opus</option>
<option value="aac">AAC</option>
<option value="flac">FLAC</option>
<option value="wav">WAV</option>
<option value="pcm">PCM</option>
</select>
</div>
<button id="playground-submit" class="playground-button">
<i class="fas fa-play"></i> Generate Speech
</button>
</div>
<div class="playground-output">
<div class="audio-section">
<h3>Voice Preview</h3>
<div id="preview-audio" class="audio-player"></div>
</div>
<div class="audio-section">
<h3>Generated Result</h3>
<div id="playground-status" class="playground-status"></div>
<div id="playground-audio" class="audio-player"></div>
</div>
</div>
</div>
</section>
<!-- Main Content -->
<main class="main-content">
<!-- Quick Start -->
<section class="content-section">
<h2>Quick Start</h2>
<p>Choose your preferred programming language to get started with the API:</p>
<!-- Python Example -->
<div class="code-block">
<div class="code-header">
<span class="code-language">Python</span>
<button class="copy-button" onclick="copyCode(this)">
<i class="fas fa-copy"></i>
</button>
</div>
<pre><code class="language-python">
import requests
import os
def generate_speech(text, voice="alloy", format="mp3", instructions=None):
url = "https://ttsapi.site/v1/audio/speech"
headers = {
"Content-Type": "application/json"
}
data = {
"input": text,
"voice": voice,
"response_format": format
}
# Add instructions if provided
if instructions:
data["instructions"] = instructions
response = requests.post(url, json=data, headers=headers)
if response.status_code == 200:
# Get the appropriate file extension based on format
ext = format.lower()
filename = f"output.{ext}"
# Save the audio file
with open(filename, "wb") as f:
f.write(response.content)
print(f"Audio saved as {filename}")
return filename
else:
error = response.json()
print(f"Error: {response.status_code}, {error}")
return None
# Example usage
text = "Hello, this is a test."
voice = "alloy"
format = "mp3" # Supported formats: mp3, opus, aac, flac, wav, pcm
instructions = "Speak in a cheerful and upbeat tone."
# Generate speech with default format (MP3)
generate_speech(text, voice, instructions=instructions)
# Generate speech in WAV format
generate_speech(text, voice, format="wav", instructions=instructions)</code></pre>
</div>
<!-- JavaScript Example -->
<div class="code-block">
<div class="code-header">
<span class="code-language">JavaScript</span>
<button class="copy-button" onclick="copyCode(this)">
<i class="fas fa-copy"></i>
</button>
</div>
<pre><code class="language-javascript">async function generateSpeech(text, voice = 'alloy', format = 'mp3', instructions = null) {
const response = await fetch('https://ttsapi.site/v1/audio/speech', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
input: text,
voice: voice,
response_format: format,
...(instructions && { instructions })
})
});
if (response.ok) {
const blob = await response.blob();
// Create audio element for playback
const audio = new Audio(URL.createObjectURL(blob));
audio.play();
// Optional: Download the file
const url = window.URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = `output.${format}`;
document.body.appendChild(a);
a.click();
window.URL.revokeObjectURL(url);
document.body.removeChild(a);
return blob;
} else {
const error = await response.json();
console.error('Error:', error);
throw error;
}
}
// Example usage
const text = 'Hello, this is a test.';
const voice = 'alloy';
const format = 'mp3'; // Supported formats: mp3, opus, aac, flac, wav, pcm
const instructions = 'Speak in a cheerful and upbeat tone.';
// Generate speech with default format (MP3)
generateSpeech(text, voice, undefined, instructions);
// Generate speech in WAV format
generateSpeech(text, voice, 'wav', instructions);</code></pre>
</div>
</section>
<!-- Available Voices -->
<section class="content-section">
<h2>Available Voices</h2>
<div class="voice-list">
<span class="voice-name">alloy</span>
<span class="voice-name">ash</span>
<span class="voice-name">ballad</span>
<span class="voice-name">coral</span>
<span class="voice-name">echo</span>
<span class="voice-name">fable</span>
<span class="voice-name">onyx</span>
<span class="voice-name">nova</span>
<span class="voice-name">sage</span>
<span class="voice-name">shimmer</span>
<span class="voice-name">verse</span>
</div>
</section>
<!-- API Reference -->
<section class="content-section">
<h2>API Reference</h2>
<div class="api-endpoint">
<h3>Generate Speech (OpenAI Compatible)</h3>
<pre><code class="language-http">POST /v1/audio/speech</code></pre>
<div class="request-body">
<h4>Request Parameters</h4>
<table class="params-table">
<tr>
<th>Parameter</th>
<th>Type</th>
<th>Required</th>
<th>Description</th>
</tr>
<tr>
<td>input</td>
<td>string</td>
<td>Yes</td>
<td>The text to convert to speech</td>
</tr>
<tr>
<td>voice</td>
<td>string</td>
<td>Yes</td>
<td>The voice to use (see Available Voices)</td>
</tr>
<tr>
<td class="partial-param">instructions</td>
<td>string</td>
<td>No</td>
<td><em>Mapped to "prompt" parameter when sent to the backend service. Can be used to guide voice emotion or style.</em></td>
</tr>
<tr>
<td class="partial-param">response_format</td>
<td>string</td>
<td>No</td>
<td>The format of the audio response. Supported formats: mp3, opus, aac, flac, wav, pcm. Defaults to mp3.</td>
</tr>
<tr>
<td class="compat-param">model</td>
<td>string</td>
<td>No</td>
<td><em>OpenAI compatibility only - completely ignored.</em></td>
</tr>
<tr>
<td class="compat-param">speed</td>
<td>number</td>
<td>No</td>
<td><em>OpenAI compatibility only - completely ignored.</em></td>
</tr>
</table>
<div class="compatibility-notice">
<p><strong>Note:</strong> Parameters in <span class="compat-inline">gray</span> are completely ignored by the service or may cause misleading behavior. Only <code>input</code>, <code>voice</code>, <code>response_format</code> and <code>instructions</code> affect the actual TTS output.</p>
</div>
<!-- Instructions Parameter Details -->
<div class="parameter-details">
<h4>How the Instructions Parameter Works</h4>
<p>The <code>instructions</code> parameter is mapped to a <code>prompt</code> parameter when sent to the backend service. It can be used to guide the voice emotion, tone, or style. Some examples of effective instructions:</p>
<ul class="examples-list">
<li><strong>Emotional guidance:</strong> "Speak in a happy and excited tone."</li>
<li><strong>Character impersonation:</strong> "Speak like a wise old wizard."</li>
<li><strong>Contextual hints:</strong> "This is being read to a child, speak gently."</li>
<li><strong>Reading style:</strong> "Read this as a news broadcast."</li>
</ul>
<div class="tip-box">
<p><strong>Tip:</strong> Keep instructions clear and concise. Overly complex instructions may not be interpreted correctly.</p>
</div>
</div>
<h4>Response Format</h4>
<p>The API returns audio in the requested format with the following headers:</p>
<ul>
<li><code>Content-Type</code>: Based on the requested format (e.g., "audio/mpeg" for MP3)</li>
<li><code>Access-Control-Allow-Origin</code>: "*" (CORS enabled)</li>
</ul>
<h4>Error Responses</h4>
<table class="error-table">
<tr>
<th>Status Code</th>
<th>Description</th>
</tr>
<tr>
<td>400</td>
<td>Missing required parameters (input or voice)</td>
</tr>
<tr>
<td>429</td>
<td>Rate limit exceeded or queue is full. Includes Retry-After header when rate limited.</td>
</tr>
<tr>
<td>500</td>
<td>Internal server error</td>
</tr>
</table>
</div>
</div>
<!-- Queue System -->
<div class="api-endpoint">
<h3>Queue System</h3>
<p>The API uses a queue system to handle multiple requests efficiently:</p>
<ul>
<li>Maximum queue size: Configurable via <code>MAX_QUEUE_SIZE</code> environment variable (default: 100 requests)</li>
<li>Requests are processed in FIFO (First In, First Out) order</li>
<li>Rate limiting: Configurable via <code>RATE_LIMIT_REQUESTS</code> and <code>RATE_LIMIT_WINDOW</code> environment variables (default: 30 requests per 60 seconds per IP address)</li>
<li>Queue status can be monitored via the <code>/api/queue-size</code> endpoint</li>
<li>Queue status updates every 2 seconds in the web interface</li>
<li>Visual indicators show queue load (Low/Medium/High) based on utilization</li>
</ul>
<h4>Queue Status Endpoint</h4>
<pre><code class="language-http">GET /api/queue-size</code></pre>
<p>Returns JSON with queue information:</p>
<pre><code class="language-json">{
"queue_size": 0, // Current number of requests in queue
"max_queue_size": 100 // Maximum queue capacity
}</code></pre>
<div class="response-codes">
<h4>Response Status Codes</h4>
<ul>
<li><code>200</code> - Success</li>
<li><code>429</code> - Queue is full or rate limit exceeded</li>
<li><code>500</code> - Server error</li>
</ul>
</div>
</div>
</section>
</main>
</div>
</div>
<script src="script.js"></script>
</body>
</html>