【JavaScript】实现文本转语音功能

效果预览:https://sevlt.github.io/text-to-speech/index.html

Html 代码:

<!DOCTYPE html>
<html lang="zh-CN">
	<head>
		<meta charset="UTF-8" />
		<meta name="viewport" content="width=device-width, initial-scale=1.0" />
		<link
			rel="stylesheet"
			href="https://cdn.staticfile.org/twitter-bootstrap/4.3.1/css/bootstrap.min.css"
		/>
		<title>文本转语音</title>
		<style>
			body {
				background: #141414;
			}
		</style>
	</head>
	<body>
		<div class="text-white">
			<div class="container text-center">
				<img src="./img/speech.png" class="mb-3" />
				<div class="row">
					<!-- 居中对齐 -->
					<div class="col-md-5 mx-auto">
						<form class="mb-5">
							<!-- 文本输入框 -->
							<div class="form-froup">
								<textarea
									id="text-input"
									class="form-control mb-2"
									placeholder="请输入文本内容..."
								></textarea>
							</div>
							<!-- 音速 -->
							<div class="form-froup">
								<label for="rate">音速</label>
								<div id="rate-value" class="badge badge-primary float-right">1</div>
								<input
									type="range"
									id="rate"
									class="custom-range"
									min="0.5"
									max="2"
									value="1"
									step="0.1"
								/>
							</div>
							<!-- 音调 -->
							<div class="form-froup">
								<label for="pitch">音调</label>
								<div id="pitch-value" class="badge badge-primary float-right">
									1
								</div>
								<input
									type="range"
									id="pitch"
									class="custom-range mb-2"
									min="0"
									max="2"
									value="1"
									step="0.1"
								/>
							</div>
							<!-- 选择发音语言 -->
							<div class="form-froup">
								<select id="voice-select" class="form-control mb-5"></select>
							</div>
							<!-- 视听按钮 -->
							<div class="form-froup">
								<button class="btn btn-light btn-block mb-3">试听</button>
								<p class="text-secondary">
									注意:此应用使用的是Web Speech API,为确保正常运行,请使用最新版
									Chrome 浏览器。
								</p>
							</div>
						</form>
					</div>
				</div>
			</div>
		</div>
		<script src="https://cdn.staticfile.org/jquery/3.2.1/jquery.min.js"></script>
		<script src="https://cdn.staticfile.org/popper.js/1.15.0/umd/popper.min.js"></script>
		<script src="https://cdn.staticfile.org/twitter-bootstrap/4.3.1/js/bootstrap.min.js"></script>
		<script src="./main.js"></script>
	</body>
</html>

JavaScript 代码:

// 初始化 speechSynthesis API
const synth = window.speechSynthesis
// 获取 DOM 节点
const body = document.querySelector('body')
const textForm = document.querySelector('form')
const textInput = document.querySelector('#text-input')
const voiceSelect = document.querySelector('#voice-select')
const rate = document.querySelector('#rate')
const rateValue = document.querySelector('#rate-value')
const pitch = document.querySelector('#pitch')
const pitchValue = document.querySelector('#pitch-value')

let voices = []

function getVoiceList() {
	voices = synth.getVoices()
	// 循环 voices 数组,并逐一创建一个 option
	voices.forEach((voice) => {
		const option = document.createElement('option')
		option.textContent = voice.name
		// 设置 option 属性
		option.setAttribute('data-lang', voice.lang)
		option.setAttribute('data-name', voice.name)
		voiceSelect.appendChild(option)
	})
}
// synth.getVoices() 为异步执行
// synth.getVoices() 方法将在 synth.onvoiceschanged 触发时运行
// 因此须有如下语句,否则 synth.getVoices() 返回空数组
getVoiceList()
if (synth.onvoiceschanged !== undefined) {
	synth.onvoiceschanged = getVoiceList
}
// 发音方法
function speakIt() {
	// 若正在发音则直接返回
	if (synth.speaking) {
		return
	}
	if (textInput.value != '') {
		// 添加 gif 动画
		body.style.background = '#141414 url(./img/wave.gif) repeat'
		body.style.backgroundPositionY = '-50px'
		// 获取发音文本
		const speakText = new SpeechSynthesisUtterance(textInput.value)
		// 发音结束后触发的方法
		speakText.onend = (e) => {
			body.style.background = '#141414'
		}
		// 发音出错是触发的方法
		speakText.onerror = (e) => {
			alert('出现错误,请重试。')
		}
		// 获取 select 框当前选中的语言项并获取其 data-name 属性值
		const selectVoice = voiceSelect.selectedOptions[0].getAttribute('data-name')
		// 遍历 voices 数组,在 voice.name 中找到与上方 select 中选择的语言一致的选项
		// 并把它赋值给 speakText.voice
		voices.forEach((voice) => {
			if (voice.name === selectVoice) {
				speakText.voice = voice
			}
		})
        // 设置发音速率
        speakText.rate = rate.value
        // 设置发音音调
		speakText.pitch = pitch.value
        // 开始发音
		synth.speak(speakText)
	}
}
// 提交表单
textForm.addEventListener('submit', (e) => {
	e.preventDefault()
	speakIt()
})
// 改变速率右侧的数值
rate.addEventListener('change', (e) => {
	rateValue.textContent = rate.value
})
// 改变音调右侧的数值
pitch.addEventListener('change', (e) => {
	pitchValue.textContent = pitch.value
})

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章