使用原生浏览器实现一个语音合成播放功能

4664次阅读 269人点赞 作者: WuBin 发布时间: 2025-01-10 08:08:05
扫码到手机查看

完整代码

SpeechSynthesis 功能的 兼容性:https://caniuse.com/?search=SpeechSynthesis

在线体验地址:http://code.wubin.work/code/js/sound-read/


<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8" />
	<meta name="viewport" content="width=device-width, initial-scale=1.0" />
	<title>SpeechSynthesis</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>
点赞 支持一下 觉得不错?客官您就稍微鼓励一下吧!
关键词:SpeechSynthesis,语音播放
推荐阅读
  • uniapp实现被浏览器唤起的功能

    当用户打开h5链接时候,点击打开app若用户在已经安装过app的情况下直接打开app,若未安装过跳到应用市场下载安装这个功能在实现上主要分为两种场景,从普通浏览器唤醒以及从微信唤醒。

    10356次阅读 684人点赞 发布时间: 2022-12-14 16:34:53 立即查看
  • Vue

    盘点Vue2和Vue3的10种组件通信方式

    Vue中组件通信方式有很多,其中Vue2和Vue3实现起来也会有很多差异;本文将通过选项式API组合式API以及setup三种不同实现方式全面介绍Vue2和Vue3的组件通信方式。

    4859次阅读 365人点赞 发布时间: 2022-08-19 09:40:16 立即查看
  • JS

    几个高级前端常用的API

    推荐4个前端开发中常用的高端API,分别是MutationObserver、IntersectionObserver、getComputedstyle、getBoundingClientRect、requ...

    14957次阅读 987人点赞 发布时间: 2021-11-11 09:39:54 立即查看
  • PHP

    【正则】一些常用的正则表达式总结

    在日常开发中,正则表达式是非常有用的,正则表达式在每个语言中都是可以使用的,他就跟JSON一样,是通用的。了解一些常用的正则表达式,能大大提高你的工作效率。

    14220次阅读 548人点赞 发布时间: 2021-10-09 15:58:58 立即查看
  • 【中文】免费可商用字体下载与考证

    65款免费、可商用、无任何限制中文字体打包下载,这些字体都是经过长期验证,经得住市场考验的,让您规避被无良厂商起诉的风险。

    13040次阅读 1055人点赞 发布时间: 2021-07-05 15:28:45 立即查看
  • Vue

    Vue3开发一个v-loading的自定义指令

    在vue3中实现一个自定义的指令,有助于我们简化开发,简化复用,通过一个指令的调用即可实现一些可高度复用的交互。

    17209次阅读 1382人点赞 发布时间: 2021-07-02 15:58:35 立即查看
  • JS

    关于手机上滚动穿透问题的解决

    当页面出现浮层的时候,滑动浮层的内容,正常情况下预期应该是浮层下边的内容不会滚动;然而事实并非如此。在PC上使用css即可解决,但是在手机端,情况就变的比较复杂,就需要禁止触摸事件才可以。

    15655次阅读 1269人点赞 发布时间: 2021-05-31 09:25:50 立即查看
  • Vue

    Vue+html2canvas截图空白的问题

    在使用vue做信网单页专题时,有海报生成的功能,这里推荐2个插件:一个是html2canvas,构造好DOM然后转canvas进行截图;另外使用vue-canvas-poster(这个截止到2021年3月...

    30981次阅读 2437人点赞 发布时间: 2021-03-02 09:04:51 立即查看
  • Vue

    vue-router4过度动画无效解决方案

    在初次使用vue3+vue-router4时候,先后遇到了过度动画transition进入和退出分别无效的情况,搜遍百度没没找到合适解决方法,包括vue-route4有一些API都进行了变化,以前的一些操...

    26813次阅读 2062人点赞 发布时间: 2021-02-23 13:37:20 立即查看
交流 收藏 目录