Zum Inhalt

Konfiguration

Alle Einstellungen befinden sich in der Erweiterungskonfiguration: Admin Tools → Settings → Extension Configuration → nt_ai.

Werte lassen sich auch je Umgebung über den Standard-TYPO3-Mechanismus in config/system/settings.php überschreiben:

$GLOBALS['TYPO3_CONF_VARS']['EXTENSIONS']['nt_ai']['provider']['default'] = 'openai';

Für Geheimnisse können Umgebungsvariablen-Platzhalter direkt im Erweiterungskonfigurationsformular verwendet werden:

provider.anthropic.apiKey = %env(NT_AI_ANTHROPIC_KEY)%
provider.openai.apiKey    = %env(NT_AI_OPENAI_KEY)%

nt-ai löst diese zur Laufzeit über getenv() auf.

Modellnamen aus der Umgebung

Modellnamen verstehen denselben Platzhalter. Ein Projekt kann sie damit aus der versionierten config/system/settings.php heraushalten und das Modell wechseln, indem es eine Umgebungsvariable ändert — ohne Commit und ohne Deployment:

// config/system/settings.php (Auszug)
'EXTENSIONS' => [
    'nt_ai' => [
        'provider' => [
            'openai' => [
                'apiKey' => '%env(NT_AI_OPENAI_KEY)%',
                'model' => '%env(AI_MODEL_OPENAI)%',
            ],
        ],
    ],
],
# .env
AI_MODEL_OPENAI=gpt-4.1-mini

Das gilt für die Modell-Einstellung jedes Anbieters und für tts.model. Der Platzhalter muss den ganzen Wert bilden, der Variablenname darf A–Z, 0–9 und _ enthalten. Die Variable muss für PHPs getenv() sichtbar sein — gesetzt vom Webserver oder Container oder aus einer .env geladen, etwa über helhum/dotenv-connector.

Ein bewusster Unterschied zu den API-Schlüsseln: Ist die Variable leer oder fehlt sie, gilt der unten genannte Standard des Anbieters, kein leerer Wert. Ein fehlender API-Schlüssel macht einen Anbieter zu Recht unverfügbar. Ein leerer Modellname dagegen ginge an den Anbieter und ließe jeden Aufruf scheitern — ein vergessener ENV-Eintrag soll die KI-Funktionen nicht lahmlegen. Derselbe Rückfall gilt für ein im Backend leer gespeichertes Modellfeld.

Verfügbar ab 1.15.0. Wörtliche Modellnamen funktionieren unverändert weiter.

Anbieter-Einstellungen

provider.default legt fest, welcher Anbieter verwendet wird, wenn bei einem Aufruf kein Anbieter angegeben ist. Mögliche Werte: anthropic, openai, gemini, deepseek, mistral, groq, ollama.

Anthropic Claude

Einstellung Typ Standard Beschreibung
provider.anthropic.apiKey string (leer) API-Schlüssel von console.anthropic.com. Erforderlich zur Nutzung von Claude. Unterstützt %env(VAR)%-Platzhalter.
provider.anthropic.model string claude-sonnet-4-5 Modell-Bezeichner. Beispiele: claude-opus-4-5, claude-haiku-4-5. Vision wird bei allen Claude-3+- und 4+-Modellen unterstützt. Unterstützt %env(VAR)%, siehe Modellnamen aus der Umgebung.
provider.anthropic.baseUrl string https://api.anthropic.com/v1 Nur überschreiben, wenn Anthropic über eine eigene Infrastruktur als Proxy betrieben wird.

OpenAI

Einstellung Typ Standard Beschreibung
provider.openai.apiKey string (leer) API-Schlüssel von platform.openai.com. Erforderlich zur Nutzung von OpenAI.
provider.openai.model string gpt-4o-mini Beispiele: gpt-4o, gpt-4o-mini, gpt-4-turbo. Für die Alt-Text-Generierung ein Vision-Modell verwenden (gpt-4o, gpt-4o-mini). Unterstützt %env(VAR)%, siehe Modellnamen aus der Umgebung.
provider.openai.baseUrl string https://api.openai.com/v1 Überschreiben für Azure OpenAI, OpenRouter, LM Studio oder andere OpenAI-API-kompatible Endpunkte.

Google Gemini

Einstellung Typ Standard Beschreibung
provider.gemini.apiKey string (leer) API-Schlüssel von aistudio.google.com. Erforderlich zur Nutzung von Gemini.
provider.gemini.model string gemini-2.0-flash Beispiele: gemini-2.5-pro, gemini-2.0-flash, gemini-1.5-flash. Alle aufgeführten Modelle unterstützen Vision. Unterstützt %env(VAR)%, siehe Modellnamen aus der Umgebung.
provider.gemini.baseUrl string https://generativelanguage.googleapis.com/v1beta Überschreiben bei Proxy-Setups.

DeepSeek

Einstellung Typ Standard Beschreibung
provider.deepseek.apiKey string (leer) API-Schlüssel von platform.deepseek.com. Erforderlich zur Nutzung von DeepSeek.
provider.deepseek.model string deepseek-chat deepseek-chat = DeepSeek-V3 (allgemein), deepseek-reasoner = R1 (Chain-of-Thought). Keines der Modelle unterstützt Vision. Unterstützt %env(VAR)%, siehe Modellnamen aus der Umgebung.
provider.deepseek.baseUrl string https://api.deepseek.com/v1 Überschreiben bei Proxy-Setups.

