Signatur
Beschreibung
summarizeStreaming() gehört zur Summarizer API, einer der „Built-in AI“-Schnittstellen, bei denen ein lokal im Browser laufendes Sprachmodell (in Chrome z. B. Gemini Nano) genutzt wird. Anders als summarize(), das erst nach Abschluss der gesamten Generierung ein Promise<string> auflöst, gibt diese Methode sofort einen ReadableStream zurück, aus dem die Zusammenfassung Stück für Stück gelesen werden kann.
Das lohnt sich vor allem bei längeren Texten oder Zusammenfassungen im Format "markdown" bzw. mit length: "long": Nutzer sehen die ersten Wörter nach Sekundenbruchteilen, statt auf das komplette Ergebnis zu warten. Art, Format und Länge der Zusammenfassung (z. B. "key-points", "tldr", "teaser", "headline") werden nicht hier, sondern beim Erzeugen der Instanz über Summarizer.create() festgelegt.
Der Stream lässt sich bequem mit for await…of konsumieren oder klassisch über getReader(). Über ein AbortSignal kann die Generierung jederzeit abgebrochen werden – etwa wenn der Nutzer einen neuen Text einfügt oder die Ansicht verlässt.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $input Pflicht | string | Der zusammenzufassende Text. Er darf das Eingabekontingent (summarizer.inputQuota) nicht überschreiten. |
|
| $options | object | {} | Optionales Konfigurationsobjekt für diesen einzelnen Aufruf. |
| $options.context | string | Zusätzlicher Kontext speziell für diese Eingabe, z. B. "Produktbewertung eines Onlineshops". Ergänzt den bei create() gesetzten sharedContext. |
|
| $options.signal | AbortSignal | Signal eines AbortController, mit dem die Generierung abgebrochen wird. Der Stream wird dann mit einem AbortError beendet. |
Rückgabewert
ReadableStream, dessen Chunks Textfragmente der Zusammenfassung sind. In aktuellen Chrome-Versionen (ab 138) sind die Chunks inkrementell – sie müssen also aneinandergehängt werden. Fehler (z. B. Kontingent überschritten, Abbruch) werden über den Stream gemeldet.Beispiele
Einfache Streaming-Zusammenfassung mit for await
const text = document.querySelector('#artikel').textContent;
if ('Summarizer' in self && (await Summarizer.availability()) !== 'unavailable') {
const summarizer = await Summarizer.create({
type: 'key-points',
format: 'plain-text',
length: 'short',
outputLanguage: 'de'
});
let summary = '';
for await (const chunk of summarizer.summarizeStreaming(text)) {
summary += chunk;
}
console.log(summary);
summarizer.destroy();
} else {
console.log('Summarizer API nicht verfügbar');
}
Live-Ausgabe im UI mit Abbruch-Möglichkeit
const output = document.querySelector('#zusammenfassung');
const cancelBtn = document.querySelector('#abbrechen');
let controller;
const summarizeLive = async (summarizer, text) => {
controller?.abort(); // laufende Generierung stoppen
controller = new AbortController();
output.textContent = '';
try {
const stream = summarizer.summarizeStreaming(text, {
context: 'Kundenbewertung eines Elektronik-Onlineshops',
signal: controller.signal
});
for await (const chunk of stream) {
output.textContent += chunk;
}
} catch (err) {
if (err.name === 'AbortError') {
output.textContent += ' [abgebrochen]';
} else {
console.error('Zusammenfassung fehlgeschlagen:', err);
}
}
};
cancelBtn.addEventListener('click', () => controller?.abort());
Stream manuell mit getReader() lesen und Kontingent prüfen
const summarizer = await Summarizer.create({ type: 'tldr', length: 'medium' });
const text = 'Sehr langer Besprechungstext …';
const benoetigt = await summarizer.measureInputUsage(text);
if (benoetigt > summarizer.inputQuota) {
throw new Error(`Text zu lang: ${benoetigt} von ${summarizer.inputQuota}`);
}
const reader = summarizer.summarizeStreaming(text).getReader();
let result = '';
while (true) {
const { done, value } = await reader.read();
if (done) break;
result += value;
}
console.log(result);
// Wichtig · Fallstricke
- Experimentell & begrenzte Unterstützung: Aktuell nur in Chromium-Browsern (Chrome 138+ auf Desktop) mit ausreichender Hardware verfügbar; Firefox und Safari unterstützen die API nicht. Immer per
'Summarizer' in selfundSummarizer.availability()prüfen. - Inkrementelle vs. kumulative Chunks: Frühe Vorabversionen lieferten in jedem Chunk den bisherigen Gesamttext. Ab Chrome 138 sind die Chunks inkrementell – Code, der mit
output.textContent = chunkarbeitet, zeigt dann nur das letzte Fragment. - Modell-Download: Beim ersten
Summarizer.create()muss das Modell ggf. heruntergeladen werden; dafür ist eine Nutzeraktivierung (z. B. Klick) nötig. Fortschritt über diemonitor-Option verfolgen. - Kontingent: Überschreitet
inputdasinputQuota, schlägt der Stream mit einemQuotaExceededErrorfehl. Vorab mitmeasureInputUsage()prüfen oder Text aufteilen. - Kontext & Berechtigung: Nur in sicheren Kontexten (HTTPS) und im Hauptfenster; in iframes muss die Permissions Policy
summarizererlaubt sein. Nicht in Web Workern verfügbar. - Sicherheit: Ausgaben des Modells nie ungeprüft per
innerHTMLeinfügen – beiformat: "markdown"das Ergebnis mit einem sicheren Markdown-Renderer und Sanitizer verarbeiten, um XSS zu vermeiden. - Ressourcen freigeben: Nicht mehr benötigte Instanzen mit
summarizer.destroy()beenden.