Skip to Content
3. EntwicklungArchitekturKI-Jobbasis und TTS

KI-Jobbasis, TTS und Bildvorschläge

Das CMS erzeugt Vorlese-Audios für Kategoriebezeichnungen, Storytitel sowie Text- und Linkinhalte von Stories. Audio und Wort-Zeitmarken sind Bestandteil des veröffentlichten Inhalts; die Joblogik bleibt unabhängig vom gewählten Audioanbieter. Die zugrunde liegende private Queue und der Adaptervertrag sind für TTS-, Bild- und Textjobs gemeinsam aufgebaut. TTS- und Bild-Lane besitzen produktive Worker; die Text-Lane ist für eine spätere Funktion vorbereitet.

Inhalt speichern Eingabe + Quell-Hash private KI-Queue mit getrennten Lanes: tts | image | text ├── TTS-Worker: pending → running → done / failed / cancelled │ ├── Qwen3-TTS (lokales Python-Skript) │ ├── KugelAudio │ ├── ElevenLabs │ └── Audio + Wort-Zeitmarken → Media Library │ └── kompatible ttsJobs-Projektion am Inhalt ├── Bild-Worker: pending → running → done / failed / cancelled │ ├── MFLUX / FLUX.2 klein (lokal auf Apple Silicon) │ ├── fal.ai / GPT Image 2 oder FLUX Kontext Pro │ ├── betreiberseitig gewählter HTTP-Endpunkt │ └── privater Vorschlag → Auswahl → Media Library └── Text-Lane (vorbereitet)

Gemeinsames Jobmodell

Jeder KI-Job enthält Modalität, Lane, Operation, Zielinhalt, Dokument-ID, optionale numerische Entity-ID, Feldpfad, Locale, Eingabe-Hash, Status, Anzahl der Versuche, Queue-, Start- und Endzeit sowie Lease und Fehler. Ein stabiler Jobschlüssel verhindert doppelte offene Aufträge für dieselbe Operation am selben Ziel.

Modalitätsspezifische Ein- und Ausgaben liegen in Request- und Result-Payloads. Generierte Dateien werden als Artefakte mit einem Zustand wie temporary, proposal, accepted oder rejected referenziert. So können spätere Bild- und Textfunktionen denselben Vertrag verwenden, ohne TTS-Felder vorzutäuschen. Die Bild-Lane verwendet diesen Vertrag für mehrere private Vorschläge und ihre redaktionelle Auswahl. Die Text-Lane besitzt noch keinen Worker und keine redaktionelle Oberfläche.

Der gemeinsame Adaptervertrag deklariert Modalität, unterstützte Operationen und Abbruchfähigkeit. Sein Ergebnis kann Provider, Modell, Adapter- und Promptversion, technische Nutzungswerte und Provenienz enthalten. Die Queue speichert keine API-Schlüssel. Nutzungswerte dienen der Nachvollziehbarkeit; eine automatische Preis- oder Budgetberechnung findet nicht statt. Eine vorgesehene Lizenz wird nur als optionale Betreiberangabe protokolliert und nicht vom CMS rechtlich bewertet.

Für TTS erkennt der Eingabe-Hash, ob ein gespeichertes Audio noch zum aktuellen Text passt. Audio, Wort-Zeitmarken und die für die App benötigten Metadaten werden weiterhin als ttsJobs an Story oder Kategorie projiziert. Die zentrale Queue gehört nicht zum öffentlichen Content-API-Vertrag und wird weder im Content-Type Builder noch im Content Manager als redaktioneller Inhalt angezeigt.

Automatische Auslöser

  • Beim Anlegen einer Kategorie oder Story werden alle benötigten Jobs eingereiht.
  • Beim Ändern einer Kategoriebezeichnung werden deren Jobs synchronisiert.
  • Beim Ändern von Storytitel oder Slides werden die Storyjobs synchronisiert.
  • Unveränderte Text-Hashes behalten ihr fertiges Audio; veränderte Felder werden wieder auf pending gesetzt.
  • Veröffentlichen und Zurückziehen lösen keine neue Generierung aus.
  • Eine Veröffentlichung wird abgewiesen, solange für die Locale Jobs den Status pending oder running haben.

Queue-Lanes und Worker

Die Lanes tts, image und text besitzen getrennte Einstellungen für Parallelität, Lease-Dauer und Ausführungszeit. Dadurch blockiert ein langer Job nicht automatisch andere Modalitäten. Innerhalb einer Lane reserviert ein Worker den ältesten offenen Auftrag nach queuedAt und anschließend nach der technischen ID. Ein bedingtes Update von pending auf running verhindert, dass mehrere CMS-Instanzen denselben Auftrag gleichzeitig übernehmen. Die TTS- und Bild-Worker laufen im Strapi-Prozess. Die Text-Lane stellt derzeit nur die gemeinsame technische Basis bereit.