Mistral AI

Einstellung Typ Standard Beschreibung
provider.mistral.apiKey string (leer) API-Schlüssel von console.mistral.ai.
provider.mistral.model string mistral-small-latest Beispiele: mistral-large-latest, pixtral-large-latest (Vision). Vision ist nur bei pixtral-*-Modellen verfügbar. Unterstützt %env(VAR)%, siehe Modellnamen aus der Umgebung.
provider.mistral.baseUrl string https://api.mistral.ai/v1 Überschreiben bei Proxy-Setups.

Groq

Einstellung Typ Standard Beschreibung
provider.groq.apiKey string (leer) API-Schlüssel von console.groq.com.
provider.groq.model string llama-3.3-70b-versatile Beispiele: llama-3.1-8b-instant, gemma2-9b-it. Groq unterstützt kein Vision. Unterstützt %env(VAR)%, siehe Modellnamen aus der Umgebung.
provider.groq.baseUrl string https://api.groq.com/openai/v1 Überschreiben bei Proxy-Setups.

Ollama (lokal)

Einstellung Typ Standard Beschreibung
provider.ollama.baseUrl string http://localhost:11434 URL der Ollama-Instanz. Bei getrennten Containern für TYPO3 und Ollama die container-interne URL verwenden (z. B. http://host.docker.internal:11434).
provider.ollama.model string llama3.2 Lokal installierter Modellname. Für Vision-Funktionen zuerst ein multimodales Modell installieren: ollama pull llama3.2-vision Unterstützt %env(VAR)%, siehe Modellnamen aus der Umgebung.

KI-Foundation-Extensions (optional)

Seit 1.22.0. Statt eines eingebauten Anbieters kann nt_ai seine Anfragen an eine KI-Foundation-Extension übergeben. API-Schlüssel, Modell, Budgets und Protokoll werden dann dort verwaltet; die provider.*-Einstellungen oben greifen nicht.

provider.default Voraussetzung Konfiguriert in
aim b13/aim Backend-Modul von AiM (Anbieter-Konfigurationen)
nr_llm netresearch/nr-llm Backend-Modul von nr_llm (Standard-Konfiguration)

Eine Brücke gibt es nur, solange die jeweilige Extension installiert ist, und sie gilt nur dann als verfügbar, wenn dort ein nutzbarer Anbieter eingerichtet ist.

Grenzen: Massenläufe gehen über eine Brücke nacheinander statt parallel; eine Anfrage trägt ein Bild; Bildanfragen über nr_llm (0.40) laufen an dessen Budget und Telemetrie vorbei; die Kostenschätzung im Token-Widget kennt nur Modelle aus der Preistabelle von nt_ai. Beide Foundations sind noch vor Version 1.0 — nach einem Update dort zuerst eine Alt-Text-Erzeugung testen, bevor geplante Läufe darauf bauen.

Verhalten

Einstellung Typ Standard Beschreibung
behavior.timeout integer (Sekunden) 60 Maximale Wartezeit für KI-Anfragen. Bei sehr langsamen lokalen Modellen erhöhen.
behavior.maxTokens integer 2048 Maximale Token pro Antwort. Gilt für alle Anbieter.
behavior.logRequests boolean aus Wenn aktiv, wird jeder KI-Aufruf über den Standard-TYPO3-Logger protokolliert. Hilfreich zum Debuggen, kann jedoch sensible Prompt-Inhalte in Log-Dateien schreiben. Im Produktivbetrieb deaktiviert lassen.
behavior.defaultLanguage string (ISO 639-1) en Wird verwendet, wenn bei einem Aufruf keine Sprache angegeben ist. Beeinflusst Inhaltserstellung, Übersetzungen und Alt-Texte.

Alt-Text-Anpassung

Diese Einstellungen formen die von der KI erzeugten Alt-Texte so, dass sie zur Tonalität und Barrierefreiheitsrichtlinie Ihrer Website passen. Die Einstellungen gelten für jede Alt-Text-Generierung, einschließlich Massen-CLI-Läufen und den „Alt-Text generieren"-Schaltflächen.

Einstellung Typ Standard Beschreibung
altText.customInstructions mehrzeiliger Text (leer) Freiformige zusätzliche Regeln für die KI. Eine Anweisung pro Zeile. Werden wörtlich an den System-Prompt angehängt.
altText.maxLength integer 125 Weiche Obergrenze für die Alt-Text-Länge in Zeichen. 0 deaktiviert die Begrenzung. Die KI wird angewiesen, das Limit einzuhalten; die Ausgabe wird zusätzlich hart an Wortgrenzen gekürzt, falls das Modell es überschreitet. WCAG-/Screenreader-Best-Practice liegt bei ca. 125 Zeichen.
altText.style enum concise concise — ein kurzer Satz. descriptive — 1–2 Sätze. detailed — 2–3 Sätze, geeignet für Diagramme und Inhaltsbilder.
altText.forbidImagePrefix boolean an Entfernt Formulierungen wie „Bild von…", „Abbildung zeigt…", „Image of…" aus dem Prompt und defensiv aus der Antwort. Screenreader kündigen Grafiken bereits an, solche Präfixe sind daher überflüssig.
altText.includeDetectedText boolean an Die KI transkribiert sichtbaren Text im Bild (Schilder, Screenshots, Beschriftungen, Verpackungen). Wichtig für die Barrierefreiheit — Text in Bildern ist für Screenreader-Nutzer sonst nicht zugänglich.
altText.tone string neutral, factual Freiformige Tonbeschreibung. Beispiele: friendly, casual (Blogs), marketing, enthusiastic (Landingpages), technical, precise (Dokumentation).
altText.brandContext string (max. 500 Zeichen) (leer) Ein kurzer Hinweis zu Ihrer Website oder Marke, der jeder Alt-Text-Anfrage beigefügt wird. Nützlich für kontextsensitive Beschreibungen.

