今天分享的是浏览器的语音合成功能,浏览器的语音播放并不复杂,主要对象有两个,一个是 speechSynthesis,一个是 SpeechSynthesisUtterancespeechSynthesis 是一个全局唯一的对象,它无法通过构造函数来生成,用来表示语音播放的状态,例如语音播放、语音暂停等,而SpeechSynthesisUtterance 是用来表示语音播放的属性,包括语音内容、语音音调、语音音量等,可以通过 new 来生成;在介绍两个对象的属性和用法之前,可以先看一下它们的兼容性如何;
在这里插入图片描述

1、speechSynthesis
  • 属性
    • pending:表示当前播放列表是否有未播完的语音,即播放列表长度是否大于 2;
    • speaking:表示当前是否有语音正在进行播放,无论是播放还是暂停的状态, 也就是播放列表是否为空;
    • paused: 表示当前是否是暂停状态;
  • 事件
    • onvoiceschanged:监听事件,当 SpeechSynthesisVoice 列表发生改变的时候触发,通常也是在这个事件中通过 SpeechSynthesis.getVoices 来获取到浏览器支持的语音配置对象;
  • 方法
    • cancel:移除所有语音队列中的语音,相当于清空的功能;
    • pause:将当前语音对象置为暂停状态,这里需要注意一下,当调用这个方法时,整个浏览器的语音播放会处于一个暂停状态,如果没有调用 cancel 或 resume 方法,则不会继续播放,包括其他标签页添加进语音播放列表的语音合成对象
    • resume:将当前语音对象置为非暂停状态,如果是暂停状态,则继续播放剩下的语音;
    • speak:添加一个语音对象到语音播放列表,当前列表为空时,则会马上播放,如果当前播放列表存在其他语音对象,则会等到其他语音对象播放完毕之后播放;
    • getVoices: 返回当前设备所有可用声音的列表;
      在这里插入图片描述
2、 SpeechSynthesisUtterance
  • 属性

    • lang:语音播放的语言;
    • pitch:语音播放的音调,最大值为 2;
    • rate:语音播放的速率;
    • text:语音播放的文字内容;
    • voice:语音播放的声音,通过 SpeechSynthesis.getVoices 获取的列表项来设置,需要注意一个点,getVoices 返回所有可用的列表,但是也有一个限制,那就是当前设备是否支持设置的声音,也就是图中的 localService 字段值,如果不支持,设置之后播放是没有声音的
      在这里插入图片描述
    • volume:语音播放的音量,最大值为 1;
  • 事件

    • boundary: 在播放语音时遇到一个单词或句子的结束,这个事件就会被触发;
    • start:当浏览器开始播放合成语音时触发;
    • end:当浏览器播放合成语音结束时触发;
    • error:当语音播放发生中断,无法成功播放时触发,SpeechSynthesis.cancel 会触发;
    • pause:当暂停播放语音时触发;
    • resume:当暂停语音之后选择继续播放时触发;
      在这里插入图片描述
3、实战案例
<!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>
		<p id="text">这段文字将通过浏览器的语音合成API来播放</p>
		<button id="playBtn">播放</button>
		<button id="pauseBtn">暂停</button>
		<button id="resumeBtn">继续</button>
		<button id="cancelBtn">取消</button>
		<button id="statusBtn">获取状态</button>
		<script>
			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");
			let ssu = null;
			playBtn.addEventListener("click", () => {
				// 创建语音
				if (!ssu) {
					ssu = new SpeechSynthesisUtterance(text.innerText);
					ssu.addEventListener("start", () => {
						console.log("开始播放语音");
					});
					ssu.addEventListener("end", () => {
						console.log("播放语音结束");
					});
					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);
					});
				}
				console.log(ssu);
				// 播放语音
				window.speechSynthesis.speak(ssu);
			});
			pauseBtn.addEventListener("click", () => {
				window.speechSynthesis.pause();
			});
			resumeBtn.addEventListener("click", () => {
				window.speechSynthesis.resume();
			});
			cancelBtn.addEventListener("click", () => {
				window.speechSynthesis.cancel();
			});
			statusBtn.addEventListener("click", () => {
				const { pending, speaking, paused } = window.speechSynthesis;
				console.log(`当前播放列表${pending ? "有" : "没有"}未播完的语音`);
				console.log(`当前播放列表${speaking ? "存在" : "不存在"}语音`);
				console.log(`当前${paused ? "是" : "不是"}暂停播放状态`);
			});
		</script>
	</body>
</html>
Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