Zum Inhalt

Architektur

TTS-Suite folgt einer schichtweisen Architektur mit klar getrennten Verantwortungen: eine tab-orientierte Web-Oberfläche, eine zentrale Orchestrierungsschicht, spezialisierte Service-Komponenten für Routing, Synthese, Qualitätssicherung und Audio-Verarbeitung sowie eine SQLite-basierte Persistenzschicht. Die TTS- und ASR-Modelle laufen außerhalb der Anwendung als separate vLLM-Omni-Inferenzserver und werden über OpenAI-kompatible HTTP-APIs angesprochen. Die Generierung ist als Generator-basierte Pipeline implementiert, die Fortschrittsereignisse an die UI streamt.

Auf einen Blick

  • Schichten-Trennung: UI (Gradio 6) → Orchestrierung → Services → Persistenz und externe Endpoints
  • Generator-basierter Pipeline-Lauf mit Fortschritts-Events und lokalem Zustand pro Generierung (kein geteilter Zustand zwischen Sitzungen)
  • Persistenz über SQLite im WAL-Modus mit getrennten Connections pro Aufruf
  • Externe TTS- und ASR-Modelle über OpenAI-kompatible HTTP-Schnittstelle, optional mit Bearer-Token
  • Konfiguration ausschließlich über .env-Datei und Umgebungsvariablen
  • Zustandsweitergabe zwischen den Tabs ausschließlich über UUIDs in gr.State, nicht über JSON-Blobs
  • Bereitstellung als Docker-Container oder direkte Python-Installation

Architekturbeschreibung

Schichten und Komponenten

Die Anwendung ist in fünf Schichten organisiert:

  • UI-Schicht — Eine Gradio-6-Anwendung mit fünf aufeinander aufbauenden Tabs (Skript-Werkstatt, Stimmen-Studio, Generierung, Review, Export). Ein gemeinsamer Sitzungs-Zustand führt nur die UUIDs des aktiven Skripts und Projekts sowie die WER-Schwelle, sodass die Reaktivität der Oberfläche auch bei umfangreichen Skripten stabil bleibt.
  • Orchestrierungs-Schicht — Der Orchestrator koordiniert die fünf Phasen einer Generierung (Segment-Synthese, ASR-QA, Stitching, Nachbearbeitung, Persistierung). Jeder Aufruf erzeugt einen lokalen Fortschritts-Datensatz (GenerationProgress) und gibt ihn als Generator an die UI zurück.
  • Service-Schicht — Spezialisierte Dienste für die einzelnen Verarbeitungsschritte: TTSRouter (HTTP-Kommunikation mit den TTS-Backends inklusive Backend-spezifischer Payload-Formate), EmotionsRouter (Auflösung der Emotion gegen das Stimm-Profil), VoiceRegistry und ScriptRegistry (CRUD auf Stimm- und Skript-Bibliothek), QAEngine (ASR-Aufruf und WER-Berechnung), AudioStitcher (Segment-Pegel-Normalisierung, Sample-Rate-Anpassung, Crossfading), AudioPipeline (DSP-Kette und Presets), LLMService (Prompt-Aufbau und JSON-Validierung der LLM-Antwort) und Security (Eingabe- und Pfad-Validierung).
  • Persistenz-Schicht — Eine SQLite-Datenbank im WAL-Modus speichert Stimm-Profile, Skripte und Projekte als JSON-serialisierte Pydantic-Modelle. Jede Operation öffnet eine eigene Connection; Lese-Zugriffe können nebenläufig erfolgen. Referenz-Audios und generierte Segmente liegen als Dateien im konfigurierbaren Daten-Verzeichnis.
  • Externe Endpoints — Sieben OpenAI-kompatible Inferenzdienste werden adressiert: fünf vLLM-Omni-Endpoints für die TTS-Modi (Qwen3-CustomVoice, Qwen3-Base, Qwen3-VoiceDesign, Fish Speech S2 Pro, Voxtral), ein vLLM-Omni-Endpoint für Qwen3-ASR und ein OpenAI-kompatibler LLM-Server (Ollama, vLLM oder OpenAI API) für die Skriptgenerierung. Die Endpoints werden ausschließlich über HTTP angesprochen, optional mit Bearer-Token.

