JS30 day23 - Speech Synthesis
作業內容
最近做的都跟聲音有關,雖然概念上不複雜但我覺得 Google 能把這個東西實作出來放在瀏覽器真的太猛了吧 = =,這個作業自己覺得比較難的部分是理解整個 google 系統是怎麼把聲音的資訊結合成物件
學到什麼
-
JS
SpeechSynthesisUtterance()
物件為 Web Speech API 中代表一發音的需求,翻成白話文就是一段話的資訊,例如內容,語言、音調、聲音、速率等,我們可以透過 console log 看看這個物件的組成:
1
SpeechSynthesisUtterance {text: "", lang: "", voice: null, volume: -1, rate: -1, …}
發出聲音的方式是用下面的方式來說:
1
SpeechSynthesis.speak(<SpeechSynthesisUtterance實體>)
上面這句的
SpeechSynthesis
介面是語音合成伺服器的控制器,可透過其來取得可使用的語音合成資訊,並播放或暫停發音等相關功能
speechSynthesis.addEventListener('voiceschanged', populatVoices)
voiceschanged 事件是當SpeechSynthesis.getVoices()
改變時被觸發,它也是 SpeechSynthesis 唯一的一個事件。
這裡會被觸發,Bos 是說因為 SpeechSynthesis 被讀取所以觸發了這個事件
SpeechSynthesis.getVoices()
:取得一陣列,其中包含目前所有的 SpeechSynthesisVoice 物件,其裡頭的屬性為當下環境支援的所有發音資訊,晚點必須選擇其中一個給 msg 這個實體才有辦法發出聲音
1
2
3
4function populateVoices(){
voices = this.getVoices()
console.log(voices)
}參考資料:https://ithelp.ithome.com.tw/articles/10196799
- 現在要做出在下拉選單選擇不同語言就要發出不同語言的聲音
1
2
3
4function setVoice(){
msg.voice = voices.find(voice => voice.name === this.value)
}
voicesDropdown.addEventListener('change', setVoice)- 做出切換語言同時直接中段前一個然後發聲音
1
2
3
4
5
6
7
8
9
10
11function setVoice(){
msg.voice = voices.find(voice => voice.name === this.value)
toggle()
}
function toggle(startOver = true){
speechSynthesis.cancel()
if (startOver){
speechSynthesis.speak(msg)
}
}- 監聽 scroll bar 跟 text 變化
1
2
3
4
5
6
7
8function setOption(){
console.log(this.name, this.value);
msg[${this.name}] = this.value;
toggle();
}
options.forEach(option => {
option.addEventListener('change', setOption)
})- 綁定 stopButton 事件的時候注意不能這樣寫
1
stopButton.addEventListener('click', toggle(false))
這樣會只有在一開始的時候觸發一次,按鍵本身沒作用,所以有兩種寫法
bind()
會生成一個新的綁定函式,第一個值是 this 的值,後面的才是第 1,2,3…個參數1
2
3stopButton.addEventListener('click', toggle.bind(null, false))
// 或者
stopButton.addEventListener('click', () => toggle(false))- 經過自己分析之後,發出聲音的步驟可以拆解如下如下
1
2
3
4
5
6
7
8
9
10
11
12
13//1.把瀏覽器可以發出的聲音列出來,放在下拉選單(window 會比 mac 少),這邊的 this 是 speechSynthesis
voices = this.getVoices()
//2.根據使用者選的下拉選單,把指定的這個 vioce 物件塞回去給 SpeechSynthesisUtterance 生出來的實體 msg
msg.voice = voices.find(voice => voice.name === this.value)
//3.根據 input 不同改變這段 msg 的內容 / 速度 / 音高
msg[this.name] = this.value
//4.包裝成 toggle function 發出聲音,如果傳入的參數是 false 就可以不發出聲音
function toggle(startOver = true){
speechSynthesis.cancel()
if (startOver){
speechSynthesis.speak(msg)
}
}
參考資料:
https://github.com/wesbos/JavaScript30
code 內容:
HTML:
1 | <div class="voiceinator"> |
CSS:
1 | html { |
JS:
1 | const msg = new SpeechSynthesisUtterance(); |