Jede Reservierung besitzt eine zeitlich begrenzte Lease. Ein aktiver Worker verlängert sie während längerer Provideraufrufe. Beim regulären Herunterfahren stellt der Worker seinen aktiven Auftrag sofort wieder auf pending. Beim Neustart erkennt das CMS außerdem verwaiste Leases nicht mehr laufender Node-Prozesse auf demselben Host und reiht sie erneut ein, ohne aktive Parallel-Worker anzutasten. Nach einem harten Abbruch auf einem anderen Host greift spätestens die Lease-Grenze; eine abgelaufene Lease wird ebenfalls wieder pending. Dieser technische Retry behält queuedAt und damit die bisherige Queue-Position. Manueller Retry und erzwungene Neugenerierung stellen einen Auftrag dagegen mit einem neuen queuedAt hinten an; Cancel beendet ihn als cancelled.

Bildvorschläge und redaktionelle Übernahme

Für Kategorie- und Story-Icons sowie Bilder von Text-Slides startet die Redaktion die Generierung ausdrücklich an einem bereits angelegten Eintrag. Titel und Slide-Text werden dabei aus dem aktuellen Formular übernommen und müssen vor der Generierung nicht erneut gespeichert werden. Ein vollständig neuer Eintrag benötigt zunächst durch einmaliges Speichern eine technische Dokument-ID. Zielinhalt, Locale, Feldtyp, redaktionelle Zusatzanweisung und ein festes Stilprofil bilden die Eingabe. Die Stilprofile können betreiberseitig auf freigegebene Medien aus der Media Library verweisen. Ob der Betreiber ein lokales Modell oder eine API verwendet, ändert den redaktionellen Ablauf nicht. Unterstützte Rasterbilder und SVG-Dateien werden für lokale Referenzaufrufe in größenbegrenzte PNG-Dateien umgewandelt; die ursprünglichen Medien bleiben unverändert.

Das Seitenpanel fasst offene Aufträge und verfügbare Vorschläge zusammen. Der eigentliche Workflow öffnet sich als Overlay und benennt die Felder mit ihrem inhaltlichen Kontext. Dort wählt die Redaktion das Bildfeld, eines der vom Betreiber freigeschalteten Modelle, die Vorschlagsanzahl und optional eine je Feld getrennte Bildanweisung. Nach der Generierung lässt sich der tatsächlich verwendete Prompt einsehen. Eine Bildanweisung dient zugleich als bearbeitbarer Ausgangspunkt für den Alternativtext; ohne Bildanweisung wird er aus dem Zielinhalt vorgeschlagen.

Ein Bildjob kann bis zu vier Vorschläge liefern. Sie bleiben außerhalb der Media Library in einem privaten Vorschlagsspeicher und sind nur über eine aktive Admin-Session mit passender Content-Manager-Berechtigung abrufbar. Erst die ausdrückliche Auswahl mit geprüftem Alternativtext lädt genau einen Vorschlag in die Media Library und setzt ihn in das Formular ein. Das Formular muss danach gespeichert werden. Ein vorher verwendetes Medium wird dabei weder automatisch überschrieben noch gelöscht.

Icons werden als quadratische Vollformatbilder mit Farbe bis an alle Dateiränder erzeugt. Eine defensive Randnormalisierung entfernt typische modellseitige Außenränder. Die einheitlichen rundlichen Ecken entstehen erst bei der Darstellung in der App, sodass kein weißer Hintergrund Bestandteil der Bilddatei wird.

Verwerfen, Abbruch, erneute Generierung, verlorene Leases und das Löschen des Zielinhalts entfernen nicht mehr benötigte private Dateien am jeweiligen Zustandswechsel. Es gibt keinen zeitgesteuerten Cleanup. Provider, Modell, Adapter- und Promptversion, technische Nutzung, Referenzmedien, Erzeugungszeit und redaktionelle Auswahl bleiben am privaten Job nachvollziehbar. Für ein übernommenes Medium wird zusätzlich ein privater Provenienzdatensatz angelegt, der die Zuordnung auch nach späteren Jobänderungen erhält. Eine konfigurierte Lizenz- oder Rechteangabe ist Metadatum und keine automatische rechtliche Freigabe.

