SpeechSynthesis是HTML5的一个新特性,基于SpeechSynthesis可以实现在客户浏览器端进行动态文本的语音合成播放。在HTML5中和Web Speech相关的API实际上有两类,一类是“语音识别(Speech Recognition)”,另外一个就是“语音合成(Speech Synthesis)”,这两个名词听上去很高大上,实际上指的分别是“语音转文字”,和“文字变语音”。而本文要介绍的就是这里的“语音合成-文字变语音”。为什么称为“合成”呢?比方说你Siri发音“你好,世界!” 实际上是把“你”、“好”、“世”、“界”这4个字的读音给合并在一起,因此,称为“语音合成”。
SpeechSyntehesisUtteranc这个类主要用于控制合成声音的属性配置,比如主要内容,语音模板,语速等等,通过这个核心类控制。它的属性信息如下:
序号 | 参数 | 解释 |
---|---|---|
1 | text | 要合成的文字内容,字符串 |
2 | lang | 使用的语言,字符串, 例如:"zh-cn" |
3 | voiceURI | 指定希望使用的声音和服务,字符串。 |
4 | volume | 声音的音量,区间范围是0到1,默认是1 |
5 | rate | 语速,数值,默认值是1,范围是0.1到10,表示语速的倍数,例如2表示正常语速的两倍。 |
6 | pitch | 表示说话的音高,数值,范围从0(最小)到2(最大)。默认值为1 |
核心方法如下表所示:
序号 | 方法名 | 说明 |
---|---|---|
1 | onstart | 语音合成开始时候的回调。 |
2 | onpause | 语音合成暂停时候的回调 |
3 | onresume | 语音合成重新开始时候的回调 |
4 | onend | 语音合成结束时候的回调 |
5 | onmark | Fired when the spoken utterance reaches a named SSML "mark" tag. |
speechSynthesis是实际调用SpeechSynthesisUtterance对象进行合成播报的。他的属性和方法如下两个表格描述。
序号 | 名称 | 描述 |
---|---|---|
1 | paused | 当SpeechSynthesis 处于暂停状态时, Boolean (en-US) 值返回 true |
2 | pending | 当语音播放队列到目前为止保持没有说完的语音时, Boolean (en-US) 值返回 true 。 |
3 | speaking | 当语音谈话正在进行的时候,即使SpeechSynthesis处于暂停状态, Boolean (en-US) 返回 true 。二、SpeechSynthesi文本实例合成 |
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>SpeechSynthesisUtterance</title>
</head>
<body>
<div style="text-align: center;margin-top:50px">
<textarea style="height: 100px; width:300px;" id="text">这段文字将通过浏览器的语音合成API来播放</textarea>
<br/>
<select name="voice" id="voices">
<option value="">选择语音</option>
</select>
<label>速度:</label>
<input name="rate" type="range" min="0" max="3" value="1" step="0.1">
<label>音高:</label>
<input name="pitch" type="range" min="0" max="2" value="1" step="0.1">
<div style="margin-top:30px">
<button id="playBtn">播放</button>
<button id="pauseBtn">暂停</button>
<button id="resumeBtn">继续</button>
<button id="cancelBtn">取消</button>
<button id="statusBtn">获取状态</button>
</div>
</div>
</body>
<script>
const speech = window.speechSynthesis
const text = document.getElementById("text");
const playBtn = document.getElementById("playBtn");
const pauseBtn = document.getElementById("pauseBtn");
const resumeBtn = document.getElementById("resumeBtn");
const cancelBtn = document.getElementById("cancelBtn");
const statusBtn = document.getElementById("statusBtn");
const voicesDropdown = document.querySelector('[name="voice"]')
const rate = document.querySelector('[name="rate"]')
const pitch = document.querySelector('[name="pitch"]')
let ssu = null;
playBtn.addEventListener("click", () => {
const { pending, speaking, paused } = speech
if (pending) { // 判断当前播放状态
console.log(`当前播放列表${pending ? "有" : "没有"}未播完的语音`);
return false;
}
// 创建语音
if (!ssu) {
ssu = new SpeechSynthesisUtterance();
ssu.text = text.value;
ssu.lang = voicesDropdown.selectedOptions[0].value // 设置播放语言(默认zh-CN)
ssu.pitch = pitch.value // 获取并设置话语的音调(0-2 默认1,值越大越尖锐,越低越低沉)
ssu.rate = rate.value // 获取并设置说话的速度(0.1-10 默认1,值越大语速越快,越小语速越慢)
ssu.volume = 100 // 获取并设置说话的音量
let count = 0
console.log(ssu);
speech.speak(ssu);
ssu.addEventListener("start", () => {
console.log("开始播放语音");
});
ssu.addEventListener("end", () => {
console.log("播放语音结束");
count ++
setTimeout(function() { // 增加控制播放次数
count < 3 && speech.speak(ssu);
}, 1000);
});
ssu.addEventListener("boundary", (e) => {
// console.log("当前遇到单词或句子", e.name);
});
ssu.addEventListener("pause", () => {
console.log("暂停播放语音");
});
ssu.addEventListener("resume", () => {
console.log("继续播放语音");
});
ssu.addEventListener("error", (e) => {
console.log("发生错误", e.error);
});
}
});
pauseBtn.addEventListener("click", () => {
speech.pause();
});
resumeBtn.addEventListener("click", () => {
speech.resume();
});
cancelBtn.addEventListener("click", () => {
speech.cancel();
});
statusBtn.addEventListener("click", () => {
const { pending, speaking, paused } = speech
console.log(pending, speaking, paused);
console.log(`当前播放列表${pending ? "有" : "没有"}未播完的语音`);
console.log(`当前播放列表${speaking ? "存在" : "不存在"}语音`);
console.log(`当前${paused ? "是" : "不是"}暂停播放状态`);
});
let voices = []
speech.addEventListener('voiceschanged',getSupportVoices)
function getSupportVoices() {
voices = speech.getVoices()
voices.forEach(e => {
const option = document.createElement('option')
option.value = e.lang
option.text = e.name
if (e.lang == 'zh-CN') {
option.selected = true;
}
voicesDropdown.appendChild(option)
})
}
</script>
</html>
本文为冯奎原创文章,转载无需和我联系,但请注明来自冯奎博客fengkui.net
最新评论