Thursday, 20 October 2022

Javascript - How to get more voices for text to speech?

I made this little script where you can enter some message and it reads it out.

I solved it by using FireFox SpeechSynthesis API.

How can I get more voices and support for more languages?

Note: There is a "bug" in SO. If I edit my question and edit the script and test it from there, then 4 voices are loading. If I run the code snippet normally, then no voices are loading, but the default voice.

if ('speechSynthesis' in window) {
 // Speech Synthesis supported
} else {
  // Speech Synthesis Not Supported
  alert("Sorry, your browser doesn't support text to speech!");
}

const voices = speechSynthesis.getVoices();
populateVoiceList();

if (typeof speechSynthesis !== 'undefined' && speechSynthesis.onvoiceschanged !== undefined) {
  speechSynthesis.onvoiceschanged = populateVoiceList;
}

var selectedLang = $("#voiceSelect").find("option").attr("data-lang");
var selectedVoice = $("#voiceSelect").find("option").attr("data-pos");

$("#voiceSelect").change(function() {
   selectedLang = $(this).find("option:selected").attr("data-lang");
   selectedVoice = $(this).find("option:selected").attr("data-pos");
});

$("#start").click(function() {
    var msg = new SpeechSynthesisUtterance();

    msg.text = $("#message").val();
    msg.lang = selectedLang;
    msg.voice = voices[selectedVoice];
 
    console.log(msg);

    window.speechSynthesis.speak(msg);
});

// Hide Dropdown if there is only one voice
if ($("#voiceSelect option").length == 0) {
    $("#voiceSelect").hide();
}

function populateVoiceList()
{
  if (typeof speechSynthesis === 'undefined') {
    return;
  }
  
  for (let i = 0; i < voices.length; i++) {
    const 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);
    option.setAttribute('data-voice-uri', voices[i].voiceURI);
    option.setAttribute('data-pos', i);

    document.getElementById("voiceSelect").appendChild(option);
  }
}
.flex-container {
    display: flex;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<select id="voiceSelect"></select>
<div class="flex-container">
    <textarea id="message" value="test"></textarea>
    <button id="start">Start</button>
</div>

JSFiddle



from Javascript - How to get more voices for text to speech?

No comments:

Post a Comment