UNPKG

speak-tts

Version:

Browser TTS (using Web speech API) made easy

281 lines (243 loc) 9.25 kB
"use strict"; 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;