Strikte Alt-Text-Richtlinie — deutsches Kunstmuseum

altText.style             = descriptive
altText.maxLength         = 200
altText.tone              = neutral, sachlich
altText.brandContext      = Museum für moderne Kunst. Bildbeschreibungen für ein Fachpublikum, Künstlernamen nur wenn klar erkennbar.
altText.customInstructions:
  Bei Kunstwerken: Stil, Material und ungefähre Epoche nennen.
  Personen nur als "Besucher", "Mitarbeiter" o.ä. bezeichnen.
  Texttafeln und Beschriftungen wörtlich übernehmen.

Alt-Text beim Upload

Einstellung Typ Standard Beschreibung
altText.generateOnUpload boolean aus Alt-Text erzeugen, sobald ein neues Bild ankommt. Synchron: Ein Upload dauert etwa 2–5 Sekunden länger. Gefüllt wird nur die Standardsprache, Übersetzungen kommen über die Metadaten-Übersetzung von nt-lingua.
altText.generateOnUploadSource enum all Welche neuen Dateien zählen, siehe unten.
altText.generateOnUploadLimit integer 0 (unbegrenzt) Höchstzahl an Alt-Texten pro Anfrage oder Planer-Lauf. Begrenzt die Kosten, wenn viele Dateien auf einmal ankommen. Was darüber hinausgeht, bleibt ohne Alt-Text und wird einmal als Warnung protokolliert; nachholen lässt es sich gesammelt mit vendor/bin/typo3 nt_ai:generate-alt-texts.

TYPO3 meldet eine neue Datei auf zwei Wegen, und altText.generateOnUploadSource legt fest, welcher zählt:

  • all — jede neu erfasste Datei, wie vor 1.16.0. Dazu gehören neben Uploads auch Dateien, die TYPO3 nur auf der Platte findet: per SFTP oder rsync kopiert und dann vom Planer „Dateiliste: Speicherindex aktualisieren" erfasst, oder sobald jemand den Ordner in der Dateiliste öffnet. Jede dieser Dateien kostet einen KI-Aufruf.
  • backend — nur Dateien, die im Backend hochgeladen werden. Auf den Server kopierte Dateien, Importe auf der Kommandozeile und Uploads aus Frontend-Formularen bleiben außen vor.

Wo Dateien auch auf anderem Weg als über das Backend auf den Server kommen, ist backend die richtige Wahl.

Audit-Einstellungen

Einstellung Typ Standard Beschreibung
audit.enabled boolean an Hauptschalter für das Barrierefreiheits-Audit-Backend-Modul.
audit.autoOnSave boolean aus Wenn aktiv, wird nach jedem Speichern einer Seite im Backend automatisch ein Audit ausgelöst (durch audit.autoCooldown ratenbegrenzt).
audit.autoCooldown integer (Sekunden) 120 Mindestabstand zwischen automatischen Audits für dieselbe Seite. Verhindert Audit-Stürme bei schnellem Speichern durch Redakteure.
audit.aiRules boolean an Legt fest, ob KI-gestützte Audit-Regeln ausgeführt werden. Bei Deaktivierung laufen nur deterministische regelbasierte Prüfungen. KI-Regeln werden auch automatisch übersprungen, wenn kein Anbieter konfiguriert ist.
audit.retentionDays integer (Tage) 90 Audit-Berichte, die älter als dieser Wert sind, können über den Standard-TYPO3-Garbage-Collection-Task gelöscht werden. 0 deaktiviert die Bereinigung.
audit.maxReportsPerPage integer 10 Maximale Anzahl gespeicherter Berichte pro Seite. Ältere Berichte werden nach jedem neuen Audit-Lauf automatisch bereinigt.
audit.httpAuthUser string leer Seit 1.21.0. Benutzername für Websites hinter HTTP-Basic-Auth (Staging). Der Audit meldet sich damit beim Abruf der eigenen Seiten an. Auch %env(NAME)%.
audit.httpAuthPassword string leer Seit 1.21.0. Passwort dazu; am besten als %env(NAME)%. Wird nur an die eigene Website gesendet.
audit.explainPrompt mehrzeiliger Text (integriert) Benutzerdefinierte Prompt-Vorlage für KI-generierte Befund-Erläuterungen. Verfügbare Platzhalter: {ruleId}, {severity}, {message}, {wcagReference}, {snippet}.

Barrierefreiheitserklärung

Angaben für den Reiter „Erklärung" im Audit-Modul, der aus den Audit-Daten einen Entwurf einer Erklärung zur Barrierefreiheit erzeugt (siehe Benutzerhandbuch → „Barrierefreiheitserklärung erstellen").

