還記得幾天前我們有將語音專程文字
今天我們要將文字轉成語音
使用的是Web Speech API
的SpeechSynthesisUtterance
和speechSynthesis
SpeechSynthesisUtterance
代表一個發音的需求,包含發音的內容和如何辨識的方法,例如text
、rate
、pitch
、lang
等
.lang
:設定或取得發音的語言。.pitch
:設定或取得發音的音調。.rate
:設定或取得發音的速度。.text
:設定或取得發音的文字內容。.voice
:設定或取得發音的聲音。.volume
:設定或取得發音的音量。SpeechSynthesis
是用來控制發音服務,可以取得合成聲音的資訊,並可以控制其發音的狀態
可以想像SpeechSynthesis
有一個utterance queue
來放置要被讀的資料
先了解他的屬性
SpeechSynthesis.paused
:如果回傳true
,表示現在是暫停狀態SpeechSynthesis.pending
:如果回傳true
,表示還有未讀完的語句在等著被讀SpeechSynthesis.speaking
:如果回傳true
,表示有發音正在被讀,即使是在暫停的狀態下.speak
:加一個發音到utterance queue
,他將在上一個發音讀完時接著讀.cancal
:清空utterance queue
.pasue
:進入暫停狀態(暫停發音).resume
:進入非暫停狀態(接著發音)首先我們要建構一個SpeechSynthesisUtterance
物件
並且需要一個陣列來存放我們的資訊
const msg = new SpeechSynthesisUtterance();
//建構一個SpeechSynthesisUtterance物件
let voices = [];
//存放發音的相關資訊
msg.text = document.querySelector('[name="text"]').value;
//將使用者輸入的內容存到msg內
function populateVoice() {
console.log("Hey!")
}
speechSynthesis.addEventListener('voiceschanged', populateVoice);
speechSynthesis.onviceschanged
事件
要特別注意的是voiceschanged
在一開始跟伺服器端被選擇(例如google提供的)或者在客戶端被安裝/解除安裝時,會執行一次
之後,這個事件會因為.getVoices()
而觸發
當觸發的時候我們就要更新可以選擇的voice list
並innerHTML
function populateVoice() {
voices = this.getVoices();
voicesDropdown.innerHTML = voices
.map(voice => `<option value="${voice.name}">${voice.name} (${voice.lang})</option>`)
.join()
}
接著我們要將選定的voice放到msg內
用.find()
去找到對應的voice
這裡有一個有趣的地方是this.value
this
指向的是<select>
而他的value
是存在子層的<option>
這個跟和是一組的有關
接著做點擊不同按鈕時讓他發聲
首先我們先使用.speak()
讓我們在點擊speak button時可以發聲
而參數則是我們設定已久的msg
這時妳會發現連點的時候並不會直接發聲
而是等上一句念完
才會處理第二次點擊的聲音
(本身的特性)
這時候我們只要在.speak()
之前加上.cancel()
把之前的話都清空即可每次連點都直接發聲
最後再加上一點微調
這個toggle()
就可以廣泛被利用
用參數startOver
來存布林值true
(預設)會播放聲音
這樣的話
就可以在「需要重新播放」時,使用toggle()
(上方切換voice也可以使用)
而「需要中止播放」,只要將startOver
設定為false
即可只中止不播放
const speakButton = document.querySelector('#speak');
const stopButton = document.querySelector('#stop');
function toggle(startOver = true) {
speechSynthesis.cancel();
if (startOver) {
speechSynthesis.speak(msg);
}
}
speakButton.addEventListener('click', toggle);
stopButton.addEventListener('click', toggle.bind(null, false));
由於在addEventListener
內不能加參數
所以我們使用.bind()
method.bind()
的第一個參數是指定target function的this,也就是.toggle()
的作用對象
第二個參數開始則是我們target function的參數
因為.toggle()
只有一個參數
所以.bind()
第一個參數傳null
,第二個參數傳false
有了上面的基礎
使用.pause()
來暫停和.resume()
來恢復播放也是輕輕鬆鬆
const pauseButton = document.querySelector('#pause');
const resumeButton = document.querySelector('#resume');
function pauseMessage() {
speechSynthesis.pause();
}
function resumeMessage() {
speechSynthesis.resume();
}
pauseButton.addEventListener('click', pauseMessage);
resumeButton.addEventListener('click', resumeMessage);
最後我們可以來調整說話的速度、音調及內容
只要有調整到以上三點的
都會調整他們存儲在msg
內的值
並馬上調用.toggle()
const options = document.querySelectorAll('[type="range"], [name="text"]');
function setOption() {
msg[this.name] = this.value;
toggle();
}
options.forEach(option => option.addEventListener('change', setOption));
這樣就大功告成了!
[Demo](https://jasonyangbanana.github.io/JS30/23 - Speech Synthesis/index-START.html)
完整程式碼