speak-tts
Version:
Browser TTS (using Web speech API) made easy
281 lines (243 loc) • 9.25 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _utils = require("./utils");
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }
var SpeakTTS =
/*#__PURE__*/
function () {
function SpeakTTS() {
_classCallCheck(this, SpeakTTS);
this.browserSupport = 'speechSynthesis' in window && 'SpeechSynthesisUtterance' in window;
this.synthesisVoice = null;
}
_createClass(SpeakTTS, [{
key: "init",
value: function init() {
var _this = this;
var conf = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
return new Promise(function (resolve, reject) {
if (!_this.browserSupport) {
reject('Your browser does not support Speech Synthesis');
}
var listeners = (0, _utils.isNil)(conf.listeners) ? {} : conf.listeners;
var splitSentences = (0, _utils.isNil)(conf.splitSentences) ? true : conf.splitSentences;
var lang = (0, _utils.isNil)(conf.lang) ? undefined : conf.lang;
var volume = (0, _utils.isNil)(conf.volume) ? 1 : conf.volume;
var rate = (0, _utils.isNil)(conf.rate) ? 1 : conf.rate;
var pitch = (0, _utils.isNil)(conf.pitch) ? 1 : conf.pitch;
var voice = (0, _utils.isNil)(conf.voice) ? undefined : conf.voice; // Attach event listeners
Object.keys(listeners).forEach(function (listener) {
var fn = listeners[listener];
var newListener = function newListener(data) {
fn && fn(data);
};
if (listener !== 'onvoiceschanged') {
speechSynthesis[listener] = newListener;
}
});
_this._loadVoices().then(function (voices) {
// Handle callback onvoiceschanged by hand
listeners['onvoiceschanged'] && listeners['onvoiceschanged'](voices); // Initialize values if necessary
!(0, _utils.isNil)(lang) && _this.setLanguage(lang);
!(0, _utils.isNil)(voice) && _this.setVoice(voice);
!(0, _utils.isNil)(volume) && _this.setVolume(volume);
!(0, _utils.isNil)(rate) && _this.setRate(rate);
!(0, _utils.isNil)(pitch) && _this.setPitch(pitch);
!(0, _utils.isNil)(splitSentences) && _this.setSplitSentences(splitSentences);
resolve({
voices: voices,
lang: _this.lang,
voice: _this.voice,
volume: _this.volume,
rate: _this.rate,
pitch: _this.pitch,
splitSentences: _this.splitSentences,
browserSupport: _this.browserSupport
});
}).catch(function (e) {
reject(e);
});
});
}
}, {
key: "_fetchVoices",
value: function _fetchVoices() {
return new Promise(function (resolve, reject) {
setTimeout(function () {
var voices = speechSynthesis.getVoices();
if ((0, _utils.size)(voices) > 0) {
return resolve(voices);
} else {
return reject("Could not fetch voices");
}
}, 100);
});
}
}, {
key: "_loadVoices",
value: function _loadVoices() {
var _this2 = this;
var remainingAttempts = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 10;
return this._fetchVoices().catch(function (error) {
if (remainingAttempts === 0) throw error;
return _this2._loadVoices(remainingAttempts - 1);
});
}
}, {
key: "hasBrowserSupport",
value: function hasBrowserSupport() {
return this.browserSupport;
}
}, {
key: "setVoice",
value: function setVoice(voice) {
var synthesisVoice;
var voices = speechSynthesis.getVoices(); // set voice by name
if ((0, _utils.isString)(voice)) {
synthesisVoice = voices.find(function (v) {
return v.name === voice;
});
} // Set the voice in conf if found
if ((0, _utils.isObject)(voice)) {
synthesisVoice = voice;
}
if (synthesisVoice) {
this.synthesisVoice = synthesisVoice;
} else {
throw 'Error setting voice. The voice you passed is not valid or the voices have not been loaded yet.';
}
}
}, {
key: "setLanguage",
value: function setLanguage(lang) {
lang = lang.replace('_', '-'); // some Android versions seem to ignore BCP 47 and use an underscore character in language tag
if ((0, _utils.validateLocale)(lang)) {
this.lang = lang;
} else {
throw 'Error setting language. Please verify your locale is BCP47 format (http://schneegans.de/lv/?tags=es-FR&format=text)';
}
}
}, {
key: "setVolume",
value: function setVolume(volume) {
volume = parseFloat(volume);
if (!(0, _utils.isNan)(volume) && volume >= 0 && volume <= 1) {
this.volume = volume;
} else {
throw 'Error setting volume. Please verify your volume value is a number between 0 and 1.';
}
}
}, {
key: "setRate",
value: function setRate(rate) {
rate = parseFloat(rate);
if (!(0, _utils.isNan)(rate) && rate >= 0 && rate <= 10) {
this.rate = rate;
} else {
throw 'Error setting rate. Please verify your volume value is a number between 0 and 10.';
}
}
}, {
key: "setPitch",
value: function setPitch(pitch) {
pitch = parseFloat(pitch);
if (!(0, _utils.isNan)(pitch) && pitch >= 0 && pitch <= 2) {
this.pitch = pitch;
} else {
throw 'Error setting pitch. Please verify your pitch value is a number between 0 and 2.';
}
}
}, {
key: "setSplitSentences",
value: function setSplitSentences(splitSentences) {
this.splitSentences = splitSentences;
}
}, {
key: "speak",
value: function speak(data) {
var _this3 = this;
return new Promise(function (resolve, reject) {
var text = data.text,
_data$listeners = data.listeners,
listeners = _data$listeners === void 0 ? {} : _data$listeners,
_data$queue = data.queue,
queue = _data$queue === void 0 ? true : _data$queue;
var msg = (0, _utils.trim)(text);
if ((0, _utils.isNil)(msg)) resolve(); // Stop current speech
!queue && _this3.cancel(); // Split into sentences (for better result and bug with some versions of chrome)
var utterances = [];
var sentences = _this3.splitSentences ? (0, _utils.splitSentences)(msg) : [msg];
sentences.forEach(function (sentence, index) {
var isLast = index === (0, _utils.size)(sentences) - 1;
var utterance = new SpeechSynthesisUtterance();
if (_this3.synthesisVoice) utterance.voice = _this3.synthesisVoice;
if (_this3.lang) utterance.lang = _this3.lang;
if (_this3.volume) utterance.volume = _this3.volume; // 0 to 1
if (_this3.rate) utterance.rate = _this3.rate; // 0.1 to 10
if (_this3.pitch) utterance.pitch = _this3.pitch; //0 to 2
utterance.text = sentence; // Attach event listeners
Object.keys(listeners).forEach(function (listener) {
var fn = listeners[listener];
var newListener = function newListener(data) {
fn && fn(data);
if (listener === 'onerror') {
reject({
utterances: utterances,
lastUtterance: utterance,
error: data
});
}
if (listener === 'onend') {
if (isLast) resolve({
utterances: utterances,
lastUtterance: utterance
});
}
};
utterance[listener] = newListener;
});
utterances.push(utterance);
speechSynthesis.speak(utterance);
});
});
}
}, {
key: "pending",
value: function pending() {
return speechSynthesis.pending;
}
}, {
key: "paused",
value: function paused() {
return speechSynthesis.paused;
}
}, {
key: "speaking",
value: function speaking() {
return speechSynthesis.speaking;
}
}, {
key: "pause",
value: function pause() {
speechSynthesis.pause();
}
}, {
key: "resume",
value: function resume() {
speechSynthesis.resume();
}
}, {
key: "cancel",
value: function cancel() {
speechSynthesis.cancel();
}
}]);
return SpeakTTS;
}();
var _default = SpeakTTS;
exports.default = _default;