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 synthesize
  • workflow (optional string): ComfyUI workflow identifier
  • ref_audio (optional string): Reference audio for voice cloning
  • voice_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 tts router (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/synthesize that validates requests, logs operations, delegates to the core service, and returns structured responses.
  • The router implements backward compatibility for deprecated voice_id parameters while promoting modern workflow and ref_audio fields.
  • Error handling transforms service failures into HTTPException responses 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:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →