還記得幾天前我們有將語音專程文字
今天我們要將文字轉成語音
使用的是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.valuethis指向的是<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)
完整程式碼