Spaces:
Running
Running
{% extends "base.html" %} | |
{% block title %}TTSFM API Documentation{% endblock %} | |
{% block extra_css %} | |
<style> | |
.code-block { | |
background-color: #f8f9fa; | |
border: 1px solid #e9ecef; | |
border-radius: 0.375rem; | |
padding: 1rem; | |
margin: 1rem 0; | |
overflow-x: auto; | |
} | |
.endpoint-card { | |
border-left: 4px solid #007bff; | |
margin-bottom: 2rem; | |
} | |
.method-badge { | |
font-size: 0.75rem; | |
padding: 0.25rem 0.5rem; | |
border-radius: 0.25rem; | |
font-weight: bold; | |
margin-right: 0.5rem; | |
} | |
.method-get { background-color: #28a745; color: white; } | |
.method-post { background-color: #007bff; color: white; } | |
.method-put { background-color: #ffc107; color: black; } | |
.method-delete { background-color: #dc3545; color: white; } | |
.response-example { | |
background-color: #f1f3f4; | |
border-radius: 0.375rem; | |
padding: 1rem; | |
margin-top: 1rem; | |
} | |
.toc { | |
position: sticky; | |
top: 2rem; | |
max-height: calc(100vh - 4rem); | |
overflow-y: auto; | |
} | |
.toc a { | |
color: #6c757d; | |
text-decoration: none; | |
display: block; | |
padding: 0.25rem 0; | |
border-left: 2px solid transparent; | |
padding-left: 1rem; | |
} | |
.toc a:hover, .toc a.active { | |
color: #007bff; | |
border-left-color: #007bff; | |
} | |
</style> | |
{% endblock %} | |
{% block content %} | |
<div class="container py-5"> | |
<div class="row"> | |
<div class="col-12 text-center mb-5"> | |
<h1 class="display-4 fw-bold"> | |
<i class="fas fa-book me-3"></i>API Documentation | |
</h1> | |
<p class="lead text-muted"> | |
Complete reference for the TTSFM Text-to-Speech API | |
</p> | |
</div> | |
</div> | |
<div class="row"> | |
<!-- Table of Contents --> | |
<div class="col-lg-3"> | |
<div class="toc"> | |
<h5 class="fw-bold mb-3">Contents</h5> | |
<a href="#overview">Overview</a> | |
<a href="#authentication">Authentication</a> | |
<a href="#text-validation">Text Validation</a> | |
<a href="#endpoints">API Endpoints</a> | |
<a href="#voices">Voices</a> | |
<a href="#formats">Audio Formats</a> | |
<a href="#generate">Generate Speech</a> | |
<a href="#batch">Batch Processing</a> | |
<a href="#status">Status & Health</a> | |
<a href="#errors">Error Handling</a> | |
<a href="#examples">Code Examples</a> | |
<a href="#python-package">Python Package</a> | |
</div> | |
</div> | |
<!-- Documentation Content --> | |
<div class="col-lg-9"> | |
<!-- Overview --> | |
<section id="overview" class="mb-5"> | |
<h2 class="fw-bold mb-3">Overview</h2> | |
<p> | |
The TTSFM API provides a modern, OpenAI-compatible interface for text-to-speech generation. | |
It supports multiple voices, audio formats, and includes advanced features like text length | |
validation and batch processing. | |
</p> | |
<div class="alert alert-info"> | |
<i class="fas fa-info-circle me-2"></i> | |
<strong>Base URL:</strong> <code>{{ request.url_root }}api/</code> | |
</div> | |
<h4>Key Features</h4> | |
<ul> | |
<li>11 different voice options</li> | |
<li>Multiple audio formats (MP3, WAV, OPUS, etc.)</li> | |
<li>Text length validation (4096 character limit)</li> | |
<li>Automatic text splitting for long content</li> | |
<li>Batch processing capabilities</li> | |
<li>Real-time status monitoring</li> | |
</ul> | |
</section> | |
<!-- Authentication --> | |
<section id="authentication" class="mb-5"> | |
<h2 class="fw-bold mb-3">Authentication</h2> | |
<p> | |
Currently, the API supports optional API key authentication. If configured, | |
include your API key in the request headers. | |
</p> | |
<div class="code-block"> | |
<pre><code>Authorization: Bearer YOUR_API_KEY</code></pre> | |
</div> | |
</section> | |
<!-- Text Validation --> | |
<section id="text-validation" class="mb-5"> | |
<h2 class="fw-bold mb-3">Text Length Validation</h2> | |
<p> | |
TTSFM includes built-in text length validation to ensure compatibility with TTS models. | |
The default maximum length is 4096 characters, but this can be customized. | |
</p> | |
<div class="alert alert-warning"> | |
<i class="fas fa-exclamation-triangle me-2"></i> | |
<strong>Important:</strong> Text exceeding the maximum length will be rejected unless | |
validation is disabled or the text is split into chunks. | |
</div> | |
<h4>Validation Options</h4> | |
<ul> | |
<li><code>max_length</code>: Maximum allowed characters (default: 4096)</li> | |
<li><code>validate_length</code>: Enable/disable validation (default: true)</li> | |
<li><code>preserve_words</code>: Avoid splitting words when chunking (default: true)</li> | |
</ul> | |
</section> | |
<!-- API Endpoints --> | |
<section id="endpoints" class="mb-5"> | |
<h2 class="fw-bold mb-3">API Endpoints</h2> | |
<!-- Voices Endpoint --> | |
<div class="card endpoint-card" id="voices"> | |
<div class="card-body"> | |
<h4 class="card-title"> | |
<span class="method-badge method-get">GET</span> | |
/api/voices | |
</h4> | |
<p class="card-text">Get list of available voices.</p> | |
<h6>Response Example:</h6> | |
<div class="response-example"> | |
<pre><code>{ | |
"voices": [ | |
{ | |
"id": "alloy", | |
"name": "Alloy", | |
"description": "Alloy voice" | |
}, | |
{ | |
"id": "echo", | |
"name": "Echo", | |
"description": "Echo voice" | |
} | |
], | |
"count": 6 | |
}</code></pre> | |
</div> | |
</div> | |
</div> | |
<!-- Formats Endpoint --> | |
<div class="card endpoint-card" id="formats"> | |
<div class="card-body"> | |
<h4 class="card-title"> | |
<span class="method-badge method-get">GET</span> | |
/api/formats | |
</h4> | |
<p class="card-text">Get list of supported audio formats.</p> | |
<h6>Response Example:</h6> | |
<div class="response-example"> | |
<pre><code>{ | |
"formats": [ | |
{ | |
"id": "mp3", | |
"name": "MP3", | |
"mime_type": "audio/mp3", | |
"description": "MP3 audio format" | |
} | |
], | |
"count": 6 | |
}</code></pre> | |
</div> | |
</div> | |
</div> | |
<!-- Text Validation Endpoint --> | |
<div class="card endpoint-card"> | |
<div class="card-body"> | |
<h4 class="card-title"> | |
<span class="method-badge method-post">POST</span> | |
/api/validate-text | |
</h4> | |
<p class="card-text">Validate text length and get splitting suggestions.</p> | |
<h6>Request Body:</h6> | |
<div class="code-block"> | |
<pre><code>{ | |
"text": "Your text to validate", | |
"max_length": 4096 | |
}</code></pre> | |
</div> | |
<h6>Response Example:</h6> | |
<div class="response-example"> | |
<pre><code>{ | |
"text_length": 5000, | |
"max_length": 4096, | |
"is_valid": false, | |
"needs_splitting": true, | |
"suggested_chunks": 2, | |
"chunk_preview": [ | |
"First chunk preview...", | |
"Second chunk preview..." | |
] | |
}</code></pre> | |
</div> | |
</div> | |
</div> | |
<!-- Generate Speech Endpoint --> | |
<div class="card endpoint-card" id="generate"> | |
<div class="card-body"> | |
<h4 class="card-title"> | |
<span class="method-badge method-post">POST</span> | |
/api/generate | |
</h4> | |
<p class="card-text">Generate speech from text.</p> | |
<h6>Request Body:</h6> | |
<div class="code-block"> | |
<pre><code>{ | |
"text": "Hello, world!", | |
"voice": "alloy", | |
"format": "mp3", | |
"instructions": "Speak cheerfully", | |
"max_length": 4096, | |
"validate_length": true | |
}</code></pre> | |
</div> | |
<h6>Parameters:</h6> | |
<ul> | |
<li><code>text</code> (required): Text to convert to speech</li> | |
<li><code>voice</code> (optional): Voice ID (default: "alloy")</li> | |
<li><code>format</code> (optional): Audio format (default: "mp3")</li> | |
<li><code>instructions</code> (optional): Voice modulation instructions</li> | |
<li><code>max_length</code> (optional): Maximum text length (default: 4096)</li> | |
<li><code>validate_length</code> (optional): Enable validation (default: true)</li> | |
</ul> | |
<h6>Response:</h6> | |
<p>Returns audio file with appropriate Content-Type header.</p> | |
</div> | |
</div> | |
<!-- Batch Processing Endpoint --> | |
<div class="card endpoint-card" id="batch"> | |
<div class="card-body"> | |
<h4 class="card-title"> | |
<span class="method-badge method-post">POST</span> | |
/api/generate-batch | |
</h4> | |
<p class="card-text">Generate speech from long text by automatically splitting into chunks.</p> | |
<h6>Request Body:</h6> | |
<div class="code-block"> | |
<pre><code>{ | |
"text": "Very long text that exceeds the limit...", | |
"voice": "alloy", | |
"format": "mp3", | |
"max_length": 4096, | |
"preserve_words": true | |
}</code></pre> | |
</div> | |
<h6>Response Example:</h6> | |
<div class="response-example"> | |
<pre><code>{ | |
"total_chunks": 3, | |
"successful_chunks": 3, | |
"results": [ | |
{ | |
"chunk_index": 1, | |
"chunk_text": "First chunk text...", | |
"audio_data": "base64_encoded_audio", | |
"content_type": "audio/mp3", | |
"size": 12345, | |
"format": "mp3" | |
} | |
] | |
}</code></pre> | |
</div> | |
</div> | |
</div> | |
</section> | |
</div> | |
</div> | |
</div> | |
{% endblock %} | |
{% block extra_js %} | |
<script> | |
// Smooth scrolling for TOC links | |
document.querySelectorAll('.toc a').forEach(link => { | |
link.addEventListener('click', function(e) { | |
e.preventDefault(); | |
const target = document.querySelector(this.getAttribute('href')); | |
if (target) { | |
target.scrollIntoView({ behavior: 'smooth' }); | |
// Update active link | |
document.querySelectorAll('.toc a').forEach(l => l.classList.remove('active')); | |
this.classList.add('active'); | |
} | |
}); | |
}); | |
// Highlight current section in TOC | |
window.addEventListener('scroll', function() { | |
const sections = document.querySelectorAll('section[id]'); | |
const scrollPos = window.scrollY + 100; | |
sections.forEach(section => { | |
const top = section.offsetTop; | |
const bottom = top + section.offsetHeight; | |
const id = section.getAttribute('id'); | |
const link = document.querySelector(`.toc a[href="#${id}"]`); | |
if (scrollPos >= top && scrollPos < bottom) { | |
document.querySelectorAll('.toc a').forEach(l => l.classList.remove('active')); | |
if (link) link.classList.add('active'); | |
} | |
}); | |
}); | |
</script> | |
{% endblock %} | |