功能
將文字轉換成語音,並透過控制條調整語音的速率以及音調。
- SpeechSynthesis(文本轉換語音):可拿到語音合成,並播放或暫停發音等屬性
- SpeechSynthesisUtterance(文本轉換語音控制):可調整音調、聲音、速率等屬性
- SpeechRecognition(語音轉換文本)
step 1 : 建立 SpeechSynthesisUtterance 物件,并且取得 HTML 頁面中的元素
// 設置 SpeechSynthesisUtterance
const msg = new SpeechSynthesisUtterance();
let voices = [];
const voicesDropdown = document.querySelector('[name="voice"]');
// 選取器同時選取 type 為 range,以及 name 為 text
const options = document.querySelectorAll('[type="range"],[name="text"]');
const speakButton = document.querySelector("#speak");
const stopButton = document.querySelector("#stop");
// 語音說出的内容為文字欄位中的内容
msg.text = document.querySelector('[name="text"]').value;
step 2 : 拿到當前使用裝置的語音語系,並放入下拉選單中
SpeechSynthesis.getVoices():回傳當前裝置可用的所有聲音清單(包含lang, name等屬性)
function populateVoices() {
// 取得當前裝置的語音語系,並放入變數 voices
voices = this.getVoices();
// 將所有語系選項放入下拉選單中
voicesDropdown.innerHTML = voices
// filter 篩選出包含 en 的語系
.filter(voice => voice.lang.includes('en'))
// 用 map 將篩選後資料組一個個 option 選項
.map(voice => `<option value=${voice.name}>${voice.name} (${voice.lang})</option>`)
// 用 join 去除 map 後回傳的陣列中的逗號
.join('');
}
// 監聽語系選單,選單改變時,觸發該事件並更新語系清單
speechSynthesis.addEventListener('voiceschanged', populateVoices);
step 3 : 設定播放相關功能
function toggle(starOver = true) {
// 先停止播放
speechSynthesis.cancel();
// 如果 startOver 為 true
if (starOver) {
// 開始播放
speechSynthesis.speak(msg);
}
}
function setVoice() {
// 設定發音的語系設爲下拉選單中切換的語系
msg.voice = voices.find(voice => voice.name === this.value);
// 播放
toggle();
}
function setOption() {
// options 這個 Nodelist,
// 剛好裡面每個值的 name 取名的與 SpeechSynthesisUtterance 的物件屬性相同
// 所有可以通過下列方式,改變其 value
msg[this.name] = this.value;
// 播放
toggle();
}
// 監聽語系的下拉選單,可以切換發音的語系
voicesDropdown.addEventListener('change', setVoice);
// 監聽速率跟音調控制條以及文字欄位,有變動時觸發 setOption function
options.forEach(option => option.addEventListener('change', setOption));
// 監聽播放按鈕,如果被點擊,觸發 toggle function
speakButton.addEventListener('click', toggle);
// 監聽停止按鈕,如果被點擊,觸發 toggle function,並帶入參數 false
stopButton.addEventListener('click', () => toggle(false));
完整程式碼
const msg = new SpeechSynthesisUtterance();
let voices = [];
const voicesDropdown = document.querySelector('[name="voice"]');
const options = document.querySelectorAll('[type="range"],[name="text"]');
const speakButton = document.querySelector("#speak");
const stopButton = document.querySelector("#stop");
msg.text = document.querySelector('[name="text"]').value;
function populateVoices() {
voices = this.getVoices();
voicesDropdown.innerHTML = voices
.filter((voice) => voice.lang.includes("en"))
.map(
(voice) =>
`<option value="${voice.name}">${voice.name} (${voice.lang})</option>`
)
.join("");
}
function setVoice() {
msg.voice = voices.find((voice) => voice.name === this.value);
toggle();
}
// function play() {
// stop();
// speechSynthesis.speak(utterance);
// }
// function stop() {
// speechSynthesis.cancel();
// }
function toggle(startOver = true) {
speechSynthesis.cancel();
if (startOver) {
speechSynthesis.speak(msg);
}
}
function setOption() {
console.log(this.name, this.value);
msg[this.name] = this.value;
// play();
toggle();
}
speechSynthesis.addEventListener("voiceschanged", populateVoices);
voicesDropdown.addEventListener("change", setVoice);
options.forEach((option) => option.addEventListener("change", setOption));
speakButton.addEventListener("click", toggle);
stopButton.addEventListener("click", () => toggle(false));
// speakButton.addEventListener("click", play);
// stopButton.addEventListener("click", stop);
參考資料: