Sitemap

Have you ever use SpeechSynthesis ?

7 min readDec 23, 2024

--

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奇摩拍賣上。

TW Yahoo Auction and Web Speech API

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。

Reference

--

--

Paul Li
Paul Li

Written by Paul Li

Paul is the lead programmer of the AMP project at Yahoo Taiwan and is always eager for modern web technologies. He is also focusing on UX for vivid user flow.

No responses yet