admin管理员组文章数量:1416629
I would like to read the text of my pages with SpeechSynthesisUtterance.
I found this script: /
Almost perfect, but the pause button doesn't seem to do much, and I wish I had the ability to set a language and maybe choose a voice.
I found the reference here: , but I'm not very knowledgeable in JavaScript.
For language, as far as I understand, should be used the lang parameter set in the html tag.
For the voice I have absolutely no idea of how to implement it in the code.
It would be important because I have texts in English, Spanish, French and Italian, and the result without voice and language settings sometimes sounds really weird.
Update
These days I fiddled a little, I managed (more or less) to bine two different scripts/examples.
This: /
and this:
The code that came out is this:
HTML
<html>
<head>
<link rel="stylesheet" href="style.css">
<script src="text-to-speech.js"></script>
</head>
<body>
<div class=buttons>
<button id=play></button>
<button id=pause></button>
<button id=stop></button>
</div>
<select id="voices">
</select>
<div id="description">
The SpeechSynthesis interface of the Web Speech API is the controller interface for the speech service; this can be used to retrieve information about the synthesis voices available on the device, start and pause speech, and other mands besides.
Questo è in italiano e viene?
</div>
</body>
</html>
CSS
@import url('+Text');
.buttons {
margin-top: 25px;
}
button {
background: none;
border: none;
cursor: pointer;
height: 48px;
outline: none;
padding: 0;
width: 48px;
}
#play {
background-image: url(.svg);
}
#play.played {
background-image: url(.svg);
}
#pause {
background-image: url(.svg);
}
#pause.paused {
background-image: url(.svg);
}
#stop {
background-image: url(.svg);
}
#stop.stopped {
background-image: url(.svg);
}
JAVASCRIPT
onload = function() {
if ('speechSynthesis' in window) with(speechSynthesis) {
// select voices////
var synth = window.speechSynthesis;
var voiceSelect = document.querySelector('#voices');
var voices = [];
function populateVoiceList() {
voices = synth.getVoices().sort(function (a, b) {
const aname = a.name.toUpperCase(), bname = b.name.toUpperCase();
if ( aname < bname ) return -1;
else if ( aname == bname ) return 0;
else return +1;
});
var selectedIndex = voiceSelect.selectedIndex < 0 ? 0 : voiceSelect.selectedIndex;
voiceSelect.innerHTML = '';
for(i = 0; i < voices.length ; i++) {
var option = document.createElement('option');
option.textContent = voices[i].name + ' (' + voices[i].lang + ')';
if(voices[i].default) {
option.textContent += ' -- DEFAULT';
}
option.setAttribute('data-lang', voices[i].lang);
option.setAttribute('data-name', voices[i].name);
voiceSelect.appendChild(option);
}
voiceSelect.selectedIndex = selectedIndex;
}
populateVoiceList();
if (speechSynthesis.onvoiceschanged !== undefined) {
speechSynthesis.onvoiceschanged = populateVoiceList;
}
//end select voices
var playEle = document.querySelector('#play');
var pauseEle = document.querySelector('#pause');
var stopEle = document.querySelector('#stop');
var flag = false;
playEle.addEventListener('click', onClickPlay);
pauseEle.addEventListener('click', onClickPause);
stopEle.addEventListener('click', onClickStop);
function onClickPlay() {
if (!flag) {
flag = true;
utterance = new SpeechSynthesisUtterance(document.querySelector('#description').textContent);
//utterance.voice = getVoices()[0];
//add voice//
var selectedOption = voiceSelect.selectedOptions[0].getAttribute('data-name');
for(i = 0; i < voices.length ; i++) {
//if(voices[i].name === 'Google UK English Female') {
if(voices[i].name === selectedOption) {
utterance.voice = voices[i];
break;
}
}
voiceSelect.onchange = function(){
onClickStop();
stopEle.className = '';
onClickPlay();
playEle.className = 'played';
}
//and add voice
utterance.onend = function() {
flag = false;
playEle.className = pauseEle.className = '';
stopEle.className = 'stopped';
};
playEle.className = 'played';
stopEle.className = '';
speak(utterance);
}
if (paused) { /* unpause/resume narration */
playEle.className = 'played';
pauseEle.className = '';
resume();
}
}
function onClickPause() {
if (speaking && !paused) { /* pause narration */
pauseEle.className = 'paused';
playEle.className = '';
pause();
}
}
function onClickStop() {
if (speaking) { /* stop narration */
/* for safari */
stopEle.className = 'stopped';
playEle.className = pauseEle.className = '';
flag = false;
cancel();
}
}
}
else { /* speech synthesis not supported */
msg = document.createElement('h5');
msg.textContent = "Detected no support for Speech Synthesis";
msg.style.textAlign = 'center';
msg.style.backgroundColor = 'red';
msg.style.color = 'white';
msg.style.marginTop = msg.style.marginBottom = 0;
document.body.insertBefore(msg, document.querySelector('div'));
}
}
Now I have the play, stop and pause buttons (pauses still does not work) and I can select one of the voices from those available in the device.
Seems to work fine with chrome, maybe a little less with Firefox, (but I'm using Linux LMDE, maybe it's my fault). And after a while on Chrome stops talking. I don't know why, but it seems to me that I've seen someone maybe understand why in some of the thousands of web pages I've opened these days, I'll have to reopen them all.
It would be nice if the selected voice was saved in a cookie, so if I open another page the script starts with the last voice I selected (I have no idea how to do it in JavaScript)
Update 2
I made some other small steps forward and simplified.
It almost seems to work, not always the pause button, the big doubt I have now is that with chrome it does not seem to stop when I update or change pages, and it is really bad that when you change page he keeps reading the previous page.
HTML
<div id="SpeechSynthesis">
<div>
<button id=play>play</button>
<button id=pause>pause</button>
<button id=stop>stop</button>
</div>
<select id="voices">
</select>
</div>
<p id="texttospeech">
The SpeechSynthesis interface of the Web Speech API is the controller interface for the speech service; this can be used to retrieve information about the synthesis voices available on the device, start and pause speech, and other mands besides.
Questo è in italiano e viene?
</p>
JAVASCRIPT
onload = function() {
if ('speechSynthesis' in window){
var synth = speechSynthesis;
var flag = false;
//stop when change page ???(not sure)
if(synth.speaking){ /* stop narration */
/* for safari */
flag = false;
synth.cancel();
}
/* references to the buttons */
var playEle = document.querySelector('#play');
var pauseEle = document.querySelector('#pause');
var stopEle = document.querySelector('#stop');
/* click event handlers for the buttons */
playEle.addEventListener('click', onClickPlay);
pauseEle.addEventListener('click', onClickPause);
stopEle.addEventListener('click', onClickStop);
// select voices////
//var synth = window.speechSynthesis;
var voiceSelect = document.querySelector('#voices');
var voices = [];
function populateVoiceList() {
voices = synth.getVoices().sort(function (a, b) {
const aname = a.name.toUpperCase(), bname = b.name.toUpperCase();
if ( aname < bname ) return -1;
else if ( aname == bname ) return 0;
else return +1;
});
var selectedIndex = voiceSelect.selectedIndex < 0 ? 0 : voiceSelect.selectedIndex;
voiceSelect.innerHTML = '';
for(i = 0; i < voices.length ; i++) {
var option = document.createElement('option');
option.textContent = voices[i].name + ' (' + voices[i].lang + ')';
if(voices[i].default) {
option.textContent += ' -- DEFAULT';
}
option.setAttribute('data-lang', voices[i].lang);
option.setAttribute('data-name', voices[i].name);
voiceSelect.appendChild(option);
}
voiceSelect.selectedIndex = selectedIndex;
}
populateVoiceList();
if (speechSynthesis.onvoiceschanged !== undefined) {
speechSynthesis.onvoiceschanged = populateVoiceList;
}
//end select voices
function onClickPlay() {
if(!flag){
flag = true;
utterance = new SpeechSynthesisUtterance(document.querySelector('#texttospeech').textContent);
//utterance.voice = synth.getVoices()[0];
//add voice//
var selectedOption = voiceSelect.selectedOptions[0].getAttribute('data-name');
for(i = 0; i < voices.length ; i++) {
//if(voices[i].name === 'Google UK English Female') {
if(voices[i].name === selectedOption) {
utterance.voice = voices[i];
break;
}
}
voiceSelect.onchange = function(){
onClickStop();
onClickPlay();
}
//and add voice
utterance.onend = function(){
flag = false;
};
synth.speak(utterance);
//fix stop after a while bug
let r = setInterval(() => {
console.log(speechSynthesis.speaking);
if (!speechSynthesis.speaking) {
clearInterval(r);
} else {
speechSynthesis.resume();
}
}, 14000);
//end fix stop after a while bug
}
if(synth.paused) { /* unpause/resume narration */
synth.resume();
}
}
function onClickPause() {
if(synth.speaking && !synth.paused){ /* pause narration */
synth.pause();
}
}
function onClickStop() {
if(synth.speaking){ /* stop narration */
/* for safari */
flag = false;
synth.cancel();
}
}
}
else {
msg = document.createElement('h5');
msg.textContent = "Detected no support for Speech Synthesis";
msg.style.textAlign = 'center';
msg.style.backgroundColor = 'red';
msg.style.color = 'white';
msg.style.marginTop = msg.style.marginBottom = 0;
document.body.insertBefore(msg, document.querySelector('#SpeechSynthesis'));
}
}
Update 3
I tried to add a cookie with the last selected voice. I added a couple of functions to manage the cookies, and I set the cookie in the onClickPlay() function.
//add voice//
var selectedOption = voiceSelect.selectedOptions[0].getAttribute('data-name');
for(i = 0; i < voices.length ; i++) {
//if(voices[i].name === 'Google UK English Female') {
if(voices[i].name === selectedOption) {
utterance.voice = voices[i];
setCookie('SpeechSynthesisVoice',voices[i].name,30);
break;
}
}
Firefox sets the cookie without problems, chrome no (even if the file is on an online server).
Then I tried to set the voice saved in the cookie as "selected" in populateVoiceList() function:
//get cookie voice
var cookievoice = getCookie('SpeechSynthesisVoice');
//add selcted to option if if cookievoice
if (cookievoice === voices[i].name) {
option.setAttribute('selected', 'selected');
}
It works, I find the "selected" in the code, but it doesn't seem to be considered, it always starts talking with the first voice in the list, or the default one, I'm not sure, and not with the one that has the "selected".
The cookie functions I use:
//cookie functions
function setCookie(name, value, days) {
var expires = '',
date = new Date();
if (days) {
date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));
expires = '; expires=' + date.toGMTString();
}
document.cookie = name + '=' + value + expires + '; path=/';
}
function getCookie(name) {
var cookies = document.cookie.split(';'),
length = cookies.length,
i,
cookie,
nameEQ = name + '=';
for (i = 0; i < length; i += 1) {
cookie = cookies[i];
while (cookie.charAt(0) === ' ') {
cookie = cookie.substring(1, cookie.length);
}
if (cookie.indexOf(nameEQ) === 0) {
return cookie.substring(nameEQ.length, cookie.length);
}
}
return null;
}
function eraseCookie(name) {
createCookie(name, '', -1);
}
I would like to read the text of my pages with SpeechSynthesisUtterance.
I found this script: https://www.hongkiat./blog/text-to-speech/
Almost perfect, but the pause button doesn't seem to do much, and I wish I had the ability to set a language and maybe choose a voice.
I found the reference here: https://developer.mozilla/en-US/docs/Web/API/SpeechSynthesisUtterance, but I'm not very knowledgeable in JavaScript.
For language, as far as I understand, should be used the lang parameter set in the html tag.
For the voice I have absolutely no idea of how to implement it in the code.
It would be important because I have texts in English, Spanish, French and Italian, and the result without voice and language settings sometimes sounds really weird.
Update
These days I fiddled a little, I managed (more or less) to bine two different scripts/examples.
This: https://www.hongkiat./blog/text-to-speech/
and this: https://developer.mozilla/en-US/docs/Web/API/SpeechSynthesis#Examples
The code that came out is this:
HTML
<html>
<head>
<link rel="stylesheet" href="style.css">
<script src="text-to-speech.js"></script>
</head>
<body>
<div class=buttons>
<button id=play></button>
<button id=pause></button>
<button id=stop></button>
</div>
<select id="voices">
</select>
<div id="description">
The SpeechSynthesis interface of the Web Speech API is the controller interface for the speech service; this can be used to retrieve information about the synthesis voices available on the device, start and pause speech, and other mands besides.
Questo è in italiano e viene?
</div>
</body>
</html>
CSS
@import url('https://fonts.googleapis./css?family=Crimson+Text');
.buttons {
margin-top: 25px;
}
button {
background: none;
border: none;
cursor: pointer;
height: 48px;
outline: none;
padding: 0;
width: 48px;
}
#play {
background-image: url(https://rpsthecoder.github.io/js-speech-synthesis/play.svg);
}
#play.played {
background-image: url(https://rpsthecoder.github.io/js-speech-synthesis/play1.svg);
}
#pause {
background-image: url(https://rpsthecoder.github.io/js-speech-synthesis/pause.svg);
}
#pause.paused {
background-image: url(https://rpsthecoder.github.io/js-speech-synthesis/pause1.svg);
}
#stop {
background-image: url(https://rpsthecoder.github.io/js-speech-synthesis/stop.svg);
}
#stop.stopped {
background-image: url(https://rpsthecoder.github.io/js-speech-synthesis/stop1.svg);
}
JAVASCRIPT
onload = function() {
if ('speechSynthesis' in window) with(speechSynthesis) {
// select voices////
var synth = window.speechSynthesis;
var voiceSelect = document.querySelector('#voices');
var voices = [];
function populateVoiceList() {
voices = synth.getVoices().sort(function (a, b) {
const aname = a.name.toUpperCase(), bname = b.name.toUpperCase();
if ( aname < bname ) return -1;
else if ( aname == bname ) return 0;
else return +1;
});
var selectedIndex = voiceSelect.selectedIndex < 0 ? 0 : voiceSelect.selectedIndex;
voiceSelect.innerHTML = '';
for(i = 0; i < voices.length ; i++) {
var option = document.createElement('option');
option.textContent = voices[i].name + ' (' + voices[i].lang + ')';
if(voices[i].default) {
option.textContent += ' -- DEFAULT';
}
option.setAttribute('data-lang', voices[i].lang);
option.setAttribute('data-name', voices[i].name);
voiceSelect.appendChild(option);
}
voiceSelect.selectedIndex = selectedIndex;
}
populateVoiceList();
if (speechSynthesis.onvoiceschanged !== undefined) {
speechSynthesis.onvoiceschanged = populateVoiceList;
}
//end select voices
var playEle = document.querySelector('#play');
var pauseEle = document.querySelector('#pause');
var stopEle = document.querySelector('#stop');
var flag = false;
playEle.addEventListener('click', onClickPlay);
pauseEle.addEventListener('click', onClickPause);
stopEle.addEventListener('click', onClickStop);
function onClickPlay() {
if (!flag) {
flag = true;
utterance = new SpeechSynthesisUtterance(document.querySelector('#description').textContent);
//utterance.voice = getVoices()[0];
//add voice//
var selectedOption = voiceSelect.selectedOptions[0].getAttribute('data-name');
for(i = 0; i < voices.length ; i++) {
//if(voices[i].name === 'Google UK English Female') {
if(voices[i].name === selectedOption) {
utterance.voice = voices[i];
break;
}
}
voiceSelect.onchange = function(){
onClickStop();
stopEle.className = '';
onClickPlay();
playEle.className = 'played';
}
//and add voice
utterance.onend = function() {
flag = false;
playEle.className = pauseEle.className = '';
stopEle.className = 'stopped';
};
playEle.className = 'played';
stopEle.className = '';
speak(utterance);
}
if (paused) { /* unpause/resume narration */
playEle.className = 'played';
pauseEle.className = '';
resume();
}
}
function onClickPause() {
if (speaking && !paused) { /* pause narration */
pauseEle.className = 'paused';
playEle.className = '';
pause();
}
}
function onClickStop() {
if (speaking) { /* stop narration */
/* for safari */
stopEle.className = 'stopped';
playEle.className = pauseEle.className = '';
flag = false;
cancel();
}
}
}
else { /* speech synthesis not supported */
msg = document.createElement('h5');
msg.textContent = "Detected no support for Speech Synthesis";
msg.style.textAlign = 'center';
msg.style.backgroundColor = 'red';
msg.style.color = 'white';
msg.style.marginTop = msg.style.marginBottom = 0;
document.body.insertBefore(msg, document.querySelector('div'));
}
}
Now I have the play, stop and pause buttons (pauses still does not work) and I can select one of the voices from those available in the device.
Seems to work fine with chrome, maybe a little less with Firefox, (but I'm using Linux LMDE, maybe it's my fault). And after a while on Chrome stops talking. I don't know why, but it seems to me that I've seen someone maybe understand why in some of the thousands of web pages I've opened these days, I'll have to reopen them all.
It would be nice if the selected voice was saved in a cookie, so if I open another page the script starts with the last voice I selected (I have no idea how to do it in JavaScript)
Update 2
I made some other small steps forward and simplified.
It almost seems to work, not always the pause button, the big doubt I have now is that with chrome it does not seem to stop when I update or change pages, and it is really bad that when you change page he keeps reading the previous page.
HTML
<div id="SpeechSynthesis">
<div>
<button id=play>play</button>
<button id=pause>pause</button>
<button id=stop>stop</button>
</div>
<select id="voices">
</select>
</div>
<p id="texttospeech">
The SpeechSynthesis interface of the Web Speech API is the controller interface for the speech service; this can be used to retrieve information about the synthesis voices available on the device, start and pause speech, and other mands besides.
Questo è in italiano e viene?
</p>
JAVASCRIPT
onload = function() {
if ('speechSynthesis' in window){
var synth = speechSynthesis;
var flag = false;
//stop when change page ???(not sure)
if(synth.speaking){ /* stop narration */
/* for safari */
flag = false;
synth.cancel();
}
/* references to the buttons */
var playEle = document.querySelector('#play');
var pauseEle = document.querySelector('#pause');
var stopEle = document.querySelector('#stop');
/* click event handlers for the buttons */
playEle.addEventListener('click', onClickPlay);
pauseEle.addEventListener('click', onClickPause);
stopEle.addEventListener('click', onClickStop);
// select voices////
//var synth = window.speechSynthesis;
var voiceSelect = document.querySelector('#voices');
var voices = [];
function populateVoiceList() {
voices = synth.getVoices().sort(function (a, b) {
const aname = a.name.toUpperCase(), bname = b.name.toUpperCase();
if ( aname < bname ) return -1;
else if ( aname == bname ) return 0;
else return +1;
});
var selectedIndex = voiceSelect.selectedIndex < 0 ? 0 : voiceSelect.selectedIndex;
voiceSelect.innerHTML = '';
for(i = 0; i < voices.length ; i++) {
var option = document.createElement('option');
option.textContent = voices[i].name + ' (' + voices[i].lang + ')';
if(voices[i].default) {
option.textContent += ' -- DEFAULT';
}
option.setAttribute('data-lang', voices[i].lang);
option.setAttribute('data-name', voices[i].name);
voiceSelect.appendChild(option);
}
voiceSelect.selectedIndex = selectedIndex;
}
populateVoiceList();
if (speechSynthesis.onvoiceschanged !== undefined) {
speechSynthesis.onvoiceschanged = populateVoiceList;
}
//end select voices
function onClickPlay() {
if(!flag){
flag = true;
utterance = new SpeechSynthesisUtterance(document.querySelector('#texttospeech').textContent);
//utterance.voice = synth.getVoices()[0];
//add voice//
var selectedOption = voiceSelect.selectedOptions[0].getAttribute('data-name');
for(i = 0; i < voices.length ; i++) {
//if(voices[i].name === 'Google UK English Female') {
if(voices[i].name === selectedOption) {
utterance.voice = voices[i];
break;
}
}
voiceSelect.onchange = function(){
onClickStop();
onClickPlay();
}
//and add voice
utterance.onend = function(){
flag = false;
};
synth.speak(utterance);
//fix stop after a while bug
let r = setInterval(() => {
console.log(speechSynthesis.speaking);
if (!speechSynthesis.speaking) {
clearInterval(r);
} else {
speechSynthesis.resume();
}
}, 14000);
//end fix stop after a while bug
}
if(synth.paused) { /* unpause/resume narration */
synth.resume();
}
}
function onClickPause() {
if(synth.speaking && !synth.paused){ /* pause narration */
synth.pause();
}
}
function onClickStop() {
if(synth.speaking){ /* stop narration */
/* for safari */
flag = false;
synth.cancel();
}
}
}
else {
msg = document.createElement('h5');
msg.textContent = "Detected no support for Speech Synthesis";
msg.style.textAlign = 'center';
msg.style.backgroundColor = 'red';
msg.style.color = 'white';
msg.style.marginTop = msg.style.marginBottom = 0;
document.body.insertBefore(msg, document.querySelector('#SpeechSynthesis'));
}
}
Update 3
I tried to add a cookie with the last selected voice. I added a couple of functions to manage the cookies, and I set the cookie in the onClickPlay() function.
//add voice//
var selectedOption = voiceSelect.selectedOptions[0].getAttribute('data-name');
for(i = 0; i < voices.length ; i++) {
//if(voices[i].name === 'Google UK English Female') {
if(voices[i].name === selectedOption) {
utterance.voice = voices[i];
setCookie('SpeechSynthesisVoice',voices[i].name,30);
break;
}
}
Firefox sets the cookie without problems, chrome no (even if the file is on an online server).
Then I tried to set the voice saved in the cookie as "selected" in populateVoiceList() function:
//get cookie voice
var cookievoice = getCookie('SpeechSynthesisVoice');
//add selcted to option if if cookievoice
if (cookievoice === voices[i].name) {
option.setAttribute('selected', 'selected');
}
It works, I find the "selected" in the code, but it doesn't seem to be considered, it always starts talking with the first voice in the list, or the default one, I'm not sure, and not with the one that has the "selected".
The cookie functions I use:
//cookie functions
function setCookie(name, value, days) {
var expires = '',
date = new Date();
if (days) {
date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));
expires = '; expires=' + date.toGMTString();
}
document.cookie = name + '=' + value + expires + '; path=/';
}
function getCookie(name) {
var cookies = document.cookie.split(';'),
length = cookies.length,
i,
cookie,
nameEQ = name + '=';
for (i = 0; i < length; i += 1) {
cookie = cookies[i];
while (cookie.charAt(0) === ' ') {
cookie = cookie.substring(1, cookie.length);
}
if (cookie.indexOf(nameEQ) === 0) {
return cookie.substring(nameEQ.length, cookie.length);
}
}
return null;
}
function eraseCookie(name) {
createCookie(name, '', -1);
}
Share
Improve this question
edited Jan 17, 2020 at 23:09
halfer
20.3k19 gold badges109 silver badges202 bronze badges
asked Nov 8, 2019 at 0:35
alebalalebal
5,9064 gold badges14 silver badges31 bronze badges
3
- This reads like a journal entry. Can I ask what the question is? – Frazer Commented Nov 8, 2019 at 8:18
- Pause button doesn't work... and I want add lang and permit the visitor to chose a voice from all the voices in the device – alebal Commented Nov 8, 2019 at 21:13
- Speech synthesis isn't handles the same by all browsers; that code won't always work on Chrome or Firefox for example. The flag the code uses to determine if there is speech running is superfluous as speech will queue. I suggest using separate pause and resume buttons. – Frazer Commented Nov 9, 2019 at 15:51
2 Answers
Reset to default 4I didn't receive much help, but somehow I managed to set up a small player that reads the text of a web page.
I did a little tutorial with a demo that explains what I did and how it works.
https://www.alebalweb-blog./85-text-to-speech-player-with-buttons-play-pause-stop-and-voice-choice.html
How about this line after the "for" loop?
voiceSelect.selectedIndex = selectedIndex;
If it's still here you're overriding your selection. Try something like
if(cookievoice === voices[i].name) {
option.setAttribute('selected', 'selected');
selectedIndex = i;
}
本文标签:
版权声明:本文标题:javascript - SpeechSynthesisUtterance script with play, pause, stop buttons and selection of language and voice - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1742171268a2426757.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论