What Is the Purpose of the 'tts' Router in the Pixelle-Video FastAPI Backend?
The tts router in the Pixelle-Video FastAPI backend serves as the public HTTP entry point that exposes Text-to-Speech (TTS) functionality to clients, handling request validation, logging, service invocation, and response formatting through a single /tts/synthesize endpoint.
The Pixelle-Video repository (AIDC-AI/Pixelle-Video) is an open-source video generation platform that combines multiple AI modalities. The tts router (api/routers/tts.py) provides a clean, version-stable API contract that bridges external HTTP clients and the internal TTS service implementation. This article explains the router's architecture, request flow, and practical usage with complete code examples.
Overview of the TTS Router Architecture
The tts router is built on FastAPI's APIRouter class and mounted with the prefix /tts. It exposes one primary endpoint that orchestrates the entire synthesis pipeline.
| Component | File Path | Purpose |
|---|---|---|
| Router definition | api/routers/tts.py |
FastAPI APIRouter with /tts prefix |
| Request/response schemas | api/schemas/tts.py |
Pydantic models for validation |
| Core TTS service | pixelle_video/services/tts_service.py |
Actual synthesis logic |
| Utility functions | pixelle_video/utils/tts_util.py |
Duration calculation, local Edge-TTS |
The /tts/synthesize Endpoint: Request Flow
When a client sends a POST request to /tts/synthesize, the router executes a six-step pipeline. Understanding this flow helps developers debug issues and extend functionality.
Step 1: Request Validation
The router parses the incoming JSON body using the TTSSynthesizeRequest Pydantic model defined in api/schemas/tts.py. This model enforces type safety for:
text(required string): The text to synthesizeworkflow(optional string): ComfyUI workflow identifierref_audio(optional string): Reference audio for voice cloningvoice_id(optional string): Deprecated legacy field for backward compatibility
# From api/schemas/tts.py
from pydantic import BaseModel
from typing import Optional
class TTSSynthesizeRequest(BaseModel):
text: str
workflow: Optional[str] = None
ref_audio: Optional[str] = None
voice_id: Optional[str] = None
Step 2: Logging for Traceability
The router logs the incoming text using Python's standard logging infrastructure. This enables audit trails and debugging without exposing sensitive parameters.
# From api/routers/tts.py (lines 24-94)
import logging
logger = logging.getLogger(__name__)
# Inside the endpoint handler:
logger.info(f"TTS synthesis request received: text='{request.text[:50]}...'")
Step 3: Parameter Assembly
The router constructs a tts_params dictionary that normalizes user input. It handles the deprecated voice_id field to maintain backward compatibility while preferring newer parameters.
# Parameter assembly logic from api/routers/tts.py
tts_params = {
"text": request.text,
"workflow": request.workflow,
"ref_audio": request.ref_audio,
}
# Backward compatibility handling
if request.voice_id and not request.workflow:
tts_params["workflow"] = f"legacy/{request.voice_id}.json"
Step 4: Service Invocation
The router delegates actual synthesis to the core TTS service via await pixelle_video.tts(**tts_params). This asynchronous call allows the FastAPI worker to handle other requests during processing.
The core service (pixelle_video/services/tts_service.py) implements a strategy pattern that selects between:
- Local Edge-TTS: Fast, offline synthesis using Microsoft's Edge speech engine
- ComfyUI Workflow: Cloud-based synthesis through configurable ComfyUI pipelines
# Service invocation from api/routers/tts.py
from pixelle_video.services import tts_service
# Async call to core service
audio_path = await tts_service.synthesize(**tts_params)
Step 5: Duration Calculation
After successful generation, the router computes the audio duration using get_audio_duration from pixelle_video/utils/tts_util.py. This metadata enables clients to synchronize playback or validate output quality.
# Duration calculation from api/routers/tts.py
from pixelle_video.utils.tts_util import get_audio_duration
duration = get_audio_duration(audio_path)
Step 6: Response Construction
The router returns a TTSSynthesizeResponse containing the file path and duration. Errors are caught, logged, and transformed into HTTPException with appropriate status codes.
# From api/schemas/tts.py
class TTSSynthesizeResponse(BaseModel):
success: bool
message: str
audio_path: str
duration: float
# Error handling from api/routers/tts.py
from fastapi import HTTPException
try:
# ... synthesis pipeline ...
return TTSSynthesizeResponse(
success=True,
message="Success",
audio_path=audio_path,
duration=duration
)
except Exception as e:
logger.error(f"TTS synthesis failed: {str(e)}")
raise HTTPException(status_code=500, detail=str(e))
Practical Usage Examples
Calling the Endpoint with cURL
curl -X POST https://your-pixelle-video.example.com/tts/synthesize \
-H "Content-Type: application/json" \
-d '{
"text": "Hello, welcome to Pixelle-Video!",
"workflow": "runninghub/tts_edge.json"
}'
Response:
{
"success": true,
"message": "Success",
"audio_path": "output/7f3e2c9a5b1c4e9a8d0f.mp3",
"duration": 3.42
}
Using Python with httpx
import httpx
payload = {
"text": "你好,世界!",
"workflow": "runninghub/tts_edge.json",
"ref_audio": "samples/voice_demo.wav"
}
resp = httpx.post(
"https://your-pixelle-video.example.com/tts/synthesize",
json=payload,
timeout=30.0
)
resp.raise_for_status()
data = resp.json()
print(f"Audio saved at: {data['audio_path']} (duration {data['duration']} s)")
Testing with FastAPI TestClient
from fastapi.testclient import TestClient
from api.main import app
client = TestClient(app)
response = client.post(
"/tts/synthesize",
json={"text": "Testing internal call"}
)
assert response.status_code == 200
print(response.json())
Key Files and Their Roles
| File | Role |
|---|---|
api/routers/tts.py |
Defines the /tts router and /synthesize endpoint with complete request/response handling |
api/schemas/tts.py |
Pydantic models TTSSynthesizeRequest and TTSSynthesizeResponse for validation |
pixelle_video/services/tts_service.py |
Core synthesis logic, routing between local Edge-TTS and ComfyUI workflows |
pixelle_video/utils/tts_util.py |
Helper utilities get_audio_duration and edge_tts for local synthesis |
pixelle_video/tts_voices.py |
Voice speed-to-rate conversion mappings |
Summary
- The
ttsrouter (api/routers/tts.py) is the public HTTP gateway for all Text-to-Speech operations in Pixelle-Video. - It exposes a single POST endpoint
/tts/synthesizethat validates requests, logs operations, delegates to the core service, and returns structured responses. - The router implements backward compatibility for deprecated
voice_idparameters while promoting modernworkflowandref_audiofields. - Error handling transforms service failures into
HTTPExceptionresponses with appropriate status codes and logged details. - The router remains agnostic to synthesis implementation, delegating actual audio generation to
pixelle_video/services/tts_service.py.
Frequently Asked Questions
What HTTP method and path does the tts router use?
The tts router accepts POST requests at the path /tts/synthesize. The router is mounted with the prefix /tts in the main FastAPI application, and the synthesize endpoint is defined at the route /synthesize.
How does the tts router handle invalid requests?
The router uses Pydantic model validation through TTSSynthesizeRequest. If the incoming JSON fails validation—such as missing the required text field or providing incorrect types—FastAPI automatically returns a 422 Unprocessable Entity response with detailed error messages before the router's handler executes.
Can I use the tts router with voice cloning reference audio?
Yes. The TTSSynthesizeRequest schema includes an optional ref_audio field. When provided, the core TTS service (pixelle_video/services/tts_service.py) can use this reference audio for voice cloning workflows, depending on the configured inference mode and selected workflow.
What happens when the tts synthesis fails?
The router wraps the synthesis pipeline in a try-except block. If pixelle_video.tts() raises an exception, the router logs the error with logger.error() and raises an HTTPException with status code 500 and the error details as the response body. This ensures clients receive meaningful error information while internal details are logged server-side.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →