feat: remove API documentation tab and update README for deployment instructions

This commit is contained in:
zuoban
2025-06-29 11:49:53 +08:00
parent 3073ee8908
commit 1edb4273dd
5 changed files with 8 additions and 791 deletions

View File

@@ -1,737 +0,0 @@
<!DOCTYPE html>
<html lang="zh-CN" class="bg-[#0f1a2f]">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>API文档 - TTS服务</title>
<script src="{{.BasePath}}/static/js/tailwind.js"></script>
<link rel="icon" type="image/svg+xml" href="{{.BasePath}}/static/icons/favicon.svg">
<meta name="description" content="TTS服务API文档">
<style>
html, body {
background-color: #0f1a2f; /* 确保即使在滚动时也有深色背景 */
}
/* 固定渐变背景,移除动画效果 */
.bg-gradient-animated {
background: linear-gradient(-45deg, #0f1a2f, #2d3748, #1a365d, #0d2f62);
background-size: 400% 400%;
position: relative;
}
/* 激光效果 */
.laser-container {
position: fixed; /* 改为fixed定位使激光效果固定在视口中 */
top: 0;
left: 0;
width: 100vw; /* 使用视口宽度单位而非百分比 */
height: 100vh; /* 使用视口高度单位 */
z-index: 0;
opacity: 0.7;
pointer-events: none; /* 确保不会拦截鼠标事件 */
overflow: hidden; /* 防止激光光束溢出 */
}
.laser-beam {
position: absolute;
background: linear-gradient(to right, transparent, rgba(0, 195, 255, 0.5), transparent);
height: 2px;
width: 150vw; /* 增加宽度确保激光覆盖旋转后的视口 */
transform-origin: 0 0;
left: -25vw; /* 偏移,确保即使旋转也能覆盖整个屏幕 */
}
.laser-beam:nth-child(2n) {
background: linear-gradient(to right, transparent, rgba(255, 0, 200, 0.5), transparent);
}
.laser-beam:nth-child(3n) {
background: linear-gradient(to right, transparent, rgba(0, 255, 170, 0.5), transparent);
}
.laser-beam:nth-child(5n) {
background: linear-gradient(to right, transparent, rgba(255, 250, 0, 0.3), transparent);
}
/* 移除霓虹光效果动画 */
.glow {
position: absolute;
width: 60%;
height: 60%;
border-radius: 50%;
filter: blur(80px);
z-index: 0;
opacity: 0.3;
}
.glow:nth-child(1) {
top: -30%;
left: -10%;
background: linear-gradient(45deg, #4158D0, #0084ff);
}
.glow:nth-child(2) {
bottom: -30%;
right: -10%;
background: linear-gradient(-45deg, #00f2ff, #4158D0);
}
/* 内容区域 */
.content-area {
position: relative;
z-index: 10;
background: rgba(255, 255, 255, 0.7);
backdrop-filter: blur(20px);
-webkit-backdrop-filter: blur(20px);
border-radius: 1rem;
box-shadow: 0 5px 30px rgba(0, 0, 0, 0.2), inset 0 0 0 1px rgba(255, 255, 255, 0.3);
}
/* 毛玻璃面板效果 */
.panel-frosted {
background: rgba(255, 255, 255, 0.8);
backdrop-filter: blur(15px);
-webkit-backdrop-filter: blur(15px);
border: 1px solid rgba(255, 255, 255, 0.3);
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1);
}
/* 代码块毛玻璃效果 */
pre {
background: rgba(45, 55, 72, 0.8) !important;
backdrop-filter: blur(10px);
-webkit-backdrop-filter: blur(10px);
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.15);
border: 1px solid rgba(74, 85, 104, 0.3);
max-width: 100%;
overflow-x: auto;
white-space: pre-wrap; /* 确保长字符串可以换行 */
}
/* 表格毛玻璃效果 */
table {
backdrop-filter: blur(5px);
-webkit-backdrop-filter: blur(5px);
table-layout: fixed; /* 控制表格布局算法 */
width: 100%;
}
th {
background: rgba(247, 250, 252, 0.8) !;
backdrop-filter: blur(8px);
-webkit-backdrop-filter: blur(8px);
}
/* 链接效果强化 */
a.text-blue-500 {
transition: all 0.3s ease;
position: relative;
text-decoration: none;
}
a.text-blue-500:after {
content: '';
position: absolute;
width: 100%;
height: 1px;
bottom: -2px;
left: 0;
background: currentColor;
transform: scaleX(0);
transition: transform 0.3s ease;
}
a.text-blue-500:hover:after {
transform: scaleX(1);
}
/* 修复表格响应式问题 */
.overflow-x-auto {
width: 100%;
max-width: 100%;
}
/* 响应式修复 */
@media (max-width: 768px) {
pre code {
word-break: break-all; /* 在移动设备上更激进地断行 */
}
th, td {
word-break: break-word; /* 允许在任何字符处断行 */
}
}
/* 重新设计的按钮基础样式 */
.btn-neo {
position: relative;
overflow: hidden;
background: rgba(13, 47, 98, 0.6);
color: #dbeafe;
border: none;
backdrop-filter: blur(8px);
-webkit-backdrop-filter: blur(8px);
border-radius: 6px;
padding: 0.6rem 1.2rem;
font-weight: 500;
letter-spacing: 0.03em;
transition: all 0.3s cubic-bezier(0.165, 0.84, 0.44, 1);
box-shadow:
0 4px 8px -2px rgba(0, 0, 0, 0.2),
inset 0 1px 0 0 rgba(255, 255, 255, 0.2),
inset 0 -1px 0 0 rgba(0, 0, 0, 0.3);
}
/* 按钮边框发光效果 */
.btn-neo::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
border-radius: 6px;
padding: 1px;
background: linear-gradient(135deg, rgba(59, 130, 246, 0.8), rgba(147, 197, 253, 0.3), rgba(59, 130, 246, 0.1));
-webkit-mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
-webkit-mask-composite: xor;
mask-composite: exclude;
pointer-events: none;
}
/* 按钮悬浮效果 */
.btn-neo:hover {
transform: translateY(-2px);
box-shadow:
0 8px 16px -4px rgba(0, 0, 0, 0.3),
inset 0 1px 0 0 rgba(255, 255, 255, 0.3),
0 0 10px 2px rgba(59, 130, 246, 0.4);
background: rgba(26, 86, 219, 0.7);
color: #ffffff;
}
/* 新设计的Tab栏样式 - 更加和谐 */
.tab-bar {
display: flex;
justify-content: center;
background: rgba(13, 47, 98, 0.15); /* 更轻微的背景色 */
backdrop-filter: blur(12px);
-webkit-backdrop-filter: blur(12px);
border-radius: 10px;
padding: 4px;
box-shadow:
inset 0 0 0 1px rgba(255, 255, 255, 0.15),
0 4px 10px rgba(0, 0, 0, 0.1);
position: relative;
max-width: 380px;
margin: 0 auto;
z-index: 1;
}
.tab-bar::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
border-radius: 10px;
padding: 1px;
background: rgba(255, 255, 255, 0.2); /* 更微妙的边框 */
-webkit-mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
-webkit-mask-composite: xor;
mask-composite: exclude;
z-index: -1;
}
.tab-item {
position: relative;
color: rgba(255, 255, 255, 0.7);
font-weight: 500;
padding: 8px 18px;
flex-grow: 1;
text-align: center;
transition: all 0.25s ease;
border-radius: 6px;
z-index: 2;
letter-spacing: 0.01em;
}
.tab-item:hover {
color: rgba(255, 255, 255, 0.9);
}
.tab-item.active {
color: #1a365d; /* 更深的文字颜色,与主题对比 */
font-weight: 600;
}
.tab-indicator {
position: absolute;
background: rgba(255, 255, 255, 0.9); /* 纯白色指示器 */
border-radius: 6px;
height: calc(100% - 8px);
z-index: 1;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
transition: transform 0.3s cubic-bezier(0.34, 1.56, 0.64, 1);
top: 4px;
left: 4px;
bottom: 4px;
}
/* Tab中的图标样式 - 简化 */
.tab-icon {
display: inline-flex;
vertical-align: middle;
margin-right: 6px;
height: 18px;
width: 18px;
transition: transform 0.2s ease;
opacity: 0.9;
}
.tab-item:hover .tab-icon {
transform: scale(1.1);
}
.tab-item.active .tab-icon {
color: #1a365d; /* 图标颜色与文本匹配 */
}
/* 简化下方线条效果 */
.tab-item::after {
content: '';
position: absolute;
width: 20px;
height: 2px;
background: rgba(255, 255, 255, 0.5);
bottom: -2px;
left: 50%;
transform: translateX(-50%) scaleX(0);
transition: transform 0.2s ease;
opacity: 0;
}
.tab-item.active::after {
opacity: 0; /* 移除活动状态下的额外线条,保持简洁 */
}
</style>
</head>
<body class="bg-gradient-animated text-slate-800 font-sans min-h-screen">
<!-- 激光效果 -->
<div class="laser-container">
<div class="glow"></div>
<div class="glow"></div>
<div class="laser-beam" style="top: 10%; animation-delay: 0.5s;"></div>
<div class="laser-beam" style="top: 20%; animation-delay: 2s;"></div>
<div class="laser-beam" style="top: 30%; animation-delay: 1s;"></div>
<div class="laser-beam" style="top: 45%; animation-delay: 3.5s;"></div>
<div class="laser-beam" style="top: 60%; animation-delay: 2.5s;"></div>
<div class="laser-beam" style="top: 75%; animation-delay: 0s;"></div>
<div class="laser-beam" style="top: 90%; animation-delay: 4s;"></div>
</div>
<div class="max-w-4xl mx-auto p-4">
<div class="content-area p-6 shadow-xl my-8">
<header class="text-center mb-8 py-4">
<h1 class="text-4xl font-bold mb-2 text-gray-800">TTS服务 API文档</h1>
<p class="text-xl text-gray-600 mb-4">快速、高质量的文本转语音API服务</p>
<!-- 新Tab栏设计 -->
<div class="tab-bar mt-6">
<span class="tab-indicator" style="width: 50%; transform: translateX(50%);"></span>
<a href="{{.BasePath}}/" class="tab-item">
<span class="tab-icon">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
<path stroke-linecap="round" stroke-linejoin="round" d="M3 12l2-2m0 0l7-7 7 7M5 10v10a1 1 0 001 1h3m10-11l2 2m-2-2v10a1 1 0 01-1 1h-3m-6 0a1 1 0 001-1v-4a1 1 0 011-1h2a1 1 0 011 1v4a1 1 0 001 1m-6 0h6" />
</svg>
</span>
主页
</a>
<a href="{{.BasePath}}/api-doc" class="tab-item active">
<span class="tab-icon">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
<path stroke-linecap="round" stroke-linejoin="round" d="M10 20l4-16m4 4l4 4-4 4M6 16l-4-4 4-4" />
</svg>
</span>
API文档
</a>
</div>
</header>
<main>
<section class="panel-frosted bg-white/90 rounded-lg shadow-lg p-6 mb-8">
<h2 class="text-2xl font-bold mb-4 pb-2 border-b border-gray-200 text-gray-800">API概述</h2>
<p class="mb-3">TTS服务API提供了简单而强大的方式将文本转换为自然语音。我们支持多种语言和声音并允许您调节语速、语调以适应不同场景需求。</p>
<p class="mb-3">基础URL: <code class="bg-gray-100 px-2 py-1 rounded text-sm font-mono">{{.BasePath}}</code></p>
<p class="mb-3">所有API请求均使用HTTP协议返回标准HTTP状态码表示请求结果。</p>
</section>
<!-- 为所有 section 添加毛玻璃面板效果 -->
<section class="panel-frosted bg-white rounded-lg shadow-md p-6 mb-6">
<h2 class="text-2xl font-bold mb-4 pb-2 border-b border-gray-200 text-gray-800">文本转语音 API</h2>
<h3 class="text-xl font-semibold text-blue-600 mt-6 mb-2">端点</h3>
<code class="block bg-gray-100 p-3 rounded text-sm font-mono mb-4">GET {{.BasePath}}/tts</code>
<h3 class="text-xl font-semibold text-blue-600 mt-6 mb-2">参数</h3>
<div class="overflow-x-auto">
<table class="min-w-full bg-white mb-6">
<thead>
<tr>
<th class="py-3 px-4 bg-gray-100 font-semibold text-sm text-left border-b">参数</th>
<th class="py-3 px-4 bg-gray-100 font-semibold text-sm text-left border-b">类型</th>
<th class="py-3 px-4 bg-gray-100 font-semibold text-sm text-left border-b">必选</th>
<th class="py-3 px-4 bg-gray-100 font-semibold text-sm text-left border-b">描述</th>
</tr>
</thead>
<tbody>
<tr>
<td class="py-2 px-4 border-b"><code class="bg-gray-100 px-1 rounded text-sm font-mono">t</code></td>
<td class="py-2 px-4 border-b">string</td>
<td class="py-2 px-4 border-b"></td>
<td class="py-2 px-4 border-b">要转换的文本需要进行URL编码</td>
</tr>
<tr>
<td class="py-2 px-4 border-b"><code class="bg-gray-100 px-1 rounded text-sm font-mono">v</code></td>
<td class="py-2 px-4 border-b">string</td>
<td class="py-2 px-4 border-b"></td>
<td class="py-2 px-4 border-b">语音名称使用short_name格式默认: {{.DefaultVoice}}。可通过/voices接口获取所有可用语音</td>
</tr>
<tr>
<td class="py-2 px-4 border-b"><code class="bg-gray-100 px-1 rounded text-sm font-mono">r</code></td>
<td class="py-2 px-4 border-b">string</td>
<td class="py-2 px-4 border-b"></td>
<td class="py-2 px-4 border-b">语速调整,范围: -100%到100%,默认: {{.DefaultRate}}。正值加快语速,负值减慢语速</td>
</tr>
<tr>
<td class="py-2 px-4 border-b"><code class="bg-gray-100 px-1 rounded text-sm font-mono">p</code></td>
<td class="py-2 px-4 border-b">string</td>
<td class="py-2 px-4 border-b"></td>
<td class="py-2 px-4 border-b">语调调整,范围: -100%到100%,默认: {{.DefaultPitch}}。正值提高语调,负值降低语调</td>
</tr>
<tr>
<td class="py-2 px-4 border-b"><code class="bg-gray-100 px-1 rounded text-sm font-mono">o</code></td>
<td class="py-2 px-4 border-b">string</td>
<td class="py-2 px-4 border-b"></td>
<td class="py-2 px-4 border-b">输出音频格式,默认: {{.DefaultFormat}}。详见下方支持的格式列表</td>
</tr>
<tr>
<td class="py-2 px-4 border-b"><code class="bg-gray-100 px-1 rounded text-sm font-mono">s</code></td>
<td class="py-2 px-4 border-b">string</td>
<td class="py-2 px-4 border-b"></td>
<td class="py-2 px-4 border-b">情感风格可用值取决于所选语音的style_list属性。例如"cheerful"、"sad"等</td>
</tr>
</tbody>
</table>
</div>
<h3 class="text-xl font-semibold text-blue-600 mt-6 mb-2">示例请求</h3>
<pre class="bg-gray-800 text-gray-100 p-4 rounded overflow-x-auto mb-4"><code>curl "{{.BasePath}}/tts?t=%E4%BD%A0%E5%A5%BD%EF%BC%8C%E4%B8%96%E7%95%8C&v=zh-CN-XiaoxiaoNeural&r=0%25&p=0%25"</code></pre>
<h3 class="text-xl font-semibold text-blue-600 mt-6 mb-2">另一个示例(带情感风格)</h3>
<pre class="bg-gray-800 text-gray-100 p-4 rounded overflow-x-auto mb-4"><code>curl "{{.BasePath}}/tts?t=%E4%BB%8A%E5%A4%A9%E5%A4%A9%E6%B0%94%E7%9C%9F%E5%A5%BD&v=zh-CN-XiaoxiaoNeural&s=cheerful"</code></pre>
<h3 class="text-xl font-semibold text-blue-600 mt-6 mb-2">响应</h3>
<p class="mb-3">返回音频文件内容类型取决于请求的输出格式。正常响应状态码为200。</p>
<h3 class="text-xl font-semibold text-blue-600 mt-6 mb-2">错误响应</h3>
<p class="mb-3">如果请求参数有误或服务出现问题将返回对应的HTTP错误码和错误消息。</p>
<div class="overflow-x-auto">
<table class="min-w-full bg-white mb-6">
<thead>
<tr>
<th class="py-3 px-4 bg-gray-100 font-semibold text-sm text-left border-b">状态码</th>
<th class="py-3 px-4 bg-gray-100 font-semibold text-sm text-left border-b">描述</th>
</tr>
</thead>
<tbody>
<tr>
<td class="py-2 px-4 border-b">400</td>
<td class="py-2 px-4 border-b">参数错误或缺失必要参数</td>
</tr>
<tr>
<td class="py-2 px-4 border-b">404</td>
<td class="py-2 px-4 border-b">请求的资源不存在</td>
</tr>
<tr>
<td class="py-2 px-4 border-b">500</td>
<td class="py-2 px-4 border-b">服务器内部错误</td>
</tr>
</tbody>
</table>
</div>
</section>
<section class="panel-frosted bg-white rounded-lg shadow-md p-6 mb-6">
<h2 class="text-2xl font-bold mb-4 pb-2 border-b border-gray-200 text-gray-800">获取可用语音 API</h2>
<h3 class="text-xl font-semibold text-blue-600 mt-6 mb-2">端点</h3>
<code class="block bg-gray-100 p-3 rounded text-sm font-mono mb-4">GET {{.BasePath}}/voices</code>
<h3 class="text-xl font-semibold text-blue-600 mt-6 mb-2">参数</h3>
<div class="overflow-x-auto">
<table class="min-w-full bg-white mb-6">
<thead></thead>
<tr>
<th class="py-3 px-4 bg-gray-100 font-semibold text-sm text-left border-b">参数</th>
<th class="py-3 px-4 bg-gray-100 font-semibold text-sm text-left border-b">类型</th>
<th class="py-3 px-4 bg-gray-100 font-semibold text-sm text-left border-b">必选</th>
<th class="py-3 px-4 bg-gray-100 font-semibold text-sm text-left border-b">描述</th>
</tr>
</thead>
<tbody>
<tr>
<td class="py-2 px-4 border-b"><code class="bg-gray-100 px-1 rounded text-sm font-mono">locale</code></td>
<td class="py-2 px-4 border-b">string</td>
<td class="py-2 px-4 border-b"></td>
<td class="py-2 px-4 border-b">筛选特定语言的语音例如zh-CN中文、en-US英文</td>
</tr>
<tr>
<td class="py-2 px-4 border-b"><code class="bg-gray-100 px-1 rounded text-sm font-mono">gender</code></td>
<td class="py-2 px-4 border-b">string</td>
<td class="py-2 px-4 border-b"></td>
<td class="py-2 px-4 border-b">筛选特定性别的语音可选值Male男性、Female女性</td>
</tr>
</tbody>
</table>
</div>
<h3 class="text-xl font-semibold text-blue-600 mt-6 mb-2">示例请求</h3>
<pre class="bg-gray-800 text-gray-100 p-4 rounded overflow-x-auto mb-4"><code>curl "{{.BasePath}}/voices?locale=zh-CN&gender=Female"</code></pre>
<h3 class="text-xl font-semibold text-blue-600 mt-6 mb-2">响应</h3>
<p class="mb-3">返回JSON格式的可用语音列表</p>
<pre class="bg-gray-800 text-gray-100 p-4 rounded overflow-x-auto mb-4"><code>[
{
"name": "Microsoft Server Speech Text to Speech Voice (zh-CN, XiaoxiaoNeural)",
"display_name": "Xiaoxiao",
"local_name": "晓晓",
"short_name": "zh-CN-XiaoxiaoNeural",
"gender": "Female",
"locale": "zh-CN",
"locale_name": "中文(中国)",
"style_list": ["cheerful", "sad", "angry", "fearful", "disgruntled"]
},
...
]</code></pre>
<p class="mb-3">响应字段说明:</p>
<ul class="list-disc pl-5 mb-4 space-y-1">
<li><span class="font-semibold">name</span>:语音的完整名称</li>
<li><span class="font-semibold">display_name</span>:显示用名称(拉丁字符)</li>
<li><span class="font-semibold">local_name</span>:本地化名称</li>
<li><span class="font-semibold">short_name</span>简短名称用于API调用的v参数</li>
<li><span class="font-semibold">gender</span>性别Male或Female</li>
<li><span class="font-semibold">locale</span>:语言代码</li>
<li><span class="font-semibold">locale_name</span>:语言本地化名称</li>
<li><span class="font-semibold">style_list</span>:支持的情感风格列表(如有)</li>
</ul>
</section>
<section class="panel-frosted bg-white rounded-lg shadow-md p-6 mb-6">
<h2 class="text-2xl font-bold mb-4 pb-2 border-b border-gray-200 text-gray-800">兼容OpenAI接口 API</h2>
<h3 class="text-xl font-semibold text-blue-600 mt-6 mb-2">语音合成</h3>
<code class="block bg-gray-100 p-3 rounded text-sm font-mono mb-4">POST {{.BasePath}}/v1/audio/speech</code>
<h3 class="text-xl font-semibold text-blue-600 mt-6 mb-2">请求体 (JSON)</h3>
<div class="overflow-x-auto">
<table class="min-w-full bg-white mb-6">
<thead>
<tr>
<th class="py-3 px-4 bg-gray-100 font-semibold text-sm text-left border-b">参数</th>
<th class="py-3 px-4 bg-gray-100 font-semibold text-sm text-left border-b">类型</th>
<th class="py-3 px-4 bg-gray-100 font-semibold text-sm text-left border-b">必选</th>
<th class="py-3 px-4 bg-gray-100 font-semibold text-sm text-left border-b">描述</th>
</tr>
</thead>
<tbody>
<tr>
<td class="py-2 px-4 border-b"><code class="bg-gray-100 px-1 rounded text-sm font-mono">model</code></td>
<td class="py-2 px-4 border-b">string</td>
<td class="py-2 px-4 border-b"></td>
<td class="py-2 px-4 border-b">当前仅支持值: "tts-1"</td>
</tr>
<tr>
<td class="py-2 px-4 border-b"><code class="bg-gray-100 px-1 rounded text-sm font-mono">input</code></td>
<td class="py-2 px-4 border-b">string</td>
<td class="py-2 px-4 border-b"></td>
<td class="py-2 px-4 border-b">要转换的文本内容</td>
</tr>
<tr>
<td class="py-2 px-4 border-b"><code class="bg-gray-100 px-1 rounded text-sm font-mono">voice</code></td>
<td class="py-2 px-4 border-b">string</td>
<td class="py-2 px-4 border-b"></td>
<td class="py-2 px-4 border-b">声音名称使用Microsoft语音格式例如ja-JP-KeitaNeural、zh-CN-XiaoxiaoNeural</td>
</tr>
<tr>
<td class="py-2 px-4 border-b"><code class="bg-gray-100 px-1 rounded text-sm font-mono">speed</code></td>
<td class="py-2 px-4 border-b">number</td>
<td class="py-2 px-4 border-b"></td>
<td class="py-2 px-4 border-b">语速调整,范围: 0.5到2.0,默认: 1.0</td>
</tr>
</tbody>
</table>
</div>
<h3 class="text-xl font-semibold text-blue-600 mt-6 mb-2">示例请求</h3>
<pre class="bg-gray-800 text-gray-100 p-4 rounded overflow-x-auto mb-4"><code>curl -X POST "{{.BasePath}}/v1/audio/speech" \
-H "Content-Type: application/json" \
-d '{
"model": "tts-1",
"input": "你好,世界!",
"voice": "zh-CN-XiaoxiaoNeural"
}'</code></pre>
<h3 class="text-xl font-semibold text-blue-600 mt-6 mb-2">另一个示例(带速度调整)</h3>
<pre class="bg-gray-800 text-gray-100 p-4 rounded overflow-x-auto mb-4"><code>curl -X POST "{{.BasePath}}/v1/audio/speech" \
-H "Content-Type: application/json" \
-d '{
"model": "tts-1",
"input": "こんにちは、世界!",
"voice": "ja-JP-NanamiNeural",
"speed": 1.2
}'</code></pre>
<h3 class="text-xl font-semibold text-blue-600 mt-6 mb-2">响应</h3>
<p class="mb-3">返回音频文件内容类型取决于请求的输出格式。正常响应状态码为200。</p>
<h3 class="text-xl font-semibold text-blue-600 mt-6 mb-2">错误响应</h3>
<p class="mb-3">如果请求有误将返回JSON格式的错误信息</p>
<pre class="bg-gray-800 text-gray-100 p-4 rounded overflow-x-auto mb-4"><code>{
"error": {
"message": "错误信息描述",
"type": "错误类型",
"code": "错误代码"
}
}</code></pre>
</section>
<section class="panel-frosted bg-white rounded-lg shadow-md p-6 mb-6">
<h2 class="text-2xl font-bold mb-4 pb-2 border-b border-gray-200 text-gray-800">支持的输出格式</h2>
<div class="overflow-x-auto">
<table class="min-w-full bg-white mb-6">
<thead>
<tr>
<th class="py-3 px-4 bg-gray-100 font-semibold text-sm text-left border-b">格式名称</th>
<th class="py-3 px-4 bg-gray-100 font-semibold text-sm text-left border-b">描述</th>
</tr>
</thead>
<tbody>
<tr>
<td class="py-2 px-4 border-b"><code class="bg-gray-100 px-1 rounded text-sm font-mono">audio-16khz-32kbitrate-mono-mp3</code></td>
<td class="py-2 px-4 border-b">MP3格式16kHz, 32kbps</td>
</tr>
<tr>
<td class="py-2 px-4 border-b"><code class="bg-gray-100 px-1 rounded text-sm font-mono">audio-16khz-64kbitrate-mono-mp3</code></td>
<td class="py-2 px-4 border-b">MP3格式16kHz, 64kbps</td>
</tr>
<tr>
<td class="py-2 px-4 border-b"><code class="bg-gray-100 px-1 rounded text-sm font-mono">audio-16khz-128kbitrate-mono-mp3</code></td>
<td class="py-2 px-4 border-b">MP3格式16kHz, 128kbps</td>
</tr>
<tr>
<td class="py-2 px-4 border-b"><code class="bg-gray-100 px-1 rounded text-sm font-mono">audio-24khz-48kbitrate-mono-mp3</code></td>
<td class="py-2 px-4 border-b">MP3格式24kHz, 48kbps</td>
</tr>
<tr>
<td class="py-2 px-4 border-b"><code class="bg-gray-100 px-1 rounded text-sm font-mono">audio-24khz-96kbitrate-mono-mp3</code></td>
<td class="py-2 px-4 border-b">MP3格式24kHz, 96kbps</td>
</tr>
<tr>
<td class="py-2 px-4 border-b"><code class="bg-gray-100 px-1 rounded text-sm font-mono">audio-24khz-160kbitrate-mono-mp3</code></td>
<td class="py-2 px-4 border-b">MP3格式24kHz, 160kbps</td>
</tr>
<tr>
<td class="py-2 px-4 border-b"><code class="bg-gray-100 px-1 rounded text-sm font-mono">riff-16khz-16bit-mono-pcm</code></td>
<td class="py-2 px-4 border-b">WAV格式16kHz</td>
</tr>
<tr>
<td class="py-2 px-4 border-b"><code class="bg-gray-100 px-1 rounded text-sm font-mono">riff-24khz-16bit-mono-pcm</code></td>
<td class="py-2 px-4 border-b">WAV格式24kHz</td>
</tr>
</tbody>
</table>
</div>
</section>
</main>
<footer class="text-center mt-10 py-4 text-gray-600 text-sm">
<p>© 2025 TTS服务 | <a href="{{.BasePath}}/" class="text-blue-500 hover:underline">返回主页</a></p>
</footer>
</div>
</div>
<script>
// 添加动态激光效果
document.addEventListener('DOMContentLoaded', function() {
const laserContainer = document.querySelector('.laser-container');
// 清除任何现有的激光束
while (laserContainer.lastChild) {
laserContainer.removeChild(laserContainer.lastChild);
}
// 保留发光效果
const glow1 = document.createElement('div');
glow1.className = 'glow';
glow1.style.top = '-30%';
glow1.style.left = '-10%';
laserContainer.appendChild(glow1);
const glow2 = document.createElement('div');
glow2.className = 'glow';
glow2.style.bottom = '-30%';
glow2.style.right = '-10%';
laserContainer.appendChild(glow2);
// 添加更随机方向的激光束,同时确保不会导致水平溢出
const laserCount = 8;
for (let i = 0; i < laserCount; i++) {
const laser = document.createElement('div');
laser.className = 'laser-beam';
// 随机高度
const height = Math.random() * 2 + 1;
laser.style.height = `${height}px`;
// 随机位置
laser.style.top = `${Math.random() * 100}%`;
// 随机角度 (限制角度范围,防止水平溢出)
const angle = Math.random() * 160 + 10; // 10-170度避免接近水平的角度
// 静态定位,不使用动画
laser.style.transform = `rotate(${angle}deg)`;
// 随机不透明度
laser.style.opacity = Math.random() * 0.5 + 0.3;
laserContainer.appendChild(laser);
}
});
// Tab栏交互效果
document.addEventListener('DOMContentLoaded', function() {
// 初始化Tab指示器的位置
const tabBar = document.querySelector('.tab-bar');
const activeTab = tabBar.querySelector('.active');
const indicator = tabBar.querySelector('.tab-indicator');
// 设置指示器初始位置和宽度来匹配活动tab
if (indicator && activeTab) {
indicator.style.width = `${activeTab.offsetWidth}px`;
indicator.style.transform = `translateX(${activeTab.offsetLeft}px)`;
}
// 当窗口大小改变时调整指示器
window.addEventListener('resize', function() {
if (indicator && activeTab) {
indicator.style.width = `${activeTab.offsetWidth}px`;
indicator.style.transform = `translateX(${activeTab.offsetLeft}px)`;
}
});
});
</script>
</body>
</html>