Datenfluss

flowchart TB
    User([Nutzer])

    subgraph UI["UI-Schicht (Gradio 6)"]
        Tab1[Skript-Werkstatt]
        Tab2[Stimmen-Studio]
        Tab3[Generierung]
        Tab4[Review]
        Tab5[Export]
    end

    subgraph Orchestration["Orchestrierung"]
        Orch[Orchestrator]
    end

    subgraph Services["Services"]
        LLM[LLM-Service]
        VR[Voice-Registry]
        SR[Script-Registry]
        ER[Emotions-Router]
        TR[TTS-Router]
        QA[QA-Engine]
        ST[Audio-Stitcher]
        AP[Audio-Pipeline]
        SEC[Security]
    end

    subgraph Persistence["Persistenz"]
        DB[(SQLite)]
        FS[(Dateisystem)]
    end

    subgraph External["Externe Endpoints"]
        LLMSrv[LLM-Server]
        Q3CV[vLLM Qwen3-CustomVoice]
        Q3VD[vLLM Qwen3-VoiceDesign]
        Q3B[vLLM Qwen3-Base]
        FS2[vLLM Fish Speech S2 Pro]
        VOX[vLLM Voxtral 4B]
        ASR[vLLM Qwen3-ASR]
    end

    User --> UI

    Tab1 --> LLM
    LLM --> LLMSrv
    Tab1 --> SR
    SR --> DB

    Tab2 --> VR
    VR --> DB
    VR --> FS
    Tab2 --> TR

    Tab3 --> Orch
    Orch --> SR
    Orch --> ER
    ER --> VR
    Orch --> TR
    TR --> Q3CV
    TR --> Q3VD
    TR --> Q3B
    TR --> FS2
    TR --> VOX
    Orch --> QA
    QA --> ASR
    Orch --> ST
    Orch --> AP
    Orch --> DB
    Orch --> FS

    Tab4 --> Orch
    Tab5 --> AP
    Tab5 --> FS

    SEC -.validiert.-> Tab1
    SEC -.validiert.-> Tab2
    SEC -.validiert.-> Tab5

Erläuterung des Datenflusses

Der Nutzer interagiert ausschließlich mit der UI-Schicht. Tab 1 (Skript-Werkstatt) ruft den LLM-Service auf, der einen formspezifischen Prompt zusammensetzt und ihn an einen externen OpenAI-kompatiblen LLM-Server schickt. Das resultierende Skript wird über den Script-Registry in der SQLite-Datenbank abgelegt; lediglich die Skript-UUID fließt in den Sitzungs-Zustand der UI.

Tab 2 (Stimmen-Studio) verwaltet Stimm-Profile über den Voice-Registry. Profile inklusive Metadaten liegen in der Datenbank, Referenz-Audios im Dateisystem. Für die Live-Vorschau ruft Tab 2 den TTS-Router direkt auf.

Tab 3 (Generierung) startet den Orchestrator. Dieser lädt das Skript und das Projekt, iteriert über die Segmente und delegiert pro Segment an den Emotions-Router, der gegen das jeweilige Stimm-Profil eine Routing-Struktur erzeugt (Backend-Typ, Referenz-Audio oder Preset-Name, aufgelöste Emotion, Instruktions-Text oder Inline-Tag). Der TTS-Router wählt anhand des Backend-Typs die passende Payload-Struktur und ruft den entsprechenden vLLM-Omni-Endpoint auf. Nach jedem Segment wird ein Fortschritts-Ereignis an die UI geyielded. Anschließend transkribiert die QA-Engine jedes erfolgreich generierte Segment per Qwen3-ASR zurück und berechnet die WER. Der Audio-Stitcher normalisiert die Segment-Pegel, gleicht Sample-Raten an und fügt die Segmente mit format-abhängigen Pausen und Crossfades zusammen. Die Audio-Pipeline wendet das gewählte Preset an. Das fertige Projekt landet in der Datenbank und im Projekt-Verzeichnis.

Tab 4 (Review) nutzt den Orchestrator für die Regenerierung einzelner Segmente mit alternativer Emotion oder editiertem Text. Tab 5 (Export) wendet bei Bedarf ein anderes Audio-Preset an und schreibt die finale Datei im gewünschten Format.

