【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
})

 

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