Einstellung Typ Standard Beschreibung
declaration.targetPageUid integer 0 Zielseite, auf der die Erklärung veröffentlicht wird. 0 = automatisch die Seite mit dem Slug /barrierefreiheit.
declaration.organisation string (leer) Name der Organisation in der Erklärung. Leer = Website-Titel aus der Site-Konfiguration.
declaration.feedbackContact Text (leer) Ansprechpartner für Barrierefreiheits-Feedback (Name, E-Mail, Telefon). Pflichtangabe der Erklärung.
declaration.enforcementBody Text (leer) Zuständige Durchsetzungs-/Schlichtungsstelle (für Unternehmen unter BFSG i. d. R. die Marktüberwachungsstelle der Länder).
declaration.enforcementUrl string (leer) Link zur zuständigen Stelle (optional).
declaration.measures Text (integriert) Bereits umgesetzte Maßnahmen, eine pro Zeile oder mit \| getrennt. Installierte Schwester-Erweiterungen (nt-lingua) und das nt-ai-Audit werden automatisch ergänzt.

Publishing Quality Gate

Warnt beim Veröffentlichen einer Seite vor offenen Barrierefreiheits-Findings oder blockiert die Veröffentlichung, bis kritische Punkte behoben sind. Das Gate nutzt den zuletzt gespeicherten Audit-Bericht der Seite — daher audit.autoOnSave aktiviert lassen, damit der Bericht aktuell bleibt. Ablauf: beheben → speichern (re-Audit) → Bericht aktualisiert → Veröffentlichen erlaubt.

Einstellung Typ Standard Beschreibung
audit.qualityGate Optionen (off/warn/block) off warn: Flash-Warnung beim Veröffentlichen. block: Veröffentlichen wird verhindert (Seite bleibt versteckt), solange das Gate nicht bestanden ist.
audit.qualityGateSeverity Optionen (error/warning) error Ab welchem Schweregrad das Gate greift. error = nur kritische Fehler, warning = Fehler und Warnungen.
audit.qualityGateScope Optionen (onPublish/onSave) onPublish onPublish: nur beim Sichtbarschalten (hidden=0). onSave: bei jedem Speichern einer nicht versteckten Seite.
audit.qualityGateAdminBypass boolean an Administratoren dürfen trotz Findings veröffentlichen (erhalten nur eine Warnung).

Für Pipelines: nt_ai:audit --fail-on=error (bzw. warning) liefert Exit-Code ≠ 0 bei Findings — nutzbar als CI/CD-Gate.

PDF-Barrierefreiheit (Upload-Gate)

Prüft PDFs beim Backend-Upload auf Barrierefreiheit (getaggtes PDF, Textebene, Dokumentsprache, Titel, Alternativtexte …) und warnt oder blockiert je nach Modus. Unabhängig vom Modus wird bei jedem Backend-PDF-Upload ein Bericht für das Modul Medien → PDF-Barrierefreiheit gespeichert. Frontend-Formular-Uploads sind ausgenommen. Details zu den Prüfregeln: Benutzerhandbuch.

Einstellung Typ Standard Beschreibung
pdf.uploadGate Optionen (off/warn/block) off warn: Datei wird gespeichert, der Redakteur erhält eine bleibende Warnmeldung mit den Befunden. block: Der Upload wird mit einer Meldung inkl. Befunden abgelehnt — es entsteht keine Datei.
pdf.uploadGateSeverity Optionen (error/warning) error Ab welchem Schweregrad das Gate greift. warning = Fehler und Warnungen (z. B. fehlender Dokumenttitel), error = nur kritische Fehler.
pdf.uploadGateAdminBypass boolean an Administratoren dürfen trotz Befunden hochladen (erhalten nur die Warnung statt einer Blockade).
pdf.auditTimeLimit int (Sekunden) 60 Seit 1.19.0. Höchstdauer je Datei in der Bestandsprüfung nt_ai:pdf-audit (Planer-Aufgabe). Eine Datei darüber wird als „nicht prüfbar" vermerkt und erst nach einer Änderung erneut geprüft; der Lauf endet mit Exit-Code 1 und nennt die Anzahl in der Zusammenfassung. Mit der PHP-Erweiterung pcntl (CLI) macht der Lauf mit der nächsten Datei weiter, ohne pcntl endet er an dieser Stelle und setzt beim nächsten Mal dahinter fort. 0 = kein Limit. Je Lauf überschreibbar mit --time-limit N. Gilt nicht für Upload-Gate und Modul (dort greift max_execution_time).
pdf.verifyCommand string leer Seit 1.33.0. Zusätzliche Strukturprüfung einer durch die Schnellkorrektur geänderten PDF, bevor sie das Original ersetzt. Aufgerufen mit dem Pfad der Arbeitskopie als letztem Argument; abgelehnt wird, wenn die Kopie die Prüfung nicht besteht (Rückgabewert ≠ 0), das Original aber schon – Warnungen, die schon das Original hat, blockieren nicht. Leer = nur die eingebaute Prüfung (Neueinlesen und Vergleich). Beispiele: qpdf --check oder Python mit pikepdf und dem mitgelieferten Skript Resources/Private/Scripts/pdf-check.py (siehe Benutzerhandbuch, Schnellkorrektur).
pdf.uploadMaxSizeMb int (MB) 25 Seit 1.23.0. Größere PDFs werden beim Upload nicht sofort geprüft, damit der Upload nicht hängt (das Zeitlimit der Bestandsprüfung wirkt nur auf der Kommandozeile). Der Redakteur erhält einen Hinweis; die Bestandsprüfung erfasst die Datei beim nächsten Lauf. 0 = keine Grenze.
pdf.altTextDataPolicy Optionen (all/local/off) all Seit 1.23.0. Für einen KI-Alt-Text zu einem PDF gehen Titel und bis zu 8.000 Zeichen Dokumenttext an den KI-Anbieter. local erlaubt das nur mit Ollama, off schaltet die Funktion für PDFs ab. Gilt für Schaltflächen, Upload und Massenlauf. Bilder sind nicht betroffen. Einzelne Ordner schließt altText.excludePrefixes aus – seit 1.23.0 auch für die Schaltflächen.

