Signatur
Beschreibung
Das Ereignis downloadprogress gehört zur Schnittstelle CreateMonitor. Diese gehört zu den im Browser eingebauten KI-APIs wie Summarizer, Translator, LanguageDetector, Writer, Rewriter oder LanguageModel. Du kommst an einen CreateMonitor nicht über einen Konstruktor, sondern über die Option monitor der jeweiligen statischen create()-Methode. Dort übergibst du eine Rückruffunktion, die den Monitor als Argument bekommt. An diesem Monitor registrierst du dann den Listener.
Das Ereignisobjekt ist ein ProgressEvent. Wichtig: loaded ist kein Byte-Wert, sondern ein Anteil zwischen 0 und 1. total ist immer 1. So verraten die Werte nichts über die tatsächliche Modellgröße (Datenschutz, kein Fingerprinting). Für eine Prozentanzeige rechnest du also einfach e.loaded * 100.
Sinnvoll ist das Ereignis vor allem, wenn availability() den Wert "downloadable" oder "downloading" liefert. Dann kann der erste Aufruf von create() je nach Modell und Verbindung Minuten dauern, und eine Fortschrittsanzeige verbessert das Nutzererlebnis deutlich. Ist das Modell schon vorhanden ("available"), wird meist nichts heruntergeladen.
Statt addEventListener() kannst du auch die Eigenschaft monitor.ondownloadprogress setzen.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $type Pflicht | string | Der Ereignisname "downloadprogress". |
|
| $handler Pflicht | (event: ProgressEvent) => void | Rückruffunktion. Bekommt ein ProgressEvent mit loaded (Anteil 0–1) und total (immer 1). |
|
| $options | boolean | AddEventListenerOptions | false | Übliche Listener-Optionen wie once oder signal zum späteren Entfernen. |
Rückgabewert
addEventListener() gibt nichts zurück. Die Daten kommen über das ProgressEvent im Handler.Beispiele
Download-Fortschritt beim Erzeugen eines Summarizers protokollieren
const summarizer = await Summarizer.create({
type: 'key-points',
monitor(m) {
m.addEventListener('downloadprogress', (e) => {
console.log(`Modell geladen: ${Math.round(e.loaded * 100)} %`);
});
}
});
const text = document.querySelector('article').textContent;
console.log(await summarizer.summarize(text));
Fortschrittsbalken nur bei nötigem Download anzeigen
// <progress id="dl" max="1" hidden></progress>
const bar = document.getElementById('dl');
document.querySelector('#translate').addEventListener('click', async () => {
const opts = { sourceLanguage: 'en', targetLanguage: 'de' };
const status = await Translator.availability(opts);
if (status === 'unavailable') {
console.warn('Sprachpaar wird nicht unterstützt');
return;
}
const translator = await Translator.create({
...opts,
monitor(m) {
if (status !== 'available') bar.hidden = false;
m.ondownloadprogress = (e) => {
bar.value = e.loaded; // total ist immer 1
if (e.loaded === 1) bar.hidden = true;
};
}
});
console.log(await translator.translate('Hello world'));
});
Listener per AbortSignal wieder entfernen
const controller = new AbortController();
const detector = await LanguageDetector.create({
monitor(m) {
const onProgress = (e) => {
console.log('Fortschritt:', e.loaded.toFixed(2));
if (e.loaded === 1) m.removeEventListener('downloadprogress', onProgress);
};
m.addEventListener('downloadprogress', onProgress, { signal: controller.signal });
},
signal: controller.signal // bricht auch create() selbst ab
});
const [best] = await detector.detect('Guten Morgen zusammen');
console.log(best.detectedLanguage);
// Wichtig · Fallstricke
- Experimentell: Die Built-in-AI-APIs gibt es bisher nur in Chromium-Browsern (Chrome/Edge ab Desktop-Version 138, teils noch hinter Flags oder Origin Trials). Firefox und Safari unterstützen sie nicht. Prüfe daher vorher, ob die API existiert, z. B. mit
'Summarizer' in self. loadedist ein Anteil von 0 bis 1 und keine Byte-Zahl.lengthComputableundtotalsagen nichts über die echte Modellgröße.- Den
monitor-Rückruf musst du synchron increate()übergeben. Einen Listener, den du später registrierst, erreicht das Ereignis nicht mehr. - Muss ein Modell heruntergeladen werden, verlangt
create()eine Nutzeraktivierung (z. B. einen Klick). Außerdem ist ein sicherer Kontext (HTTPS) nötig. In Cross-Origin-iframes ist eine Permissions Policy nötig. - Auch wenn
loaded === 1erreicht ist, kann das Laden des Modells in den Speicher noch dauern. Das Promise voncreate()erfüllt sich erst danach. - Ist das Modell schon im Cache, kommt eventuell gar kein oder nur ein einziges Ereignis. Schreib deine Oberfläche so, dass sie damit zurechtkommt.