语音合成技术:代码深度解析与 API 调用神奇之旅
在数字世界的广袤宇宙中,语音合成技术如同一位能说会道的向导,引领我们跨越人机交互的新纪元。今天,让我们穿梭于代码的丛林,探索语音合成(Speech Synthesis)的秘密,从基本概念到 API 的应用,逐一揭开这项迷人技术的面纱。
引言:语音的力量
在页面功能实现过程中,我们经常会遇到需要文字转语音的情况,这时候,我们可以考虑查询一下相关的官方文档,今天我们介绍一下 Web Speech API ,让大家了解了解基础的文字转语音方法。
深入API的世界:Web Speech API
为了让你更好地理解和实现语音合成,我们首先需要熟悉 Web Speech API,特别是其 SpeechSynthesis 接口。这一接口为开发者提供了强大的工具,可以让网页应用具备读出文本的能力。
基础代码示例
让我们从一个简单的示例开始,看看如何使用这个 API 来合成语音:
HTML 样式
下面提供了一个简单的 HTML 。其中,<select> 元素初始是空的,之后会通过 JavaScript 使用 <option> 填充。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width" />
<title>Speech synthesiser</title>
<link rel="stylesheet" href="style1.css" />
</head>
<body>
<h1>Speech synthesiser</h1>
<p>
在下面的输入中输入一些文字,然后按回车或“播放”按钮要听,请使用下拉菜单更改声音。
</p>
<form>
<label for="txt">Enter text</label>
<input id="txt" type="text" class="txt" />
<div>
<label for="rate">Rate</label
><input type="range" min="0.5" max="2" value="1" step="0.1" id="rate" />
<div class="rate-value">1</div>
<div class="clearfix"></div>
</div>
<select></select>
<div class="controls">
<button id="play" type="submit">Play</button>
</div>
</form>
<script src="script1.js"></script>
</body>
</html>
效果图如下:主要内容包括一个输入框(可以自行输入要转换为语音的内容),一个语速控制滑动按钮(可以通过拖动按钮,控制语音的语速),一个语言选择器(可以根据自己输入的内容切换选择不同的语种),和一个播放按钮(摁下按钮语音即可输出)。
JS 构造
首先,我们需要获得 Window.speechSynthesis 的引用。这是 API 的入口点 —— 它返回了 SpeechSynthesis 的一个实例,这是 web 语音合成的控制接口。
const synth = window.speechSynthesis;
const inputForm = document.querySelector("form");
const inputTxt = document.querySelector(".txt");
const voiceSelect = document.querySelector("select");
const rate = document.querySelector("#rate");
const rateValue = document.querySelector(".rate-value");
let voices = [];
function populateVoiceList() {
voices = synth.getVoices().sort(function (a, b) {
const aname = a.name.toUpperCase();
const bname = b.name.toUpperCase();
if (aname < bname) {
return -1;
} else if (aname == bname) {
return 0;
} else {
return +1;
}
});
const selectedIndex =
voiceSelect.selectedIndex < 0 ? 0 : voiceSelect.selectedIndex;
voiceSelect.innerHTML = "";
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);
voiceSelect.appendChild(option);
}
voiceSelect.selectedIndex = selectedIndex;
}
populateVoiceList();
if (speechSynthesis.onvoiceschanged !== undefined) {
speechSynthesis.onvoiceschanged = populateVoiceList;
}
function speak() {
if (synth.speaking) {
console.error("speechSynthesis.speaking");
return;
}
if (inputTxt.value !== "") {
const utterThis = new SpeechSynthesisUtterance(inputTxt.value);
utterThis.onend = function (event) {
console.log("SpeechSynthesisUtterance.onend");
};
utterThis.onerror = function (event) {
console.error("SpeechSynthesisUtterance.onerror");
};
const selectedOption = voiceSelect.selectedOptions[0].getAttribute("data-name");
for (let i = 0; i < voices.length; i++) {
if (voices[i].name === selectedOption) {
utterThis.voice = voices[i];
break;
}
}
utterThis.rate = rate.value;
synth.speak(utterThis);
}
}
inputForm.onsubmit = function (event) {
event.preventDefault();
speak();
inputTxt.blur();
};
rate.onchange = function () {
rateValue.textContent = rate.value;
};
voiceSelect.onchange = function () {
speak();
};
Web Speech API
SpeechSynthesis 接口
其中 SpeechSynthesis 接口是语音服务的控制接口;它可以用于获取设备上关于可用的合成声音的信息,开始、暂停语音,或除此之外的其他命令。
属性
-
paused: 当SpeechSynthesis处于暂停状态时,Boolean值返回true。 -
pending: 当语音播放队列到目前为止保持没有说完的语音时,Boolean值返回true。 -
speaking: 当语音谈话正在进行的时候,即使SpeechSynthesis处于暂停状态,Boolean返回true。
事件操作
onvoiceschanged: 当由SpeechSynthesis.getVoices()方法返回的SpeechSynthesisVoice列表改变时触发。
方法
-
cancel(): 移除所有语音谈话队列中的谈话。 -
getVoices(): 返回当前设备所有可用声音的SpeechSynthesisVoice列表。 -
pause(): 把SpeechSynthesis对象置为暂停状态。 -
resume(): 把SpeechSynthesis对象置为一个非暂停状态:如果已经暂停了则继续。 -
speak(): 添加一个utterance到语音谈话队列;它将会在其他语音谈话播放完之后播放。
以上属性和方法,均可根据自己的需求添加到代码中调试运行,在这段代码中,我们创建了一个 SpeechSynthesisUtterance 对象,并设置了其属性和事件处理函数,然后通过 speechSynthesis.speak() 方法让浏览器朗读指定的文字。
SpeechSynthesisVoice 接口
SpeechSynthesisVoice 接口表示系统支持的语音。每个 SpeechSynthesisVoice 都有自己的相对语音服务,包括语言、名称和 URI 信息。
实例属性
-
default: 布尔值,指示该语音是否为当前应用程序语言(true)的默认语音(false)。 -
lang: 返回 BCP 47 语言标签,指示语音的语言。 -
localService: 指示声音是由本地语音合成服务(true)还是由远程语音合成服务提供(false)。 -
name: 返回一个代表语音的可读名称。 -
voiceURI: 返回此语音的URI类型和语音合成服务的位置。
代码分析
这段代码实现了一个基本的文本转语音(TTS)功能,允许用户从一个输入框中输入文本,选择不同的语音和速率,然后播放所选文本的语音合成。以下是代码的核心要点和功能分析:
初始化和获取语音列表
-
window.speechSynthesis:window.speechSynthesis是 Web Speech API 的一部分,提供了语音合成功能。
-
populateVoiceList函数:-
用于获取并填充语音选择下拉菜单。
-
使用
synth.getVoices()获取当前可用的所有语音。 -
将语音按照名称排序,并创建相应的
option元素添加到下拉菜单中。 -
为每个
option设置了data-lang和data-name属性,用于存储语音的语言和名称。
-
-
事件监听器:
- 如果浏览器支持
speechSynthesis.onvoiceschanged事件,代码将注册populateVoiceList函数为事件处理器,确保语音列表发生变化时能够更新下拉菜单。
- 如果浏览器支持
文本转语音功能
-
speak函数:-
检查
speechSynthesis是否正在说话,如果是,则不执行新的语音合成请求。 -
创建一个新的
SpeechSynthesisUtterance对象,用于封装待合成的文本。 -
为
SpeechSynthesisUtterance对象注册onend和onerror事件处理器,以便在语音合成结束或出现错误时执行相应动作。 -
根据用户在下拉菜单中的选择,设置
SpeechSynthesisUtterance对象的voice属性。 -
设置语音合成的速率,这将影响语音的快慢。
-
使用
synth.speak()方法开始语音合成。
-
用户交互
-
表单提交事件:
- 监听表单的
submit事件,阻止默认的表单提交行为,调用speak函数,并使输入框失去焦点。
- 监听表单的
-
速率变化事件:
- 监听速率输入框的
change事件,更新显示速率值的元素内容。
- 监听速率输入框的
-
语音选择变化事件:
- 监听语音选择下拉菜单的
change事件,调用speak函数,使用户在选择不同语音时立即听到语音合成。
- 监听语音选择下拉菜单的
总结
这段代码通过合理地利用 Web Speech API 的功能,代码实现了与用户交互的文本转语音功能,同时处理了事件监听、语音列表更新和语音合成控制。
结语:技术与未来的对话
通过今天的探索,我们不仅了解了如何使用 Web Speech API 实现基本的语音合成,还学习了如何根据用户的选择动态生成语音。语音合成技术的进步,正推动着人机交互方式的革命,使得我们的数字生活更加多彩。
但使用 Web Speech API 完成文字转语音的功能实现,也有明显的缺点,比如这使用该方法时,无法根据上下文内容正确地识别字段中的多音字。为解决这个问题,我们还可以调用相关的 AI 模型,就可以更加智能地完成文字转语音的功能,具体实现方法本人还在学习中,成功实现后会更新文章。