クイックジャパンを立ち読みしたところ(すんません)、「モヤモヤさまぁ~ず2」のナレーション「ショウくん」は音声合成ソフト、とのこと。
てっきり人間だと思ってましたよ(汗
というわけで(?)Pythonからフリーの音声合成ライブラリ AquesTalkを使って遊んでみました。ついでに、MeCabをつかって読み仮名の取得にもチャレンジ。
使ってみて。。。大量に読み上げさせたい場合は、ちゃんとしたソフトを買ったほうが楽だと思います(汗
でも、ほんのちょっとだけ遊びたいなら、結構便利かも、です。
以下 ソースコード
つかいみち
- ちょっとだけ合成音声が欲しい
- プログラムにかかるまえに、AquesTalkの性能がどんなだか調べたい
などなど。
つかいかた
windows版 Python2.5用
- kanaボタンで、漢字かな混じり文の読み仮名を取得
- saveボタンで、wavファイルとして保存。
- talkボタンで音声再生
(AquesTalkで認識できない記号が文に混じっていると音が出ません。)
(基本的には仮名のみでないとダメ) - マウスで選択した部分のみ読み上げます。
- 選択しないと全文。
- 読み上げが終わるまでソフトがストップしますので注意。
使用したライブラリ
- AquesTalk Windows用
独特の表記法により、イントネーションを指定する必要あり。主として- Windows版は無料で使えます
- Python用のスクリプトと同じディレクトリにDLLを置く(もしくはDLLにパスを通す)
- シングルコーテーション記号を、イントネーションが高い場所に挿入する
- 単語の区切りにスラッシュを入れる。
- 女声、男声、ロボットっぽい声、などなど追加データも。(これも無料)
- AquesTalkをPythonから(音声合成)
感謝 - MeCab
- Python日本語あれこれ。MeCab,zenhan.py,unichr
バイナリの配布場所など
- Python日本語あれこれ。MeCab,zenhan.py,unichr
ソースコード
# -*- 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"<NUMK VAL=1>",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="nn"+yomi+"nn"
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は、インタラクティブなソフト内から使いたいとき、には便利ですけれども)
Related posts
タグ: Python