Have you ever use SpeechSynthesis ?
Introduction
前一陣子看到 Gemini APP 在 App Store 上架後,立馬安裝起來體驗看看,當中最吸引我的部分便是下完 prompt 後,該 app 便會立即朗讀回來的結果。雖然說這不是什麼新穎的功能,卻讓整體易用性以及使用者體驗上起來畫龍點睛的效果。也因為這樣讓筆者起心動念想將這樣的體驗移植到 web page 來。
一直以來要讓系統可以「朗讀」這檔兒事縱是需要額外加工,好比 Chrome Extension 或者其他的 cloud service 輔助。也就是說對 web page 來說不是那麼友善與便利,雖然說花點小錢就可以辦到了,但是不是每個服務都能有充分的資源來完成這種可有可無的功能,也因為這樣讓筆者尋求是否有其他可能性~
經一番 survey 後,原來 Web Speech API 早已支援了朗讀功能,而且幾個主流的瀏覽器均有支援,也就是說要讓 web page 具備朗讀的功能是絕對可行的,所以今天要來跟大家分享筆者是如何 adopt 這樣的功能到 Yahoo奇摩拍賣上。
Web Speech API
這個 API 基本上分成了兩個面向,分別是「SpeechRecognition」以及「SpeechSynthesis」。和其 naming 一樣,分別表示了 speech to text 以及 text to speech。
- SpeechRecognition:須取得使用者授權後,便可以 device microphone 取得聲音,進而解析這段聲音所代表的意涵,由於瀏覽器的實作不同,所以部分瀏覽器(Chrome)當下需要具備網路連線能力。
- SpeechSynthesis:透過文字內容的餵入,設定對應的口說參數後,便能驅動 OS 的語言混音器進行唸出該內容的行為。
今天要跟大家分享的內容為朗讀部分的實作,也就是說會著重在後者 SpeechSynthesis 的部分。
SpeechSynthesis & SpeechSynthesisUtterance
朗讀的功能主要架構在 SpeechSynthesis & SpeechSynthesisUtterance 之上,透過全域變數 SpeechSynthesis 的 speak()、resume() 以及 pause() 這三個 method 來進行對應的操作,可以透過它所提供的 property speaking 來確認當前的狀態。
而 SpeechSynthesisUtterance 這個 class 所負責的則是口說內容的設定,當中包含了 lang、voice 以及 text 這幾個主要的 properties。Developers 可以透過 event 的監聽來動態改變 button icon 的呈現。
以上便是完整的 sample code,當使用者點擊按鈕後,讓系統唸出「這是一段文字轉成語音測試。」。朗讀的當下 button 的 icon 會由原本 speaker 轉換成 pause。讓使用者可以知道當前朗讀狀態並決定是否要 pause 或者讓系統念完。最終念完後,再將 icon 轉換成 speaker。
接下來講解一下 code 的概要:
- Line 11:判斷當前瀏覽器是否支援 web speech api,若不支援則將 button 移除。
- Line 52~56:針對 new 出來的 utterance 物件進行監聽,監聽的 event 有 start、end、resume、pause、error。
- Line 19~30:utterance 的 event handler,針對不同 event 的觸發來動態更改 button 所顯示的圖示。
- Line 37~45:button click 的 handler,透過 synth.speaking 來判斷是否朗讀中,若為否,則先無條件強制中斷朗讀(不管是否朗讀中),然後設定 utterance 的各項口說參數,最常設定的不外乎是 lang、text 以及 voice(可透過 synth.getVoices() 取得當前支援的所有聲音)。若為否,表示當前朗讀發生中,則可以透過 synth.paused 來決定要呼叫 synth.resume() 來繼續朗讀或是呼叫 synth.pause() 來進行暫停。
- Line 32~34:由於瀏覽器 SpeechSynthesis 是以排 queue 的方式來進行朗讀,所以養成好習慣,當當前 window 或者 tab 被使用者關閉時,亦要記得呼叫 synth.cancel() 避免影響到其他 tab 的 init。
FAQ
Question 1:除了系統預設的聲音,我要怎麼避免被 DEI 議題騷擾?
Answer:可以透過 synth.getVoices() 來取得當前所支援的所有聲音,再挑出符合內容語系的聲音並提供給使用者選擇。(有些聲音不見得可以完整念出設定的內容,上線前務必要多多進測試)
Question 2:有關價錢的部分要怎麼讓系統正確無誤唸出 $1,000
Answer:由於筆者在 TW Auction 上加上朗讀的功能,免不了會遇到這樣的狀況。測試的時候,系統會唸出「美金一千」。主要就是那個「$」符號導致。為了避免這種窘境,所以把「$」換成「NT$」。果然它就正確唸出「新台幣一千」,不過可能因為前後文內容的差異有機會造成系統誤,所以它有時候也會唸出「N T dollar sign 一千」這種完全聽不懂的東西。真真讓人啼笑皆非。最後,筆者索性就把金錢表示服務移除,直接改文為「1000 元」。方能符合筆者的期待。
Question 3:有些有意義的 id 該怎麼讓系統無誤的念出?比方說「Y1234567890」
Answer:在 TW Auction 有些店名因為賣家沒有設定的關係,所以 TW Auction 會直接拿該會員的 id 當作店名進行呈現,如問題陳列的「Y1234567890」便是這種狀況。而這類 id 有可能會被系統拆開念成「Y 十二億」,由於 PM 希望系統可以唸出「歪一二三四五六七八九零」。所以我們可以透過加工的方式進行調整。最快的方法便是在每個 char 之間直接塞入一個 space 進行隔開,那麼就不會被誤判成一個有效的數字。如此一來便能完成需求了。(為了唸得順暢,Y 有可能會故意和後面的數字結合念出很怪的讀音,所以最好直接轉換成國字「歪」)
Question 4:有些英文縮寫詞彙可能正確唸出,有機會可以解決嗎?
Answer:筆者遇過「No 1」這個簡寫詞彙系統無法無誤的念出。就算改成「NO. 1」也是一樣(有可能念出「no 衣」)。這時候最快的解法就把縮寫拆成完整英文單字,亦或是改成音譯(比方說「難波萬」)。便能捏成我們想要的樣子了。
Conclusion
透過 sample code 的導讀以及 FAQ 的闡述,應該讓大夥兒對於 Web Speech API 朗讀的功能有了一定程度的瞭解了吧!筆者蠻喜歡這個 Web API,不僅僅提供了另類的瀏覽體驗,更讓易用性與使用者體驗更上一層樓,有興趣的朋友千萬不要錯過了 Web Speech API。