为什么我不能在 SpeechSynthesisUtterance() 中选择女性 "Microsoft Zira" 语音?

Why Can't I Choose Female "Microsoft Zira" Voice in SpeechSynthesisUtterance()?

我关注的 HTML 页面可以正确朗读文本,但不是女性语音 Microsoft Zira Desktop - English (United States)问题:我可能在这里遗漏了什么,我们怎样才能让它用女性的声音说话?

备注:我在 MS EdgeGoogle Chrome 中多次尝试过此 html,刷新和不刷新页面,但它一直与同样的男声。它似乎忽略了下面 JavaScript 中的 msg.voice 值。我正在使用 Windows 10 - 这可能无关紧要。

<!DOCTYPE html>
<html>
<head>
<script>
    function myFunction() {
  var msg = new SpeechSynthesisUtterance();
      msg.voice = speechSynthesis.getVoices().filter(function(voice) {
    return voice.name == "Microsoft Zira Desktop - English (United States)"})[0];
    msg.text = document.getElementById("testDiv").textContent;
    window.speechSynthesis.speak(msg);
}
</script>
</head>
<body>

<h2>JavaScript in Head</h2>

<div id="testDiv">SQL Managed Instance gives you an instance of SQL Server but removes much of the <b>overhead</b> of managing a <u>virtual machine</u>. Most of the features available in SQL Server are available in SQL Managed Instance. This option is ideal for customers who want to use instance-scoped features and want to move to Azure without rearchitecting their applications.</div>

<button type="button" onclick="myFunction()">Try it</button>

</body>
</html>

更新

根据用户 @Frazer 的建议,我 运行 speechSynthesis.getVoices() 在我的 google chrome 控制台中得到了以下结果 - 其中确实包含 Microsoft Zira .... 声音:

观察:

正在关注 this advice, I moved the the <script> block to end of the body block (just before </body>) but still the same male voice. HOWEVER, when I replaced the voice from Microsoft Zira Desktop - English (United States) to Google UK English Female, the following happens: On the first click of Try it button, the speaker is still the default male, but on every subsequent clicks on this button, I correctly get the Google UK English Female voice. Note: The Microsoft Zira Desktop - English (United States) does nothing in the above scenario. This leads me to believe that this technology still is experiential - as mentioned here


为什么它适用于某些浏览器?

我在这里有一个类似问题的答案,,但我认为你的情况完全不同,值得一个新的答案。

首先,为什么它有时会起作用? 因为 "Microsoft Zira Desktop - English (United States)" 是通过 API 调用从 Web 检索的,并且此数据不可用到下一行执行时。 基本上,你应该等到 onvoiceschanged 被调用,然后再实际调用 getVoices() 来获取声音。

引用文档...

With Chrome however, you have to wait for the event to fire before populating the list, hence the bottom if statement seen below. (Source: MDN WebDocs: SpeechSynthesis.onvoiceschanged) (Emphasis mine.)

如果列表未填充,并且您没有可用的女性语言,则默认使用男性语言。

因为构造函数 `getVoices()` 进行 API 调用,将其视为异步

像这样尝试运行你的代码...

var msg = new SpeechSynthesisUtterance();
var voices = window.speechSynthesis.getVoices();

window.speechSynthesis.onvoiceschanged = function() {
    voices = window.speechSynthesis.getVoices();
};

function myFunction() {
    console.log(voices);
      msg.voice = voices.filter(function(voice) {
    return voice.name == "Microsoft Zira - English (United States)"})[0];
    console.log(msg.voice);
    msg.text = document.getElementById("testDiv").textContent;
    window.speechSynthesis.speak(msg);
}

P.S。这是我自己的编码示例,说明我如何处理文本到音频上的语音加载 reader:GreenGluon CMS: text-audio.js Also here: PronounceThat.com pronounce-that.js

将 'disabled' 属性添加到您的按钮,然后在带有 Zira 或 Chrome 语音的 /body 标签之前尝试此操作。

speechSynthesis.onvoiceschanged = () => {
  voices = speechSynthesis.getVoices()
  if (voices.length) document.querySelector("button").disabled = false
}
let voices = speechSynthesis.getVoices()

const  myFunction = () => {
  const msg = new SpeechSynthesisUtterance();
  msg.voice = voices.filter(voice => {
    return voice.name === "Microsoft Zira Desktop - English (United States)"
  })[0];
  msg.text = document.getElementById("testDiv").textContent;
  speechSynthesis.speak(msg);
}