Signatur
Beschreibung
Die schreibgeschützte Eigenschaft charIndex des SpeechSynthesisEvent-Interfaces liefert den nullbasierten Index des Zeichens in SpeechSynthesisUtterance.text, an dem die Sprachausgabe stand, als das Ereignis ausgelöst wurde. Beim boundary-Ereignis zeigt der Wert auf den Anfang des Wortes oder Satzes, der gleich gesprochen wird.
Am meisten bringt die Eigenschaft beim Ereignis boundary, zusammen mit charLength und name ("word" oder "sentence"). So lässt sich während des Vorlesens das aktuelle Wort hervorheben, etwa für Karaoke-artige Lesehilfen, Sprachlern-Apps oder Barrierefreiheit. Auch in pause, resume, end und error steht der Wert zur Verfügung. Damit kann man festhalten, wie weit ein Text schon vorgelesen wurde, und ihn später ab dieser Stelle fortsetzen.
Der Index zählt UTF-16-Codeeinheiten, genau wie String.prototype.slice() und String.prototype.length. Kann die Sprach-Engine keine Position ermitteln, ist der Wert 0.
Rückgabewert
utterance.text.Beispiele
Aktuelles Wort beim Vorlesen protokollieren
const text = 'Hallo Welt, wie geht es dir?';
const utterance = new SpeechSynthesisUtterance(text);
utterance.lang = 'de-DE';
utterance.addEventListener('boundary', (event) => {
if (event.name !== 'word') return;
const start = event.charIndex;
// charLength fehlt in manchen Browsern – Wortende selbst suchen
const end = event.charLength
? start + event.charLength
: (text.slice(start).search(/[\s,.!?]/) + 1 || text.length - start + 1) + start - 1;
console.log(start, text.slice(start, end));
});
speechSynthesis.speak(utterance);
Wort im DOM hervorheben (Lesehilfe)
const output = document.querySelector('#lesetext');
const text = output.textContent;
const utterance = new SpeechSynthesisUtterance(text);
const highlight = (start, length) => {
output.replaceChildren(
text.slice(0, start),
Object.assign(document.createElement('mark'), {
textContent: text.slice(start, start + length)
}),
text.slice(start + length)
);
};
utterance.onboundary = (event) => {
if (event.name === 'word') {
const length = event.charLength || (text.slice(event.charIndex).match(/^\S+/)?.[0].length ?? 0);
highlight(event.charIndex, length);
}
};
utterance.onend = () => { output.textContent = text; };
speechSynthesis.speak(utterance);
Fortschritt merken und später an der Stelle weiterlesen
const text = 'Kapitel eins. Es war einmal ein kleiner Browser, der sprechen lernte.';
let lastIndex = 0;
const speakFrom = (index) => {
const utterance = new SpeechSynthesisUtterance(text.slice(index));
utterance.onboundary = (event) => {
// charIndex bezieht sich auf den Teiltext, daher Offset addieren
lastIndex = index + event.charIndex;
};
speechSynthesis.speak(utterance);
};
speakFrom(0);
// Nach 2 Sekunden abbrechen und später fortsetzen
setTimeout(() => {
speechSynthesis.cancel();
console.log('Abgebrochen bei Index', lastIndex);
setTimeout(() => speakFrom(lastIndex), 1000);
}, 2000);
// Wichtig · Fallstricke
- Abhängig von der Stimme: Ob und wie oft
boundary-Ereignisse mit sinnvollemcharIndexkommen, legt die Sprach-Engine fest. Manche Online- oder Fremdstimmen, etwa bestimmte Google-Stimmen in Chrome, lösen gar keineboundary-Ereignisse aus. Chrome unter Android liefert teils nur Satzgrenzen. charLengthist nicht überall verfügbar: Ältere Safari- und Firefox-Versionen liefern keincharLength. Das Wortende muss man dann selbst auscharIndexund dem Text ermitteln.- Bezugspunkt: Der Index bezieht sich immer auf den Text der jeweiligen
SpeechSynthesisUtterance. Teilt man einen langen Text auf mehrere Äußerungen auf, muss man den Versatz selbst dazurechnen. - Kodierung: Der Index zählt UTF-16-Codeeinheiten. Emojis und andere Zeichen außerhalb der BMP belegen zwei Einheiten. Bei SSML-Eingaben, soweit die Engine sie unterstützt, kann der Index vom sichtbaren Text abweichen.
- Die Eigenschaft ist schreibgeschützt. Wer ihr etwas zuweist, bewirkt nichts (im Strict Mode kann das einen
TypeErrorauslösen).