音声合成(AquesTalk)をPythonから…に今さらながらチャレンジ

[pukiwiki]
クイックジャパンを立ち読みしたところ(すんません)、「モヤモヤさまぁ~ず2」のナレーション「ショウくん」は音声合成ソフト、とのこと。
てっきり人間だと思ってましたよ(汗

というわけで(?)Pythonからフリーの音声合成ライブラリ AquesTalkを使って遊んでみました。ついでに、MeCabをつかって読み仮名の取得にもチャレンジ。

使ってみて。。。大量に読み上げさせたい場合は、ちゃんとしたソフトを買ったほうが楽だと思います(汗

でも、ほんのちょっとだけ遊びたいなら、結構便利かも、です。

-[[サンプル音声 (mp3 55KB):http://boxheadroom.com/wp/wp-content/uploads/2008/04/test.mp3]]

以下 ソースコード
[/pukiwiki]

[pukiwiki]
*つかいみち
-ちょっとだけ合成音声が欲しい
-プログラムにかかるまえに、AquesTalkの性能がどんなだか調べたい

などなど。

*つかいかた
windows版 Python2.5用
-kanaボタンで、漢字かな混じり文の読み仮名を取得
-saveボタンで、wavファイルとして保存。
-talkボタンで音声再生
(AquesTalkで認識できない記号が文に混じっていると音が出ません。)
(基本的には仮名のみでないとダメ)
-マウスで選択した部分のみ読み上げます。
–選択しないと全文。
-読み上げが終わるまでソフトがストップしますので注意。

*使用したライブラリ
-[[AquesTalk Windows用:http://www.a-quest.com/aquestalk/index_win.html]]
独特の表記法により、イントネーションを指定する必要あり。主として
–Windows版は無料で使えます
–Python用のスクリプトと同じディレクトリにDLLを置く(もしくはDLLにパスを通す)
–シングルコーテーション記号を、イントネーションが高い場所に挿入する
–単語の区切りにスラッシュを入れる。
–女声、男声、ロボットっぽい声、などなど追加データも。(これも無料)
-[[AquesTalkをPythonから(音声合成):http://d.hatena.ne.jp/tomoemon/20071116#p1]]
感謝
-[[MeCab:http://mecab.sourceforge.net/]]
–[[Python日本語あれこれ。MeCab,zenhan.py,unichr:http://boxheadroom.com/2007/12/27/mecab_zenhan]]
バイナリの配布場所など
*ソースコード
_# -*- coding: utf8 -*-
_from AquesTalk import AquesTalk
_import time
_from Tkinter import *
_import re
_import MeCab
_
_TXTWIDTH = 60
_TXTHEIGHT = 20
_
_def check(s,
_ pat= re.compile(r”([^” u”、。.,.ぁ-ん,ァ-ン,ー,0-9,a-z,A-Z,A-Z” r”])”,re.UNICODE)
_ ) :
_ s2=pat.sub(r””, yomi)
_ return s==s2
_
_
_def cnvkana(s,biaskata=ord(u”ァ”),biashira=ord(u”ぁ”),
_ pat= re.compile(r”([” u”ァ-ン” r”])”,re.UNICODE)):
_ return pat.sub(lambda x: unichr(ord(x.group(0))-biaskata+biashira),s)
_
_def cnvnum(s,biaszen=ord(u”0”),biashan=ord(“0″),
_ pat1= re.compile(r”([” u”0-9” r”])”),
_ pat2=re.compile(r”([0-9]+)”),
_ f=lambda x: unichr(ord(x.group(0))-biaszen+biashan)
_ ):
_ s=pat1.sub(f,s)
_ return pat2.sub( r”“,s)
_def cnvalpha(s,biashan=ord(“a”),biaszen=ord(u”a”),
_ pat= re.compile(r”([” u”a-z” r”])”)
_ ):
_ return pat.sub(lambda x: unichr(ord(x.group(0))-biashan+biaszen),s)
_
_def timestamp(last=[0]):
_ t=time.strftime(“%Y%m%d%H%M%S”,time.localtime())
_ if last[0]==t :
_ time.sleep(1)
_ t=time.strftime(“%Y%m%d%H%M%S”,time.localtime())
_ last[0]=t
_ return t
_
_
_class App(Frame):
_ name = “”
_ text = unicode(
_ u”””モヤモヤさ’まーず。こんしゅうわ、あな’たの/まち’に,おじゃましちゃいま’す。う’そです。
_
_あくえす’/と’ーーくわ/、/てきすと’/じょ’ーーほーーを,おんせい’/は’けいに/へんかん’,しゅつ’りょくする,うぃんどうず’/じょーーで/ど’ーーさする,きそく’/お’んせい/ごーーせい’/ら’いぶらりです。
_
_なめ’らかな,ききとりやす’い/おんしつと,しぜんな’,イ’ントネ’ーション。”””
_
_)
_
_ def init(self):
_ self.t = MeCab.Tagger (” “.join(sys.argv))
_ self.at=AquesTalk()
_ self.master.title(“Talk Test”)
_ self.d = Text(self,width=TXTWIDTH,height=TXTHEIGHT)
_ f = Button(text=”Save”,command=self.cmd_clicked_save)
_ e = Button(text=”Kana”,command=self.cmd_clicked_kana)
_ g = Button(text=”Talk”,command=self.cmd_clicked_talk)
_ self.d.pack(padx=5, pady=0)
_ self.d.insert(END,self.text)
_
_
_ g.pack(side=RIGHT, padx=5, pady=5)
_ f.pack(side=RIGHT, padx=5, pady=5)
_ e.pack(side=RIGHT, padx=5, pady=5)
_ self.d.focus()
_ self.pack()
_
_ def cmd_clicked_kana(self):
_ t=self.txt()
_ t
_ self.getyomi(t)
_ self.stat = 2
_
_ def cmd_clicked_save(self):
_ fn=timestamp()
_ print >>file(fn+”.txt”,”wb”),self.txt().encode(“utf8″,”ignore”)
_ self.at.SyntheFile(self.txt(fsjis=True).replace(“\n”,””),100,fn+”.wav”)
_
_ self.stat = 2
_
_ def cmd_clicked_talk(self):
_ self.at.PlaySync(self.txt(fsjis=True),100)
_ self.stat = 2
_
_
_ def getyomi(self,s):
_ txt=cnvalpha(s)
_ txt = txt.encode(“sjis”,”ignore”)
_ m = self.t.parseToNode (txt)
_ l=[]
_ while m:
_ y=m.feature.split(“,”)[-1]
_ if y==”*” or not y:
_ y=m.surface
_ l.append(y)
_ m = m.next
_
_ yomi=”/”.join(l)
_ yomi=cnvkana(yomi)
_ yomi=cnvnum(yomi)
_ yomi=”\n\n”+yomi+”\n\n”
_ yomi=yomi.decode(“sjis”,”ignore”)
_ yomi=re.sub(r”(\b|” u” ” r”)”,””,yomi)
_ yomi=yomi.replace(u”ー”,u”ーー”)
_ yomi=cnvkana(yomi)
_ self.d.insert(INSERT,yomi)
_ return yomi
_
_ def txt(self, fsjis=False ):
_ try:
_ text=self.d.get(SEL_FIRST, SEL_LAST)
_ except TclError,e :
_ text = self.d.get(“1.0”,END)
_ text=text.replace(“\n”,””)
_ if fsjis :
_ text=text.encode(“sjis”,”ignore”)
_ return text
_
_ def __init__(self, master=None):
_ Frame.__init__(self, master)
_ self.pack(); self.init()
_
_ def mainloop(self,objname,objtext,mode):
_
_ Frame.mainloop(self)
_app=App()

*今後の改良点
イントネーション記号を自動で振ってくれるようにするには。。。
私じゃムリっぽいです(汗 というか、本格的に読ませるには、多分、市販品買ったほうが安いですし。
(AquesTalkは、インタラクティブなソフト内から使いたいとき、には便利ですけれども)

[/pukiwiki]

コメントを残す

メールアドレスが公開されることはありません。