語音合成 API 是一個非常棒的工具,現代瀏覽器提供了這個 API,讓我們能夠嘗試建立新型的介面並讓瀏覽器與使用者互相對話。
該 API 於 2014 年被引入,現在已經被廣泛採用,Chrome、Firefox、Safari 和 Edge 都已提供支持。不過,IE 不支援。
它是 Web 語音 API 的一部分,還包括「語音辨識 API」,不過目前只有 Chrome 在實驗模式下支援該功能。
最簡單的使用語音合成 API 的示例是一行程式碼:
speechSynthesis.speak(new SpeechSynthesisUtterance('嗨'))
將其複製並貼到瀏覽器控制台中,你的電腦應該會開始說話!
API
該 API 會將一些物件公開給 window
物件。
SpeechSynthesisUtterance
SpeechSynthesisUtterance
表示一個語音請求。在上面的例子中,我們將字符串作為參數傳給它,這是瀏覽器應該要朗讀的內容。
一旦獲得了語音請求物件,你可以對它進行一些調整,以編輯語音的屬性:
const utterance = new SpeechSynthesisUtterance('嗨')
utterance.rate
:設置語速,接受區間為 [0.1 - 10],預設為 1utterance.pitch
:設置音調,接受區間為 [0 - 2],預設為 1utterance.volume
:設置音量,接受區間為 [0 - 1],預設為 1utterance.lang
:設置語言(使用 BCP 47 語言標籤,如en-US
或it-IT
)utterance.text
:可以在建構函式中設置,也可以作為屬性傳入。文本長度不能超過 32767 個字符。utterance.voice
:設置語音(關於這個後面會說明更多)
以下是一個示例:
const utterance = new SpeechSynthesisUtterance('嗨')
utterance.pitch = 1.5
utterance.volume = 0.5
utterance.rate = 8
speechSynthesis.speak(utterance)
選擇一個語音
瀏覽器提供了不同數量的語音。
使用以下程式碼查看語音列表:
console.log(`語音數量:${speechSynthesis.getVoices().length}`)
speechSynthesis.getVoices().forEach(voice => {
console.log(voice.name, voice.lang)
})
這是一個跨瀏覽器的問題。上面的程式碼在 Firefox 和 Safari(可能也包括 Edge,但我沒有測試過)中運作正常,但在 Chrome 中不起作用。Chrome 使用不同的方式來處理語音,並要求在語音加載完成後呼叫回調函式:
const voiceschanged = () => {
console.log(`語音數量:${speechSynthesis.getVoices().length}`)
speechSynthesis.getVoices().forEach(voice => {
console.log(voice.name, voice.lang)
})
}
speechSynthesis.onvoiceschanged = voiceschanged
在回調函式被調用之後,我們可以使用 speechSynthesis.getVoices()
方法來獲得語音列表。
我相信這是因為 Chrome(如果有網絡連接)會從 Google 伺服器檢查其他語言:
如果沒有網絡連接,可用語言的數量與 Firefox 和 Safari 相同。附加的語言僅在網絡已啟用的地方提供,但該 API 也可以在離線狀態下運作。
跨瀏覽器實現語言選擇
由於存在這種差異,我們需要一種方法來抽象化它以使用這個 API。以下示例演示了如何實現這種抽象化:
const getVoices = () => {
return new Promise(resolve => {
let voices = speechSynthesis.getVoices()
if (voices.length) {
resolve(voices)
return
}
speechSynthesis.onvoiceschanged = () => {
voices = speechSynthesis.getVoices()
resolve(voices)
}
})
}
const printVoicesList = async () => {
;(await getVoices()).forEach(voice => {
console.log(voice.name, voice.lang)
})
}
printVoicesList()
使用自訂語言
預設的語音是使用英文發音的。你可以使用任何語言,只需設置 utterance 的 lang
屬性即可:
let utterance = new SpeechSynthesisUtterance('Ciao')
utterance.lang = 'it-IT'
speechSynthesis.speak(utterance)
使用其他語音
如果有多個語音可用,你可能想選擇其他語音。例如,預設的意大利語音是女性聲音,但也許我想要男性聲音,那就是語音列表中的第二個語音。
const lang = 'it-IT'
const voiceIndex = 1
const speak = async text => {
if (!speechSynthesis) {
return
}
const message = new SpeechSynthesisUtterance(text)
message.voice = await chooseVoice()
speechSynthesis.speak(message)
}
const getVoices = () => {
return new Promise(resolve => {
let voices = speechSynthesis.getVoices()
if (voices.length) {
resolve(voices)
return
}
speechSynthesis.onvoiceschanged = () => {
voices = speechSynthesis.getVoices()
resolve(voices)
}
})
}
const chooseVoice = async () => {
const voices = (await getVoices()).filter(voice => voice.lang === lang)
return new Promise(resolve => {
resolve(voices[voiceIndex])
})
}
speak('Ciao')
語言的值
以下是你可以使用的一些語言的示例:
- 阿拉伯語(沙特阿拉伯)➡️
ar-SA
- 中文(中國)➡️
zh-CN
- 中文(香港特別行政區中國)➡️
zh-HK
- 中文(台灣)➡️
zh-TW
- 捷克語(捷克共和國)➡️
cs-CZ
- 丹麥語(丹麥)➡️
da-DK
- 荷蘭語(比利時)➡️
nl-BE
- 荷蘭語(荷蘭)➡️
nl-NL
- 英語(澳大利亞)➡️
en-AU
- 英語(愛爾蘭)➡️
en-IE
- 英語(南非)➡️
en-ZA
- 英語(英國)➡️
en-GB
- 英語(美國)➡️
en-US
- 芬蘭語(芬蘭)➡️
fi-FI
- 法語(加拿大)➡️
fr-CA
- 法語(法國)➡️
fr-FR
- 德語(德國)➡️
de-DE
- 希臘語(希臘)➡️
el-GR
- 印地語(印度)➡️
hi-IN
- 匈牙利語(匈牙利)➡️
hu-HU
- 印度尼西亞語(印尼)➡️
id-ID
- 意大利語(義大利)➡️
it-IT
- 日語(日本)➡️
ja-JP
- 韓語(南韓)➡️
ko-KR
- 挪威語(挪威)➡️
no-NO
- 波蘭語(波蘭)➡️
pl-PL
- 葡萄牙語(巴西)➡️
pt-BR
- 葡萄牙語(葡萄牙)➡️
pt-PT
- 羅馬尼亞語(羅馬尼亞)➡️
ro-RO
- 俄語(俄羅斯)➡️
ru-RU
- 斯洛伐克語(斯洛伐克)➡️
sk-SK
- 西班牙語(墨西哥)➡️
es-MX
- 西班牙語(西班牙)➡️
es-ES
- 瑞典語(瑞典)➡️
sv-SE
- 泰語(泰國)➡️
th-TH
- 土耳其語(土耳其)➡️
tr-TR
移動裝置
在 iOS 上,這個 API 是可以工作的,但必須由使用者操作回調函式觸發,例如對點擊事件的回應,以提供更好的用戶體驗,避免手機發出意外的聲音。
在桌面版中,你無法像在桌面版中那樣讓網頁突然發出聲音。