Seit 1.23.0 ist error der Standard für pdf.uploadGateSeverity. Eine Installation, in der der Wert schon gespeichert ist, behält ihn; nur neue Installationen und nie gespeicherte Konfigurationen bekommen den neuen Standard. Der Upload-Hinweis nennt zuerst die Fehler, dann – falls die Schwelle warning ist – die Warnungen, höchstens drei, und zählt den Rest. Ein PDF mit mindestens einem Fehler erhält höchstens 49 von 100 Punkten.

Für Bestandsprüfung und Pipelines: nt_ai:pdf-audit [--limit N] [--force] [--fail-on=error|warning] [--time-limit N] — rein PHP-basiert (keine Systemwerkzeuge nötig). Jede Datei wird je Inhalt (SHA1) und Fassung der Prüfung genau einmal versucht — auch ein fehlgeschlagener oder abgebrochener Versuch zählt; eine ältere Fassung der Prüfung oder --force lösen eine neue Prüfung aus.

Token-Tracking und Kostenschätzung

Einstellung Typ Standard Beschreibung
tokenTracking.enabled boolean aus Wenn aktiv, wird jeder KI-Aufruf in tx_ntai_token_usage protokolliert. Erforderlich für die Token-Verbrauchs-Dashboard-Widgets.
tokenTracking.currency Optionen USD Anzeigewährung für geschätzte Kosten. USD → ~$0.19, EUR → ~0,18 €.
tokenTracking.eurRate float 0.92 USD-zu-EUR-Umrechnungskurs. Wird nur verwendet, wenn die Währung auf EUR gesetzt ist.
tokenTracking.customPricing Text (JSON) (leer) Integrierte Modellpreistabelle überschreiben oder erweitern. Preise in USD pro 1.000.000 Token. Präfix-Matching wird angewendet — "gpt-4o" trifft auf gpt-4o-2024-08-06.
{
    "my-fine-tuned-gpt4o": {"input": 4.00, "output": 12.00},
    "custom-ollama-model": {"input": 0.00, "output": 0.00}
}

Integrierte Preistabelle (Stand 2026-07)

Modell-Präfix Anbieter Input $/1M Output $/1M
gpt-4o-mini OpenAI 0.15 0.60
gpt-4o OpenAI 2.50 10.00
claude-haiku-4 Anthropic 0.80 4.00
claude-sonnet-4 Anthropic 3.00 15.00
claude-opus-4 Anthropic 15.00 75.00
gemini-2.0-flash Google 0.10 0.40
gemini-2.5-pro Google 1.25 10.00
deepseek-chat DeepSeek 0.27 1.10
mistral-small Mistral AI 0.20 0.60
llama-3.3-70b Groq 0.59 0.79

Die vollständige Tabelle befindet sich in EXT:nt_ai/Configuration/ModelPricing.php. Unbekannte Modelle werden im Dashboard-Widget als Warnung angezeigt. TTS-Modelle (tts-1, tts-1-hd, gpt-4o-mini-tts) sind dort mit dem Preis pro 1 Mio. Zeichen hinterlegt.

Vorlesen (TTS)

Engine, Tempo und Vorlese-Bereich werden in den Site-Einstellungen gewählt (Kategorie „Vorlesen (TTS)"). Die folgenden Werte gelten nur für die Cloud-Engine und stehen in der Erweiterungskonfiguration (Tab „Vorlesen (TTS)"):

Lehnt der Endpunkt einen Abschnitt ab (403 Text steht nicht auf der Seite, 429 Ratenlimit, 503 Budget oder ausgelastet, 502 Anbieterfehler), liest ihn seit 1.22.2 die Browserstimme; danach wird der nächste Abschnitt wieder in der Cloud angefragt. Nach zwei Ablehnungen in Folge liest die Browserstimme den Rest der Seite ohne weitere Anfragen. Pause, Weiter, Tempo und Lautstärke wirken auf die Stimme, die gerade liest.

Zwei Fälle, in denen die Seitentext-Prüfung Abschnitte immer ablehnt:

  • Per JavaScript nachgeladene Inhalte (z. B. eine per Ajax geladene Liste): Die Prüfung vergleicht mit dem HTML, das der Server ausliefert; solche Abschnitte stehen dort nicht. Sie werden von der Browserstimme gelesen.
  • Websites hinter HTTP-Basic-Auth (Staging): Die Prüfung ruft die Seite selbst ab und erhält 401, solange audit.httpAuthUser und audit.httpAuthPassword nicht gesetzt sind (seit 1.21.0) – die Vorlese-Prüfung nutzt dieselben Zugangsdaten wie der Audit.
Einstellung Typ Standard Beschreibung
tts.cloudProvider Optionen openai Anbieter der Premium-Sprachausgabe. API-Key = der des jeweiligen Providers (Tab „Anbieter-Einstellungen").
tts.voice string alloy Stimme des Anbieters (OpenAI: alloy, echo, fable, onyx, nova, shimmer).
tts.model string tts-1 TTS-Modell (OpenAI: tts-1, tts-1-hd, gpt-4o-mini-tts). Unterstützt %env(VAR)%, siehe Modellnamen aus der Umgebung.
tts.rateLimit integer 30 Max. neue Cloud-Anfragen pro IP und Minute (Schutz vor Bots/Massennutzung). 0 = unbegrenzt; Cache-Treffer zählen nicht. Wechselnde IPs umgehen dieses Limit, die Tagesbudgets nicht.
tts.dailyCharacterBudget integer 200000 Zeichen pro Kalendertag (UTC), die an den Anbieter gehen dürfen — für alle Besucher zusammen. Wird vor jedem Aufruf atomar reserviert; erschöpft → HTTP 503 bis zum Folgetag. 0 = kein globales Limit (nicht empfohlen). Mit OpenAI tts-1 entspricht der Standard etwa 3 USD pro Tag.
tts.dailyRequestBudget integer 2000 Anbieter-Aufrufe pro Kalendertag (UTC), für alle Besucher zusammen. 0 = kein globales Limit (nicht empfohlen).
tts.maxConcurrent integer 4 Cloud-Erzeugungen, die gleichzeitig laufen dürfen — für alle Besucher zusammen (seit 1.18.0). Weitere neue Passagen erhalten sofort HTTP 503 mit Retry-After: 5 und werden mit der Browserstimme gelesen. Der Platz einer abgebrochenen Anfrage wird nach Anfrage-Timeout plus 30 s frei. Cache-Treffer zählen nicht. 0 = keine Begrenzung.
tts.requirePageText boolean 1 Nur Text vorlesen, der auf der angefragten Seite dieser Website steht. Die öffentliche Fassung der Seite wird einmal abgerufen und eine Stunde zwischengespeichert. Grenzen siehe Benutzerhandbuch.

Der Cloud-Endpunkt /nt-ai/tts antwortet nur, wenn die Site-Engine auf cloud steht; er weist Cross-Site-Anfragen ab und ist rate-limitiert. Erzeugte Audios werden serverseitig gecacht, wiederholte Vorlesevorgänge desselben Textes sind kostenlos. Details siehe Benutzerhandbuch → Vorlesefunktion.

Berechtigungen im Backend

Seit 1.17.0 wenden alle Ansichten, Exporte und AJAX-Aktionen von nt-ai dieselben Regeln an wie der TYPO3-Kern. Administratoren sind nicht eingeschränkt.

  • Seiten: Berichte, Scores und Lighthouse-Werte gibt es nur für Seiten, die der Redakteur anzeigen darf und die in seinen Webmounts liegen, und nur für Sprachen, die er bearbeiten darf. Site-Übersicht, Summen, Regelauswertung, Gesamtbericht, Lighthouse-Reiter und Dashboard-Widgets entstehen nur aus diesen Seiten. „Alle Websites" heißt: alle Websites, die der Redakteur sehen darf; die Website-Auswahl listet nur diese. Eine in der Auswahl oder der URL gewählte Website ist ein Filter, keine Berechtigung.
  • Dateien: Einen Alt-Text erzeugen darf, wer die Datei lesen darf (Dateifreigabe). Einen Alt-Text aus dem Audit speichern darf nur, wer die Metadaten bearbeiten darf: beschreibbare (nicht schreibgeschützte) Dateifreigabe, Änderungsrecht auf sys_file_metadata und das Feld alternative, Zugriff auf die Standardsprache. Gespeichert wird über DataHandler (Verlauf, Workspaces). Fehlt ein Recht, antwortet nt-ai mit 403 und ändert nichts. Geschrieben wird nur der Metadatensatz der Standardsprache; übersetzte Alt-Texte werden nicht mehr überschrieben.
  • PDF-Modul und PDF-Widget: Liste, Summen, Detailansicht und Prüf-Aktionen umfassen nur PDFs in den Dateifreigaben des Redakteurs.
  • Barrierefreiheitserklärung (seit 1.18.0): Sie ist eine rechtliche Aussage über eine ganze Website und entsteht deshalb nie aus Teildaten. Redakteure (bei declaration.editorsMayPublish) sehen ihre Kennzahlen und dürfen sie erzeugen und veröffentlichen nur mit Zugriff auf die Startseite und auf jede Seite mit Audit- oder Lighthouse-Ergebnissen dieser Website, jede Sprache mit Ergebnissen und jedes PDF, das die Erklärung zählt (Dateifreigaben). Sonst erklärt der Reiter, dass voller Zugriff auf die Website nötig ist, und die AJAX-Aktionen antworten mit 403. Alle Kennzahlen — auch der Lighthouse-Durchschnitt — umfassen nur die gewählte Website und ihre konfigurierten Sprachen, auch für Administratoren.
  • Dashboard-Widgets (seit 1.18.0): Audit-Score, Lighthouse, Seiten-Score und die Score-Diagramme filtern nach den Sprachen des Redakteurs ebenso wie nach seinen Seiten.
  • KI-Budget (seit 1.18.0): Alle Backend-Aktionen, die einen kostenpflichtigen Anbieter aufrufen (Audit-Lauf, Erklären, Alt-Text und Bildbeschreibung, SEO- und Formulartexte, Score-Analyse, Erklärung), zehren von einem Budget pro Benutzer, rateLimitPerMinute (Standard 30 pro Minute). Ein Wechsel der Aktion setzt es nicht zurück; ist es verbraucht, antwortet die Aktion mit HTTP 429, bevor der Anbieter gefragt wird.

Lighthouse-Monitoring

Öffentlich erreichbare URLs erforderlich

Die PSI-API kann ausschließlich öffentlich zugängliche URLs analysieren. Diese Funktion auf Staging- oder Produktivservern verwenden, nicht auf lokalen DDEV-Instanzen — Google kann *.ddev.site-URLs nicht erreichen.

Einstellung Typ Standard Beschreibung
lighthouse.apiKey string (leer) Google-API-Schlüssel von console.cloud.google.com (API „PageSpeed Insights" aktivieren). Ohne Schlüssel sind Anfragen auf ~25 pro 100 Sekunden begrenzt. Im Produktivbetrieb immer einen Schlüssel konfigurieren. Unterstützt %env(NT_AI_LIGHTHOUSE_KEY)%.
lighthouse.strategy Optionen mobile Geräteprofil für Lighthouse. mobile (Standard), desktop oder both (führt zwei PSI-Aufrufe pro Seite durch — verdoppelt den Kontingentverbrauch).
# Alle Seiten, mobile Strategie (liest Einstellung aus der Erweiterungskonfiguration).
vendor/bin/typo3 nt_ai:lighthouse

# Seite 42 und vollständiger Teilbaum, nur Desktop.
vendor/bin/typo3 nt_ai:lighthouse 42 99 --strategy=desktop

# Unterseiten von Seite 1, beide Strategien ausführen.
vendor/bin/typo3 nt_ai:lighthouse 1 1 --strategy=both

Ergebnisse werden als rein additive Verlaufshistorie in tx_ntai_lighthouse_report gespeichert. Das Dashboard-Widget Lighthouse-Scores zeigt die durchschnittlichen Scores über alle analysierten Seiten.

Score-Schwellenwert-Alarme

Einstellung Typ Standard Beschreibung
alerting.enabled boolean aus Hauptschalter. Kein E-Mail wird versendet, solange dieser deaktiviert ist.
alerting.recipient string (leer) Eine oder mehrere E-Mail-Adressen, kommagetrennt. Beispiel: webmaster@example.com, seo@example.com.
alerting.thresholdGeo integer (0–100) 0 Alarm, wenn der GEO/SEO-KI-Score einer Seite diesen Wert unterschreitet. 0 deaktiviert den Alarm für diese Kategorie.
alerting.thresholdPerformance integer (0–100) 0 Schwellenwert für den Performance-KI-Score.
alerting.thresholdSemantics integer (0–100) 0 Schwellenwert für den Semantics-KI-Score.
alerting.thresholdKeywords integer (0–100) 0 Schwellenwert für den Keywords-KI-Score.
alerting.thresholdAccessibility integer (0–100) 0 Schwellenwert für den Barrierefreiheits-KI-Score.
alerting.thresholdLighthousePerformance integer (0–100) 0 Schwellenwert für den Lighthouse-Performance-Score.
alerting.thresholdLighthouseAccessibility integer (0–100) 0 Schwellenwert für den Lighthouse-Accessibility-Score.
alerting.thresholdLighthouseBestPractices integer (0–100) 0 Schwellenwert für den Lighthouse-Best-Practices-Score.
alerting.thresholdLighthouseSeo integer (0–100) 0 Schwellenwert für den Lighthouse-SEO-Score.

Empfohlene Scheduler-Konfiguration — nt_ai:alert-check nach den Analyse-Befehlen ausführen, damit aktuelle Daten gelesen werden:

03:00  nt_ai:analyze-pages    (KI-Inhalts-Scores)
03:30  nt_ai:lighthouse       (Lighthouse-PSI-Scores)
04:00  nt_ai:alert-check      (vergleichen + E-Mail senden falls nötig)

Welche Sprache ein Audit abdeckt

Eine Seite wird in der Sprache geprüft, auf die die Aufgabe eingestellt ist — indem für die UID des Satzes in der Standardsprache die URL dieser Sprache gebaut wird. Übersetzte Seitensätze sind deshalb keine eigenen Prüfziele und werden übersprungen: Als eigener Kandidat ergäbe ein solcher Satz den übersetzten Slug ohne Sprachpräfix — etwa /about-us/ statt /en/about-us/ — also eine URL, die es nicht gibt und die nur 404 antworten kann.

Für mehrere Sprachen richtet man je Sprache eine Aufgabe ein, jede mit ihrer eigenen Spracheinstellung. Sie teilen sich die Sperrtabelle und doppeln ihr Wissen über unerreichbare Seiten deshalb nicht.

Bis einschließlich 1.13.1

Übersetzte Sätze wurden als Kandidaten ausgewählt. Jeder von ihnen antwortete 404, belegte damit einen Platz je Lauf und konnte — vor 1.13.0, als die Sperrfrist einen Lauf noch nicht überlebte — den Stapel vollständig füllen. Auf einer zweisprachigen Site betraf das rund die Hälfte aller Kandidaten. Nach dem Update verschwinden sie von selbst aus dem Umlauf; Sperreinträge aus früheren Läufen laufen von allein ab.

Seiten ohne Übersetzung

Ob eine Seite ohne Übersetzung in der Zielsprache 404 antwortet oder die Standardsprache ausliefert, hängt von der Fallback-Einstellung der Site ab. Bei strict antwortet sie 404 und wird als Ergebnis eine Woche zurückgestellt — richtig und unschädlich; mit Fallback wird geprüft, was ausgeliefert wird.

Seiten, die derzeit nicht veröffentlicht sind — verborgen oder außerhalb ihrer Zeitsteuerung — sind ebenfalls keine Kandidaten. Eine Seite mit abgelaufener Endzeit antwortet 404 wie eine verborgene, und anders als eine Seite im Wartungsmodus wird sie nie von selbst wieder prüfbar; eine Seite mit künftigem Startdatum tritt von allein in den Umlauf ein, sobald sie live geht. Eine Seite bewusst vor der Veröffentlichung zu prüfen, ist Aufgabe des signierten Vorschau-Tokens im Backend. Es gilt nur für die eine Seite (Sprache, Site, URL-Pfad), für die es erzeugt wurde.

Seiten, die der Audit nicht erreicht

Der geplante Audit arbeitet den Seitenbaum ab, die am längsten nicht geprüfte Seite zuerst. Eine Seite, die nicht abgerufen werden kann, schreibt keinen Bericht — ihr „zuletzt geprüft" bleibt leer, und sie stünde beim nächsten Lauf wieder ganz vorn. Wenige unerreichbare Seiten können so jeden Stapel belegen und den Umlauf zum Stillstand bringen.

Deshalb wird eine solche Seite eine Zeit lang zurückgestellt. Wie lange, hängt von der Antwort des Servers ab:

  • 404 oder 410 — ein beabsichtigtes „nicht gefunden", typischerweise eine Detail-URL ohne Datensatz. Eine Woche Pause: Das ist ein Ergebnis, kein Fehler, und der Inhalt entsteht selten kurzfristig.
  • 503 oder 429 — „vorübergehend nicht verfügbar", also Wartungsseite oder Drosselung. Zurückgestellt für die Zeit, die der Server im Kopffeld Retry-After nennt, sonst eine Stunde. Eine Site im Wartungsmodus braucht damit keine weitere Einstellung: Sie nimmt sich selbst aus dem Umlauf und kehrt zurück, sobald sie wieder da ist.
  • Alles andere (HTTP 5xx, Zeitüberschreitungen, Verbindungsfehler) gilt als technischer Fehler. Die Pause wächst mit jedem weiteren Fehlschlag — 6 Stunden, 24 Stunden, 3 Tage, dann 7 Tage. Ein erfolgreicher Audit löscht den Eintrag.

Nur ein echter technischer Fehler zählt für die Regel, die die Aufgabe rot färbt, wenn jede prüfbare Seite eines Stapels gescheitert ist. Seiten, die lediglich 404 oder 503 geantwortet haben, zählen nicht mit.

Die Einträge stehen in tx_ntai_audit_deferral (eine Zeile je Seite und Sprache, mit Grund und Ende der Pause) und sind damit einsehbar:

SELECT page_uid, status_code, failure_count,
       FROM_UNIXTIME(deferred_until) AS pausiert_bis, reason
FROM tx_ntai_audit_deferral ORDER BY page_uid;

Abgelaufene Einträge werden automatisch entfernt.

Die Spalte reason nennt auch die Herkunft der Frist — Retry-After: 1800s, no Retry-After, default, clean 404/410 oder die Stufe der Fehler-Eskalation. Ohne diese Angabe lässt sich die Frage nicht beantworten: Ein Server mit Retry-After: 3600 und der eingebaute Vorgabewert von einer Stunde ergeben denselben Zeitpunkt.

Vor 1.13.0

Dieser Zustand lag auf dem Objekt der Planer-Aufgabe und konnte einen Lauf nicht überleben: Der Planer speichert eine Aufgabe vor der Ausführung und schreibt danach nur ihre Ausführungsdaten zurück, nie ihre Parameter. Die Pause griff deshalb nie, und ein Stapel unerreichbarer Seiten konnte den Umlauf aushungern. Zu konfigurieren ist nichts — extension:setup muss einmal laufen, damit die neue Tabelle entsteht.

Optionale Argumente in einer Planer-Aufgabe

Eine über das TYPO3-Backend angelegte Aufgabe speichert alle Argumente des Befehls — auch die, die Sie leer gelassen haben: Eine nicht gesetzte pageId wird als leerer String abgelegt, nicht als „nicht vorhanden". nt_ai:analyze-pages und nt_ai:lighthouse behandeln eine leere pageId als „nicht angegeben" und messen dann alle Seiten — das Feld im Backend leer zu lassen tut also das, wonach es aussieht.

Zwei Hinweise dazu:

  • Eine pageId von 0 wird mit einer Fehlermeldung abgewiesen. Seite 0 ist die Baumwurzel und nie eine echte Seite: Sie gehört zu keiner Site und hat keine URL, kann also nur unerreichbare Ergebnisse liefern.
  • Wer Aufgaben per Skript statt über das Backend anlegt, übergibt am besten arguments: [], damit gar keine leeren Werte gespeichert werden.