Last active
August 7, 2018 20:13
-
-
Save xfenix/58a739479c16aeaeb8300e83917b43d9 to your computer and use it in GitHub Desktop.
Browser speech generator (with chrome chunk bug fix)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(function() { | |
// article voice synth | |
var SpeechGenerator = function() { | |
var that = this; | |
this.STATES = { STOP: 0, RUN: 1, PAUSE: 2 }; | |
this.chunkSize = 190; | |
this.$root = $('.content'); | |
this.subTitleClass = 'second_title'; | |
this.status = this.STATES.STOP; | |
this.language = 'ru-RU'; | |
this.matcher = new RegExp('(.{1,' + this.chunkSize + '}[,.!?]|.{1,' + this.chunkSize + '})', 'g'); | |
this.textParts = []; | |
this.engine = window.speechSynthesis; | |
this.init = function() { | |
if(this.isEnabled()) { | |
this.textParts = this.prepareText(); | |
this.bindEvents(); | |
} | |
}; | |
this.isEnabled = function() { | |
if('speechSynthesis' in window) { | |
var i, voices = this.engine.getVoices(); | |
for(i in voices) { | |
if(voices[i].lang == this.language) { | |
return true; | |
} | |
} | |
} | |
return false; | |
} | |
this.prepareText = function() { | |
// сначала собираем текст | |
var i, j, matchParts, fullText = '', resultParts = [], | |
textParts = [ | |
this.$root.find('h1').text(), | |
this.$root.find('.' + this.subTitleClass).text(), | |
]; | |
// подготовим текст | |
this.$root.find('p').each(function() { | |
var localText = $.trim($(this).text()); | |
if(localText.length > 0 && !$(this).hasClass(that.subTitleClass)) { | |
fullText += localText + ' '; | |
} | |
}); | |
// разделяем на части по точкам обязательно | |
// иначе текст невозможно слушать | |
textParts = $.merge(textParts, fullText.split('.')); | |
for(i in textParts) { | |
// а потом каждый элемент разделяем по регулярке, | |
// на случай больших предложений | |
if(textParts[i].length > this.chunkSize) { | |
matchParts = textParts[i].match(this.matcher); | |
for(j in matchParts) { | |
resultParts.push($.trim(matchParts[j])); | |
} | |
} else { | |
resultParts.push($.trim(textParts[i])); | |
} | |
} | |
return resultParts; | |
}; | |
this.bindEvents = function() { | |
// запускаем синтез при клике на play | |
$('#generateme').on('click', function() { | |
if(that.status == that.STATES.STOP) { | |
that.runGeneration(); | |
} else if(that.status == that.STATES.PAUSE) { | |
that.resume(); | |
} else { | |
that.pause(); | |
} | |
return false; | |
}); | |
// при закрытии страницы, обновлении, т.п. | |
// отключаем синтез речи | |
$(window).on('beforeunload', function() { | |
that.stop(); | |
}); | |
}; | |
this.runGeneration = function() { | |
var i, synthConfig; | |
// сбросим состояние на всякий случай | |
this.stop(); | |
// и не забудем проставить статус | |
this.status = this.STATES.RUN; | |
for(i in this.textParts) { | |
synthConfig = new SpeechSynthesisUtterance(); | |
synthConfig.lang = 'ru-RU'; | |
synthConfig.text = this.textParts[i]; | |
that.engine.speak(synthConfig); | |
} | |
}; | |
this.stop = function() { | |
this.status = this.STATES.STOP; | |
this.engine.cancel(); | |
}; | |
this.pause = function() { | |
this.status = this.STATES.PAUSE; | |
this.engine.pause(); | |
}; | |
this.resume = function() { | |
this.status = this.STATES.RUN; | |
this.engine.resume(); | |
}; | |
return this.init(); | |
}; | |
window.speak = new SpeechGenerator(); | |
})(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment