You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Edge浏览器网页语音合成可用语音筛选及代码整合咨询

解答:Edge浏览器语音合成的无效语音过滤与代码整合

问题1:为什么那段代码能过滤掉6个无效语音?

这其实和speechSynthesis.getVoices()异步加载特性以及Edge浏览器的语音资源加载机制直接相关:

  • 当页面刚加载时直接调用synth.getVoices(),Edge返回的列表里会包含一些未完全初始化的“占位语音”——这些是系统注册但受地理限制、未完成下载或权限不足的资源,虽然能显示在下拉框里,但实际无法正常使用。
  • speechSynthesis.onvoiceschanged事件是在语音合成API完成所有可用语音的加载、验证(包括地理权限检查)后才会触发的。此时调用this.getVoices(),返回的是经过浏览器过滤后的真正可用的语音列表,那些无效的占位项会被自动剔除,所以你只能看到2个可用语音。

问题2:如何将该功能整合到现有网页中?

你需要把语音列表的填充逻辑绑定到onvoiceschanged事件上,替代原来的body onload(因为onload触发时语音资源可能还没完成验证)。具体修改步骤如下:

  1. 移除body标签上的onload="populateVoiceList()"属性,避免过早调用未准备好的语音列表。
  2. 在脚本中添加onvoiceschanged事件监听,触发时调用populateVoiceList更新下拉框。
  3. 为了兼容首次加载时事件可能已经触发的情况,在脚本最后主动调用一次populateVoiceList作为兜底。

修改后的完整代码如下:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="viewport" content="width=device-width">
<title>Speech synthesiser</title>
<script>
var synth = window.speechSynthesis;
var voiceSelect = document.getElementById("voicesAvailable");

function populateVoiceList() {
  voiceSelect.innerHTML = '';
  const voices = synth.getVoices();
  // 遍历可用语音生成下拉选项
  voices.forEach((voice, index) => {
    var option = document.createElement('option');
    option.textContent = `${voice.name} (${voice.lang})`;
    // 给选项绑定语音索引,方便后续调用时快速获取语音对象
    option.value = index;
    voiceSelect.appendChild(option);
  });
  // 无可用语音时添加提示项
  if (voices.length === 0) {
    var option = document.createElement('option');
    option.textContent = 'No available voices';
    voiceSelect.appendChild(option);
  }
}

// 绑定语音加载完成事件,确保只显示可用语音
synth.onvoiceschanged = populateVoiceList;

// 兜底调用:如果事件已提前触发,主动刷新列表
populateVoiceList();
</script>
</head>
<body>
<h1>speech test 1</h1>
<form id="myForm">
<select id="voicesAvailable">
<option>Loading voices...</option>
</select>
</form>
</body>
</html>

额外优化说明

  • 给每个下拉选项添加了value属性存储语音索引,方便后续实现语音播放功能时直接通过索引获取对应语音对象。
  • 增加了无可用语音时的提示逻辑,提升用户体验。
  • forEach替代传统for循环,代码更简洁易读。

内容的提问来源于stack exchange,提问作者dan

火山引擎 最新活动