Der fal.ai-Adapter verwendet die persistente Provider-Queue. Seine Request-ID wird direkt nach dem Submit am Job gespeichert, damit ein CMS-Neustart denselben externen Auftrag weiter abfragt und keine zweite kostenpflichtige Generierung startet. Bei Abbruch und lokalem Timeout wird die externe Stornierung versucht. Qualität, Ausgabegröße, Prompt und Anzahl der Referenzbilder beeinflussen die Providerkosten. Das CMS speichert technische Nutzungsmetriken und vorhandene fal-billableUnits. Aktuelle Einheitspreise werden ausschließlich serverseitig beim Provider abgefragt. Einen Betrag zeigt die Admin-Oberfläche nur bei einem festen Preis je Ergebnis oder auf Basis vergleichbarer abgeschlossener Aufträge. Der dabei ermittelte Kosten-Snapshot bleibt am Queue-Job über Serverneustarts hinweg erhalten. Das CMS führt weder ein Budget noch eine tatsächliche Abrechnung.

Beim Start synchronisiert das CMS vorhandene ttsJobs idempotent in die zentrale Queue. Die bestehende technische Strapi-UID und Tabelle bleiben für Rolling Deployments erhalten, obwohl neue Zugriffe den gemeinsamen KI-Vertrag verwenden. Dadurch bleiben ältere Datenexporte importierbar; vorhandene Audios, Zeitmarken und abgeschlossene Zustände bleiben erhalten. Ein zuvor laufender Job ohne gültige Lease wird erneut als pending eingereiht.

Medienbereinigung

Die Bereinigung läuft an den relevanten Zustandswechseln: nach Textänderung oder Neugenerierung, Recovery, Übernahme des veröffentlichten Audios, Publish und Löschen eines Inhalts sowie bei einem nicht festgeschriebenen Upload.

Vor dem Löschen prüft das CMS alle Draft- und Published-Stände von Stories und Kategorien sowie relevante Queue-Einträge. Gemeinsam verwendete oder noch veröffentlichte Audios bleiben erhalten. Das bisher veröffentlichte Audio wird daher während der Draft-Bearbeitung nicht gelöscht und erst nach dem Publish erneut geprüft. Bei Recover wird je Feld der neueste Fund übernommen; ältere unreferenzierte Kandidaten werden anschließend entfernt.

Zugriffsschutz

Status, Enqueue, Cancel, Recover, die Übernahme des veröffentlichten Audios und das zentrale Audio-Dashboard verwenden dieselbe aktive Admin-Session wie die Strapi-Oberfläche. Der Admin-Fetch-Client sendet das kurzlebige Zugriffstoken automatisch; ein eigenes TTS-Secret wird weder benötigt noch in das Browser-Bundle eingebettet. Öffentliche Requests, abgelaufene Sessions und Content-API-Tokens erhalten keinen Zugriff.

Nach der Authentifizierung greift Strapis Content-Manager-RBAC. Lesen von Statusdaten erfordert read, Änderungen erfordern update für den jeweiligen Content-Type. Das Dashboard setzt die Rechte für Stories und Kategorien voraus. Verändernde Routen sind zusätzlich auf zehn Requests je Route und IP innerhalb von 60 Sekunden begrenzt. Ein vorgeschalteter Reverse Proxy kann für mehrere CMS-Instanzen ergänzend ein verteiltes Limit durchsetzen.

Locale-Konfiguration

Provideroptionen können pro vollständiger Locale, Sprache oder global gesetzt werden. Für en-US gilt beispielsweise:

..._EN_US → ..._EN → globaler Wert

Qwen3-TTS

Qwen wird über ein separates Python-Skript aufgerufen. Modellgewichte, Python-Umgebung, Referenzaufnahmen und optionaler Forced Aligner werden nicht mit npm install installiert. Für Voice Cloning muss das Transkript exakt zur Referenzaufnahme passen. Der Forced Aligner liefert Wort-Zeitmarken; ohne lokale GPU ist die Generierung je nach Modell deutlich langsamer.

KugelAudio

KugelAudio wird als Cloud-Dienst über API-Key, Modell und Voice-ID angebunden. Die WebSocket-Übertragung ist der Standard, weil die Wort-Zeitmarken darüber mitgeliefert werden. Mit KUGELAUDIO_REQUIRE_TIMESTAMPS=true gilt ein Audio ohne Zeitmarken als fehlgeschlagen. Sample-Rate, Normalisierung, Sprache und Stimme können global oder je Locale konfiguriert werden.

ElevenLabs

ElevenLabs erzeugt über die API PCM-Audio, das der Adapter als WAV speichert. Für die in der App verwendete wortweise Hervorhebung ruft der Adapter bei ELEVENLABS_FORCE_ALIGNMENT=true zusätzlich Forced Alignment auf. API-Key, Voice-ID, Modell, Ausgabeformat und Sprachcode können global oder je Locale gesetzt werden.

Änderungen an Worker, Lifecycle-Hooks, Wiederherstellung oder automatischem Löschen von Medien sind datenrelevant und benötigen gezielte Tests.