我制作了这个小脚本,您可以在其中输入一些消息,它会读出它。
我通过使用 FireFox SpeechSynthesis API 解决了这个问题。
如何获得更多声音并支持更多语言?
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>
最佳答案
How can I get more voices and support for more languages?
目前还没有浏览器 vendor 支持加载自定义/更多语音。它似乎也不是新生规范的一部分,因为有一个 open issue asking how to add more voices .
声音列表取决于用户代理/设备,因为它就是这样的 specified 。用户代理使用设备操作系统提供的 native 语音引擎或基于网络的语音引擎,每个引擎都与一组支持的语音一起工作。这是comment from a chromium issue about not being able to support boundary events由于基于 native /网络的语音引擎缺少功能,作为 Web 语音 API 所依赖的平台的示例。
如果您想查看各种设备/浏览器可以使用哪些语音,您可以访问https://morganney.github.io/tts-react/?path=/story/tts-react--hook然后点击“加载”按钮即可获取 HTML <select>
SpeechSynthesisVoice
的支持。
您还可以运行下面的代码片段来查看可用的声音:
let voices = []
const btn = document.getElementById('load')
const options = document.getElementById('voices')
const hasSynth = 'speechSynthesis' in window
if (hasSynth) {
voices = speechSynthesis.getVoices()
speechSynthesis.addEventListener('voiceschanged', () => {
voices = speechSynthesis.getVoices()
})
}
btn.addEventListener('click', () => {
const initOpt = document.createElement('option')
if (!voices.length && hasSynth) {
voices = speechSynthesis.getVoices()
}
initOpt.append(document.createTextNode('-- select voice --'))
options.append(initOpt)
voices.forEach(voice => {
const option = document.createElement('option')
option.value = voice.name
option.append(document.createTextNode(`${voice.lang} - ${voice.name}`))
options.append(option)
})
options.style.display = 'inline'
})
options.addEventListener('change', (evt) => {
if (hasSynth) {
const utterance = new SpeechSynthesisUtterance()
utterance.text = 'Testing the selected voice.'
utterance.voice = voices.find(voice => voice.name === evt.target.value)
speechSynthesis.speak(utterance)
}
})
#voices {
display: none;
}
<button id="load">click to load voices</button>
<select id="voices">
</select>
关于Javascript - 如何获得更多的文本语音转换声音?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/74101042/