Web Speech API (I): 使用 SpeechSynthesis 讓瀏覽器講話

Google 在去年以 Community Group 的方式,向 W3C 提交了 Web Speech API 的規格書。該 API 主要分為兩部分:

  1. 語音轉文字 (Speech Recoginition)
  2. 文字轉語音 (Speech Synthesis)

其中 Chrome 實作語音轉文字的語音辨識功能很久了,不過似乎並沒有急著實作文字轉語音的部份;反倒是回歸 Apple 掌握的 WebKit 最近實作了無 vender prefix 的 Speech Synthesis 相關 API,目前 WebKit Nightly 就玩得到,所以來玩玩看。下一版的 Safari (6.1/7.0) 也預計會支援此 API。

本篇之前於 HappyDesigner Mini 分享會 #2 分享,實際效果可參考 Demo 影片 或是 Demo Page

基本概念

最基本的來說,要讓你的瀏覽器講話,只要達成下面兩個步驟:

  1. 建立一個 SpeechSynthesisUtterance 類別的物件,代表「要講出聲的話」。
  2. 把 utterance 物件交給 window.speechSynthesis 使用 speak 方法來念出來。

你可以一次把多個 utterance 物件經由 speak 方法指派給 window.speechSynthesis,他會被加入一個發聲的佇列、依序被講出來。

調整 Utterance 設定

下面是 SpeechSynthesisUtterance 類別的規格。要調整 utterance 的設定可以從這邊看:

除了相關事件的部份省略以外,上面可以修改的屬性都蠻望文生義的。特別要提到的是 voice 這個屬性並不在 Web Speech API 的規格裡面,是 WebKit 額外實作的屬性,用來更換發音用的語音引擎。

text 屬性是這段 utterance 裡面要被念出來的文字。裡面可以是純文字或是 SSML,而且最多不能超過 32,767 個字元。

更換語音引擎 (for WebKit)

就 Web Speech API 規格來說,本來的設計是透過 utterance 的 voiceURI 屬性來指定不同的語音引擎。但是因為 WebKit 在 OS X 上是直接透過 OS X 內建的 VoiceOver 系統來實作,所以不使用指定 URI 的方式來指定引擎。雖然一般來說透過指定 utterance 的語言就可以達到更換語音引擎的效果,但是以 OS X 下面來說,部分語言(如英文)就有多個不同的語音引擎可以使用;或是中文文字可以使用國語(zh-TW)/普通話(zh-CN)/廣東話(zh-HK)來發音,所以需要時還是可以依需要做更換。

在 WebKit 下更換語音引擎的方法是:

  1. 透過 window.speechSynthesisgetVoices() 方法取得目前系統中所有可用的語音引擎清單。
  2. 清單中每個項目是一個 SpeechSynthesisVoice 類別的物件,裡面的屬性可以取得語音引擎支援的語言(lang)、引擎名稱(name)跟其他相關資訊。
  3. 從清單中過濾出要使用的語音引擎,然後把它指派給 utterance 的 voice 屬性(WebKit only)。

可參考下面的範例:

在範例中,清單中第 45 個(44 號)語音引擎剛好是講廣東話的 SinJi Compact;所以指派給 u 之後,講出來的話就會使用廣東話發音。

偵測語音狀態

這邊可以再複習一次,使用 SpeechSynthesis 讓瀏覽器「講話」的方法是:建立一個一個 utterance 物件,來描述要講話的內容、然後交給 window.speechSynthesisspeak() 方法來負責播放語音。如果要偵測語音的狀態,來跟其他部分做配合,可以就兩個層面來偵測。

偵測「瀏覽器是否正在講話」

window.speechSynthesis 物件下面有三個屬性,可以了解目前有沒有正在講話:

  • pending: 表示 synthesis 物件的佇列裡面有還在排隊等著發聲的 utterance 物件
  • speaking: 表示有 utterance 物件已經開始唸、但是還沒講完。即便是唸到一半暫停的狀態,speaking 也會是 true
  • paused: 表示有 utterance 物件被唸到一半,但是暫停中。
偵測 utterance 物件的狀態

你無法直接偵測 utterance 物件的狀態,但是可以透過註冊事件的方式來在不同情況時獲得通知。utterance 物件可用的事件有:

  • start: 這段 utterance 開始發聲
  • end: 這段 utterance 的文字全部講完了
  • error: 發生錯誤
  • pause: 講到一半暫停
  • resume: 這段 utterance 在暫停之後恢復繼續。文件中提到被加入 queue 的 utterance 是處於「暫停」狀態,但是輪到他發聲的時候因為是第一次開始,所以觸發的會是 start 事件而非 resume 事件。
  • mark: 如果你是指定一份 SSML 給 utterance 當做要念的內容,會在唸到「mark」標籤的時候觸發。這部份請參考 SSML 文件。
  • boundary: 當發音引擎念完(觸及邊界)一個單字 (word) 或一個句子的時候觸發。

其中比較常用的應該是 startendpauseresume 事件。

向 utterance 註冊獲得的事件是 SpeechSynthesisEvent 類別,裡面可以獲得這段 utterance 從開始發聲開始經過的時間 (elapsedTime) 跟目前所講到的位置 (charIndex)。

目前的 WebKit Nightly (v538.1+) 似乎在 charIndex 部分回傳都是 0;另外目前也還無法使用 addEventListener 方法直接向 utterance 物件註冊事件,只能使用如 onend 的屬性直接指定事件處理的 function。

Demo

在 HappyDesigner Mini #2 的時候,本來想要用 Web Speech API 做一個網頁版的 Siri。不過因為語音辨識(Speech Recognition)只有 Chrome 有實作、文字轉語音(Speech Synthesis)只有 WebKit/Safari 有實作、再加上時間不夠(?)作罷。但是成功做出了一個可以針對(一個)關鍵字做反應、然後把結果念出來的 Demo。

效果可參考本篇最上方的 Demo 影片、或是有興趣的話可以下載 WebKit Nightly 之後實際玩玩看

參考資料

  1. Web Speech API Specification
  2. WebKit Nightly Builds
comments powered by Disqus