TTSFM_LAGECY / static /index_zh.html
NitinBot001's picture
Upload 28 files
64cfce9 verified
<!DOCTYPE html>
<html lang="zh">
<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">支持多种语音的文本转语音 API</p>
<div class="header-bottom">
<div class="version-badge">
<span>版本: <strong id="version">1.3.0</strong></span>
</div>
<div class="language-selector">
<a href="index.html" class="lang-btn">English</a>
<button class="lang-btn active" data-lang="zh">中文</button>
</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>免责声明</h2>
<p>此项目仅用于学习测试,请使用<a href="https://platform.openai.com/docs/guides/audio" target="_blank">https://platform.openai.com/docs/guides/audio</a> OpenAI的官方服务进行生产环境使用。</p>
</div>
</div>
</section>
<!-- Status Section -->
<section class="content-section status-section">
<h2>服务状态</h2>
<div class="status-container">
<div class="status-card">
<div class="status-header">
<h3>队列状态</h3>
<div class="status-indicator" id="status-indicator"></div>
</div>
<div class="queue-stats">
<div class="stat-item">
<span class="stat-label">活动请求:</span>
<span class="stat-value" id="queue-size">0</span>
</div>
<div class="stat-item">
<span class="stat-label">最大容量:</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">无负载</div>
</div>
</div>
</section>
<!-- Playground Section -->
<section class="content-section playground-section">
<h2>立即体验</h2>
<div class="playground-container">
<div class="playground-form">
<div class="form-group">
<label for="playground-text">要转换的文本</label>
<textarea id="playground-text" rows="4" placeholder="输入要转换为语音的文本..."></textarea>
</div>
<div class="form-group">
<label for="playground-instructions">指令</label>
<textarea id="playground-instructions" rows="2" placeholder="例如:用欢快和兴奋的语气说话"></textarea>
</div>
<div class="form-group">
<label for="playground-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">响应格式</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> 生成语音
</button>
</div>
<div class="playground-output">
<div class="audio-section">
<h3>语音预览</h3>
<div id="preview-audio" class="audio-player"></div>
</div>
<div class="audio-section">
<h3>生成结果</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>快速开始</h2>
<p>选择您喜欢的编程语言开始使用 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
}
# 如果提供了指令,则添加到请求中
if instructions:
data["instructions"] = instructions
response = requests.post(url, json=data, headers=headers)
if response.status_code == 200:
# 根据格式获取适当的文件扩展名
ext = format.lower()
filename = f"output.{ext}"
# 保存音频文件
with open(filename, "wb") as f:
f.write(response.content)
print(f"音频已保存为 {filename}")
return filename
else:
error = response.json()
print(f"错误: {response.status_code}, {error}")
return None
# 使用示例
text = "你好,这是一个测试。"
voice = "alloy"
format = "mp3" # 支持的格式:mp3、opus、aac、flac、wav、pcm
instructions = "请用欢快和兴奋的语气说话"
# 使用默认格式(MP3)生成语音
generate_speech(text, voice, instructions=instructions)
# 使用 WAV 格式生成语音
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();
// 创建音频元素用于播放
const audio = new Audio(URL.createObjectURL(blob));
audio.play();
// 可选:下载文件
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);
throw error;
}
}
// 使用示例
const text = '你好,这是一个测试。';
const voice = 'alloy';
const format = 'mp3'; // 支持的格式:mp3、opus、aac、flac、wav、pcm
const instructions = '请用欢快和兴奋的语气说话';
// 使用默认格式(MP3)生成语音
generateSpeech(text, voice, undefined, instructions);
// 使用 WAV 格式生成语音
generateSpeech(text, voice, 'wav', instructions);</code></pre>
</div>
</section>
<!-- Available Voices -->
<section class="content-section">
<h2>可用语音</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 参考</h2>
<div class="api-endpoint">
<h3>生成语音(OpenAI 兼容)</h3>
<pre><code class="language-http">POST /v1/audio/speech</code></pre>
<div class="request-body">
<h4>请求参数</h4>
<table class="params-table">
<tr>
<th>参数</th>
<th>类型</th>
<th>必需</th>
<th>描述</th>
</tr>
<tr>
<td>input</td>
<td>string</td>
<td></td>
<td>要转换为语音的文本</td>
</tr>
<tr>
<td>voice</td>
<td>string</td>
<td></td>
<td>要使用的语音(见可用语音)</td>
</tr>
<tr>
<td class="partial-param">instructions</td>
<td>string</td>
<td></td>
<td><em>发送到后端服务时映射为 "prompt" 参数。可用于指导语音情感或风格。</em></td>
</tr>
<tr>
<td class="partial-param">response_format</td>
<td>string</td>
<td></td>
<td>音频响应的格式。支持的格式:mp3、opus、aac、flac、wav、pcm。默认为 mp3。</td>
</tr>
<tr>
<td class="compat-param">model</td>
<td>string</td>
<td></td>
<td><em>仅用于 OpenAI 兼容性 - 完全忽略。</em></td>
</tr>
<tr>
<td class="compat-param">speed</td>
<td>number</td>
<td></td>
<td><em>仅用于 OpenAI 兼容性 - 完全忽略。</em></td>
</tr>
</table>
<div class="compatibility-notice">
<p><strong>注意:</strong> <span class="compat-inline">灰色</span> 的参数完全被服务忽略或可能导致误导行为。只有 <code>input</code><code>voice</code> <code>response_format</code><code>instructions</code> 会影响实际的 TTS 输出。</p>
</div>
<!-- Instructions Parameter Details -->
<div class="parameter-details">
<h4>指令参数的工作原理</h4>
<p><code>instructions</code> 参数在发送到后端服务时映射为 <code>prompt</code> 参数。它可用于指导语音情感、语气或风格。以下是一些有效的指令示例:</p>
<ul class="examples-list">
<li><strong>情感指导:</strong> "请用欢快和兴奋的语气说话"</li>
<li><strong>角色模仿:</strong> "请模仿一位睿智的老巫师说话"</li>
<li><strong>上下文提示:</strong> "这是读给孩子的,请用温柔的语气"</li>
<li><strong>朗读风格:</strong> "请以新闻广播的风格朗读"</li>
</ul>
<div class="tip-box">
<p><strong>提示:</strong> 请保持指令清晰简洁。过于复杂的指令可能无法被正确解释。</p>
</div>
</div>
<h4>响应格式</h4>
<p>API 以请求的格式返回音频,具有以下标头:</p>
<ul>
<li><code>Content-Type</code>:根据请求的格式(例如,MP3 为 "audio/mpeg")</li>
<li><code>Access-Control-Allow-Origin</code>:*(启用 CORS)</li>
</ul>
<h4>错误响应</h4>
<table class="error-table">
<tr>
<th>状态码</th>
<th>描述</th>
</tr>
<tr>
<td>400</td>
<td>缺少必需参数(input 或 voice)</td>
</tr>
<tr>
<td>429</td>
<td>速率限制超出或队列已满。速率限制时包含 Retry-After 标头。</td>
</tr>
<tr>
<td>500</td>
<td>内部服务器错误</td>
</tr>
</table>
</div>
</div>
<!-- Queue System -->
<div class="api-endpoint">
<h3>队列系统</h3>
<p>API 使用队列系统高效处理多个请求:</p>
<ul>
<li>最大队列大小:可通过 <code>MAX_QUEUE_SIZE</code> 环境变量配置(默认:100 个请求)</li>
<li>请求按 FIFO(先进先出)顺序处理</li>
<li>速率限制:可通过 <code>RATE_LIMIT_REQUESTS</code><code>RATE_LIMIT_WINDOW</code> 环境变量配置(默认:每个 IP 地址 60 秒内最多 30 个请求)</li>
<li>可以通过 <code>/api/queue-size</code> 端点监控队列状态</li>
<li>Web 界面每 2 秒更新一次队列状态</li>
<li>根据使用率显示队列负载状态(低/中/高)</li>
</ul>
<h4>队列状态端点</h4>
<pre><code class="language-http">GET /api/queue-size</code></pre>
<p>返回包含队列信息的 JSON:</p>
<pre><code class="language-json">{
"queue_size": 0, // 当前队列中的请求数
"max_queue_size": 100 // 队列最大容量
}</code></pre>
<div class="response-codes">
<h4>响应状态码</h4>
<ul>
<li><code>200</code> - 成功</li>
<li><code>429</code> - 队列已满或超出速率限制</li>
<li><code>500</code> - 服务器错误</li>
</ul>
</div>
</div>
</section>
</main>
</div>
</div>
<script src="script.js"></script>
</body>
</html>