View File

@@ -116,7 +116,7 @@
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1);
}
/* 为滑块输入元素添加毛玻璃效 - 更新样式 */
/* 为滑块输入元素添加毛玻璃效<EFBFBD><EFBFBD> - 更新样式 */
input[type="range"] {
-webkit-appearance: none;
appearance: none;
@@ -980,30 +980,7 @@
<h1 class="text-4xl font-bold mb-2 text-slate-800">文本转语音 (TTS)</h1>
<p class="text-xl text-slate-600 mb-4">将文本转换为自然流畅的语音</p>
<!-- Tab栏设计 -->
<div class="tab-bar mt-6">
<span class="tab-indicator" style="width: 50%;"></span>
<a href="{{.BasePath}}/" class="tab-item active">
<span class="tab-icon">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24"
stroke="currentColor" stroke-width="2">
<path stroke-linecap="round" stroke-linejoin="round"
d="M3 12l2-2m0 0l7-7 7 7M5 10v10a1 1 0 001 1h3m10-11l2 2m-2-2v10a1 1 0 01-1 1h-3m-6 0a1 1 0 001-1v-4a1 1 0 011-1h2a1 1 0 011 1v4a1 1 0 001 1m-6 0h6"/>
</svg>
</span>
主页
</a>
<a href="{{.BasePath}}/api-doc" class="tab-item">
<span class="tab-icon">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24"
stroke="currentColor" stroke-width="2">
<path stroke-linecap="round" stroke-linejoin="round"
d="M10 20l4-16m4 4l4 4-4 4M6 16l-4-4 4-4"/>
</svg>
</span>
API文档
</a>
</div>
<!-- Tab bar removed as requested -->
</header>
<main>
@@ -1075,7 +1052,7 @@
<label for="style" class="mb-1 font-semibold text-slate-700">风格:</label>
<select id="style"
class="p-2 border border-slate-300 rounded-md bg-white/90 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition">
<option value="loading">加载...</option>
<option value="loading">加载<EFBFBD><EFBFBD><EFBFBD>...</option>
</select>
</div>
</div>
@@ -1170,7 +1147,7 @@
</main>
<footer class="text-center mt-10 py-4 text-slate-600 text-sm">
<p>© 2025 TTS服务 | <a href="{{.BasePath}}/api-doc" class="text-blue-500 hover:underline">API文档</a></p>
<p>© 2025 TTS服务</p>
</footer>
</div>
</div>
@@ -1259,7 +1236,7 @@
// 创建渐变背景从中间的0点向两边扩散
let gradient;
if (val < 0) {
// 负值 - 从中到左侧
// 负值 - 从中<EFBFBD><EFBFBD>到左侧
const middlePos = 50; // 0值在滑块中间
const fillPos = middlePos + (percentage / 2); // 填充位置
gradient = `linear-gradient(to right, rgba(59, 130, 246, 0.1) ${fillPos}%, rgba(13, 47, 98, 0.2) ${fillPos}%)`;
@@ -1310,4 +1287,5 @@
});
</script>
</body>
</html>
</html>