2015年8月17日 星期一

用Python擴充我的Scratch2 -- 文字轉語音

在使用Scratch做動畫時,常常要呈現角色的台詞,有時在思考,
如果角色有聲音的話有多好。當然Scratch是可以做到,只要把台
詞一句一句錄成聲音檔就好了,只是過程會很辛苦。那有沒有什麼
方法可以讓角色的發出聲音呢?記得之前在寫AppInventor時,
有使用到一種依照文字動態、即時地發出聲音的做法,就是「文字轉語音」
(Text To Speech,簡稱TTS)。


(圖片來源:minionvilla.com)

「文字轉語音」的方式在不同的OS上許多選擇,在IOS上有NSSpeechSynthesizer
,在linux有espeak,在Windows有SAPI5,google也有線上的TTS引擎可以使用, 甚至也有「工研院文字轉語音Web服務」,因為自己只以手邊方便的做法,所以只有嘗試SAPI5,其他的TTS方法我目前都未研究,有興趣的人都可以試試看,不過要注意是否支援中文語音。


在這裡提一下我的實作環境,OS是Windows8.1的筆電,python是3.4版,使
用的SAPI5的TTS功能,為了能存取SAPI的TTS功能(SpVoice的com物件),
python需要安裝win32模組。對於OS,TTS,或是程式語言,只要能找到同樣
功能的組合,也不一定要跟我的環境一樣,只有原理了解,找到合適工具,
相信也可以有不同的做法來結合TTS的功能。


這一篇文章主要討論的是,使用python,依照Scratch2的擴充積木機制,
,做出Scratch2的「文字轉語音積木」(SAPI TTS),有關Scratch2的擴充
原理,請參考之前的文章。本文會在原理的基礎上,做一些應用。有關
SAPI5的TTS(SpVoice)的參考資料,詳細請看MSDN

要讓Scratch2支援文字轉語音(TTS),主要有三個問題,第一個是python
要如何使用SAPI5的TTS功能。第二個是TTS的積木描述檔(s2e)要怎麼定義。
第三個是helper伺服程式要怎麼寫。沒關係,就一個一個來克服吧!

關於第一個問題,python要使用SAPI5的TTS功能,需要安裝pywin32模組,因安裝時有地方要特別注意,所以稍做一下說明。下載連結是 pywin32 Source Forge ,要注意要下載的檔案,必須要與python的版本相對應,在下圖是我python的互動模式

在兩個紅框中的資訊,表示我的python是3.4版,以32位元編譯(雖然我的機器是64位元),所以下載檔案時,要下載如下圖紅框標示的檔案,下載完就進行安裝

那python使用SAPI5的TTS,要怎麼寫呢?我寫了一個測試程式,測試TTS在使用上可能有的不同功能。程式如下:


主要連結的語法是3~6行,產生出來的speaker物件,可以透過它就可以做出TTS功能。在第12及13行中,Rate是改變語音的速度(-10~10),Volume是語音音量(0~100),真正要說出語音,是用像19行的寫法,speaker.Speak("要說的文字") ,這樣就可以把語音說出來。在這個程式中,我用了第15行的示範文字(使用蘇恆誠老師的名義,請見諒),分別做了四個測試,因為也會與後面的Scratch2積木功能設計有關,所以在此說明一下。

測試一是同步語音(19~21行),會等待聲音播完後,再執行下一行

測試二是非同步語音(25~30行),不會等待聲音播完,程式會繼續執行下去

測試三是語音音量(35~42行) ,有大、中、小聲

測試四是語音速度(47~53行)  ,中、快 、慢速

程式實際運行的影片如下(主要是聽語音的部分):



接著第二個問題,在Scratch2中,SAPI TTS積木要怎麼規畫呢?大致上是依照之前的四個測試,來設計出四個積木,s2e的積木描述檔如下:

 在Scratch2中匯入s2e檔之後的積木如下圖:

這次的s2e檔定義了四個新積木,比上次的再複雜一些,解釋如下
(每個積木的前三個參數說明,請看前一篇)

第一個積木的定義是在 s2e檔中的第6行,這是不等待的轉語音積木,跟上次比起來,第2個參數裡的積木格式,多了%s,這會讓積木中有個文字格子。另外多了第4個參數 "文字" ,這是代表的是積木裡格子的預設值

第二個積木的定義是在第7行,這是會等待的轉語音積木, 語音播完 ,Scratch2才會繼續下一個積木。在參數定義中,第1個積木種類參數是"w",這是等待積木的意思,Scratch2會等這個積木執行完。(註:積木等待執行的機制其實有另外的細節,可參考Scratch2的資料)  

(等待與不等待這兩種積木,在原本的Scratch2就有使用,如「播放聲音」與「廣播」積木)

第三個積木的定義是在第8行,這個積木會把語音速度值送出。在第二個積木格式參數,有個沒見過的%m.speed,其中的%m會讓積木上出現選單,而speed是會到第13行去找出選單的內容,在這裡語音速度值是從-10到10

第四個積木的定義是在第9行,這個積木會把語音音量值送出。同樣%m.volume產生一個選單,值的範圍是0~100    

到這裡完成了s2e的積木描述檔

最後一個問題,helper伺服程式如何寫呢?基本上只要把第一個測試的python程式,加上Scratch2的helper伺服程式,就可以了,先來看一下helper伺服程式的寫法:

第11~26行是建議的全域變數區域,也可以不放這裡,但放在此處比較好理解。
全域變數有語音速度、語音音量

第29~31行是要呼叫SAPI,產生一個speaker物件(可與第一個測試程式的code互相對照)

再來http的程式一樣略過,主要來看53~77之間,處理Scratch2送來的Get 命令的程式碼。這裡的四段if,就會分別處理 s2e中定義的四個積木命令名稱的真正動作,實際的轉成語音,改速度,音量,都是在這個地方完成。(可與第一個測試程式的code互相對照)

在這邊特別提出的是,當積木有參數時,實際送出的命令是什麼呢?以第一個積木為例 ,如果第一個積木的文字是Hi, 那送出的命令是/ttsNoWait/Hi,參數會在命令名稱後面,加上/後,接上文字內容。另外要提的是,如果參數是中文的話,會像中文網址一樣,會做URL的編碼,所以在59與64行,為什麼會加上unquote函式,就是要把URL編碼過的中文字再還原回來。(註:有認真看code的人會發現,第64行有點不一樣,cmd_list的索引值變成2,這個主要是因Scratch2在處理等待積木,會自動多加上一個參數的關係)

最後完成的Scratch2 的SAPI TTS擴充積木的測試影片,請看下方


這樣就可以在Scratch2中使用「文字轉語音TTS」的功能了。

最後附一段這篇文章的概念影片,影片的最後,有個應用於動畫的效果展示


做了半天,寫了這麼久,終於完成了。有時會問自已,這麼麻煩的做出這個功能,值得嗎?等別人做出來不就好了?到底是為什麼?

也許是覺得有趣,或許是覺得很酷,亦或是想要了解事物運作原理的好奇心吧!還有,不管是maker或是Coder,如果我自己如果不動手making 或是coding的話,總是會有個少了什麼的感覺吧!




沒有留言:

張貼留言