Dieses Skript kann dir Artikel vorlesen. Es handelt sich aber nicht wirklich um ein Skript, das für den Produktiveinsatz geeignet ist, sondern nur um eine Machbarkeitsstudie. Die Vorlesefunktion wird dann in der Seitenleiste aktiviert, beachte den Tooltip zur Bedienung.
Einschränkungen
BearbeitenDas Skript ist nicht für den Produktiveinsatz gedacht. Insbesondere in den folgenden Fälle solltest du es nicht verwenden (oder dich zumindest nicht bei mir beschweren, wenn es nicht so funktioniert, wie du es gerne hättest):
- Als blinder oder stark sehbehinderter Benutzer nutze bitte einfach deinen gewöhnlichen Screenreader, dieser funktioniert wesentlich besser als dieses Skript.
- Wenn du wissen willst, wie sich blinde Benutzer hier zurechtfinden, dann nutze eine Testinstallation eines Screenreaders, dieses Skript liefert keinen allzu realistischen Eindruck.
- Wenn du einen alten Browser verwendest (etwa IE 8), dann vergiss dieses Skript. Es wird nicht funktionieren.
- Wenn du einfach nur gerne Artikel vorgelesen haben willst, dann nutze Portal:Gesprochene Wikipedia.
- Wenn du beliebige Artikel vorgelesen haben willst, dann nutze Wikipedia:Pediaphon.
- Wenn du der Ansicht bist, dass eine Vorlesefunktion in jeden Browser gehört, dann hast du vollkommen recht. Die CSS-Eigenschaften existieren seit CSS 2, langsam wäre es an der Zeit, dass die Browser endlich damit anfangen, diese umzusetzen.
Wenn du hier immer noch liest, bist du offenbar ein Spielkind, das gerne solche technischen Spielereien testet, in diesem Fall ist das Skript für dich richtig. Getestet wurde das Skript mit dem meSpeak.js
-Polyfill in Firefox und mit Firefox OS, beides funktioniert einigermaßen.
Einbindung
BearbeitenDie Einbindung des Skripts besteht aus zwei Teilen.
Speech-Synthesis-API
BearbeitenZunächst musst du dafür sorgen, dass dein Browser die Speech-Synthesis-API hinreichend gut implementiert, notfalls über einen Polyfill. Mir sind folgende Möglichkeiten bekannt:
- Nutze einen Browser mit Unterstützung der Web Speech API, siehe Web Speech API#Browserunterstützung.
- Nutze den janantalas Polyfill.
- Nutze den Polyfill auf Basis von
meSpeak.js
.
Beachte, dass bei janantalas Polyfill (und vermutlich auch bei Google Chrome) Web-APIs von Google zum Einsatz kommen. Das bedeutet, dass Google erfährt, was du dir vorlesen lässt, und dass je nach Internetverbindung Pausen auftreten können. meSpeak.js
und Firefox kommen ohne Online-Dienste aus.
janantalas Polyfill
BearbeitenUm den Polyfill von janantala zu nutzen, musst du das Skript polyfill.js ergänzen um
window.polyfillSpeechSynthesis = window.speechSynthesisPolyfill;
window.polyfillSpeechSynthesisUtterance = window.SpeechSynthesisUtterancePolyfill;
Polyfill auf Basis von meSpeak.js
Bearbeiten
Um den Polyfill auf Basis von meSpeak.js
zu nutzen, erstellst du eine Datei mit folgendem Inhalt:
(function () {
"use strict";
//meSpeak data
var meSpeakData = {
'_': 'hier Inhalt von mespeak_config.json',
en: 'hier Inhalt von voices/en/en.json',
de: 'hier Inhalt von voices/de.json'
};
//XMLHttpRequest mock
function XMLHttpRequest () {
}
XMLHttpRequest.prototype = {
readyState: 4,
open: function (_, url) {
this.responseText = meSpeakData[url];
this.status = url in meSpeakData ? 200 : 404;
},
send: function () {
this.onreadystatechange();
}
};
//meSpeak
//meSpeak init
meSpeak.loadConfig('_');
meSpeak.loadVoice('de');
meSpeak.loadVoice('en');
//SpeechSynthesis polyfill
var SpeechSynthesis = {
pending: false,
speaking: false,
paused: false,
speak: function (utterance) {
this._queue.push(utterance);
this.pending = true;
this._workQueue();
},
cancel: function () {
if (this.speaking) {
this._current._cancel();
}
this._queue = [];
this.pending = false;
this.speaking = false;
},
pause: function () {
if (!this.paused && this.speaking) {
this._current._pause();
}
this.paused = true;
},
resume: function () {
if (!this.paused) {
return;
}
if (this.speaking) {
this._current._resume();
}
this.paused = false;
this._workQueue();
},
getVoices: function () {
var lang, list = [], i, variants = ['', 'f1', 'f2', 'f3', 'f4', 'f5',
'm1', 'm2', 'm3', 'm4', 'm5', 'm6', 'm7', 'croak',
'klatt', 'klatt2', 'klatt3', 'whisper', 'whisperf'];
for (lang in meSpeakData) {
if (lang === '_') {
continue;
}
for (i = 0; i < variants.length; i++) {
list.push({
voiceURI: 'mespeak:' + lang + '/' + variants[i],
name: lang + ' (' + variants[i] + ')',
lang: lang,
localService: true,
'default': i === 0
});
}
}
return list;
},
_queue: [],
_workQueue: function () {
if (this.paused || this.speaking || !this.pending) {
return;
}
this._current = this._queue.shift();
this.pending = this._queue.length > 0;
this.speaking = true;
this._current._speak(function (canceled) {
if (canceled) {
return;
}
this.speaking = false;
this._workQueue();
}.bind(this));
}
};
function SpeechSynthesisUtterance (text) {
if (!(this instanceof SpeechSynthesisUtterance)) {
return new SpeechSynthesisUtterance(text);
}
this.text = text;
this.lang = '';
this.voiceURI = '';
this.volume = 1; //0 - 1
this.rate = 1; //0.1 - 10
this.pitch = 1; //0 - 2
this.onstart = undefined;
this.onend = undefined;
this.onerror = undefined;
this.onpause = undefined;
this.onresume = undefined;
//this.onmark = undefined;
//this.onboundery = undefined;
}
SpeechSynthesisUtterance.prototype = {
_speak: function (callback) {
this._fire('start');
var lang, variant;
lang = this.lang || document.documentElement.lang || 'en';
variant = this.voiceURI.replace(/.*\//, '');
if (!(lang in meSpeakData)) {
lang = lang.replace(/-.*/, '');
}
if (!(lang in meSpeakData)) {
this._fire('error');
callback();
return;
}
meSpeak.loadVoice(lang);
meSpeak.speak(this.text.replace(/Z/g, 'z'), { //Wörter mit großem Z werden aus irgendeinem Grund buchstabiert
amplitude: 100 * this.volume,
pitch: 50 * this.pitch,
speed: 175 * this.rate,
variant: variant,
ssml: true,
nostop: true
}, function () {
this._fire('end');
callback(this._canceled);
}.bind(this));
},
_cancel: function () {
this._canceled = true;
meSpeak.stop();
},
_pause: function () {
//this._fire('pause');
},
_resume: function () {
//this._fire('resume');
},
_fire: function (event) {
if (this['on' + event]) {
this['on' + event]();
}
}
};
window.polyfillSpeechSynthesis = SpeechSynthesis;
window.polyfillSpeechSynthesisUtterance = SpeechSynthesisUtterance;
})();
Lade meSpeak.js
von http://www.masswerk.at/mespeak/ herunter und ergänze diese Datei folgendermaßen: Der Inhalt von mespeak_config.json
muss ohne Zeilenumbrüche an die angegebene Stelle eingefügt werden (die Zeile lautet dann '_': '{"config":"..."}',
, gleiches gilt für die beiden Sprachdateien in den folgenden Zeilen. Analog können bei Bedarf auch noch mehr Sprachen ergänzt werden. Füge außerdem unterhalb des Kommentars //meSpeak
den Inhalt von mespeak.js
ein und speichere die Datei.
Polyfill-Dateien einbinden
BearbeitenBei der Verwendung eines Polyfills muss das entsprechende Skript korrekt geladen werden. Die jeweilige Datei musst du so zugänglich machen, dass dein Browser darauf zugreifen kann. Beachte, dass sie in beiden Fällen GPL-lizensiert ist (obiger Code darf hiermit sowohl unter GPL als auch wie alle Seiten hier unter CC-BY-SA genutzt werden), weshalb du sie nicht einfach als CC-lizensierte Unterseite in deinem BNR speichern kannst. Nutze einen „echten“ oder einen lokalen Webserver um die Datei auszuliefern, oder konfiguriere deinen Browser so, dass er auch file:
-URLs lädt und speichere sie irgendwo im lokalen Dateisystem. Füge eine Zeile mw.user.options.set('userjs-speechsynthesis-polyfill', 'HIER DIE URL ZUR DATEI');
in deine common.js ein.
vorleser.js
Bearbeiten
Das Skript selbst wird wie üblich eingebunden:
Falls du meine Skriptsammlung Fliegelflagel verwendest, kannst du das Skript in der Fliegelflagel-Konfiguration aktivieren.
Andere Benutzer können das Skript durch folgende Zeile in der eigenen common.js einbinden:
//[[Benutzer:Schnark/js/vorleser.js]]
mw.loader.load('https://de.wikipedia.org/w/index.php?title=Benutzer:Schnark/js/vorleser.js&action=raw&ctype=text/javascript');
Code
BearbeitenDer Javascript-Code befindet sich unter Benutzer:Schnark/js/vorleser.js.