Javascript - 如何获得更多语音文本到语音?

问题描述 投票:0回答:3

我制作了这个小脚本,您可以在其中输入一些消息,它会读出它。

我通过使用 FireFox SpeechSynthesis API 解决了这个问题。

如何获得更多的声音和更多语言的支持?

注意:SO 中有一个“bug”。如果我编辑我的问题并编辑脚本并从那里测试它,那么 4 个声音是 加载中。如果我正常运行代码片段,那么就没有声音 正在加载,但是默认语音。

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

javascript jquery text-to-speech speech-synthesis
3个回答
2
投票

如何获得更多的声音和更多语言的支持?

目前还没有浏览器供应商支持加载自定义/更多语音。它似乎也不是新生规范的一部分,因为有一个未解决的问题询问如何添加更多声音

声音列表取决于用户代理/设备,因为这就是它的指定方式。用户代理使用设备操作系统提供的本机语音引擎或基于网络的语音引擎,每个引擎都与一组支持的语音一起工作。以下是 来自 chromium 问题的评论,内容是由于基于本机/网络的语音引擎中缺少功能,无法支持边界事件,作为 Web 语音 API 所依赖的平台的示例。

如果您想查看各种设备/浏览器可以使用哪些语音,可以访问 https://morganney.github.io/tts-react/?path=/story/tts-react--hook 并单击“加载”按钮以获取

<select>
支持的 HTML
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>


1
投票

我稍微修改了你的代码,并在这里有一个工作版本:https://jsfiddle.net/lharby/j36nbhy1/

首先我们设置合成变量和一个let来将声音初始化为一个空数组,我们可以稍后推送到

const synth = window.speechSynthesis;
let voices = [];

然后我们必须在

voices = synth.getVoices();
函数中传递
populateVoiceList
,因为对它的调用是异步进行的。

然后我更改了

for loop
,为
forEach
函数,如下所示:

voices.forEach((item, index) => {
    const option = document.createElement('option');
    option.textContent = `${item.name} (${item.lang})`;
    option.setAttribute('data-lang', item.lang);
    option.setAttribute('data-name', item.name);
    option.setAttribute('data-voice-uri', item.voiceURI);
    option.setAttribute('data-pos', index);
    document.getElementById("voiceSelect").appendChild(option);
});

我认为其余部分几乎相同,但如果您遇到问题,请告诉我。为了进行测试,我确实必须进行一些编辑。


0
投票

Banner

以前,我使用过浏览器语音合成,但它有很多问题。然后我制作了一些js库来解决所有TTS问题。它结合了浏览器语音合成和音频文件(可以通过 tts API 获取)作为语音源。我的图书馆还提供了正在朗读的突出显示文本。

Architecture

Feature Overview

有关详细信息,请访问我的 GitHub 存储库

© www.soinside.com 2019 - 2024. All rights reserved.