Der Security-Dienst validiert in mehreren Tabs Eingaben, Datei-Uploads und Pfade — er greift querschnittlich, ohne im Hauptdatenfluss zu liegen.

KI-Komponenten im Workflow

Drei Klassen von KI-Komponenten wirken in der Pipeline zusammen, eingebettet in eine regelbasierte Orchestrierung:

  • LLM (Skriptgenerierung) — Verwandelt einen Rohtext in ein strukturiertes Dialog-Skript mit Sprecher-Definitionen, Segmenten und Emotions-Tags. Die Antwort wird gegen die Pydantic-Datenmodelle als JSON-Schema validiert; bei Format-Fehlern erfolgt ein Retry mit eingegrenztem Prompt.
  • TTS-Modelle (Synthese) — Drei heterogene Modellfamilien mit unterschiedlichen API-Verträgen. Der TTS-Router kapselt diese Heterogenität (Qwen3-CustomVoice: voice + instructions + language; Qwen3-Base: ref_audio als base64-Data-URL plus ref_text; Qwen3-VoiceDesign: task_type:VoiceDesign plus Beschreibungstext; Fish Speech: voice:default plus separates ref_audio plus Inline-Tags; Voxtral: Preset-Name oder base64-Audio im selben voice-Feld).
  • ASR-Modell (Qualitätssicherung) — Qwen3-ASR transkribiert jedes generierte Segment zurück. Eine Levenshtein-basierte WER-Berechnung vergleicht das Ergebnis mit dem Original-Text. Vor dem Vergleich werden beide Texte normalisiert (Whitespace und Inline-Tags entfernt).

Der Emotions-Router ist regelbasiert und verbindet diese Komponenten: er übersetzt die abstrakten Emotion-Bezeichnungen aus dem LLM-Skript in das jeweilige Backend-Format (Instruktion oder Inline-Tag) und wählt im Clone-Modus den passenden Referenz-Audio-Clip aus.

Nebenläufigkeit und Robustheit

Der Orchestrator ist zustandslos zwischen Aufrufen — jede Generierung erzeugt ein lokales GenerationProgress-Objekt, sodass parallele Sitzungen sich nicht gegenseitig beeinflussen. Die SQLite-Datenbank läuft im WAL-Modus mit eigener Connection pro Operation, was nebenläufige Lese-Zugriffe ermöglicht. TTS-Aufrufe sind mit konfigurierbarem Retry (Standard: drei Versuche) versehen; fehlgeschlagene Segmente werden als QA_FAILED markiert, ohne den Gesamtlauf abzubrechen. Audio-Uploads aus unterschiedlichen Browsern und Aufnahmegeräten werden über pydub robust nach WAV konvertiert, mit verständlichen Fehlermeldungen statt generischer Exceptions.

Konfiguration und Deployment

Sämtliche Endpoints, Modellnamen, Audio-Parameter, Stitching-Parameter und Sicherheitsgrenzen werden ausschließlich über eine .env-Datei beziehungsweise Umgebungsvariablen gesetzt; es gibt keine Kommandozeilen-Argumente. Die Anwendung startet entweder direkt über python app.py oder als Docker-Container (Python-3.12-Slim-Basis mit ffmpeg und libsndfile). Die externen vLLM-Omni-Inferenzserver werden separat betrieben und können sich beliebig im Netz befinden, solange sie HTTP-erreichbar sind.

Technologie-Übersicht

  • UI: Gradio 6
  • Datenmodellierung: Pydantic v2
  • HTTP-Client: httpx
  • Persistenz: SQLite (WAL-Modus), Dateisystem
  • Audio-Verarbeitung: pydub, scipy, numpy, pyloudnorm, noisereduce
  • TTS-Modelle: Qwen3-TTS (CustomVoice, Base, VoiceDesign), Voxtral 4B TTS, Fish Speech S2 Pro
  • ASR: Qwen3-ASR
  • Inferenz-Backend für TTS und ASR: vLLM-Omni mit OpenAI-kompatibler API
  • LLM-Backend: beliebiger OpenAI-kompatibler Server (Ollama, vLLM, OpenAI API)
  • Bereitstellung: Docker oder direkte Python-3.10+-Installation