(完成動画。時々でてる音は録画用に使ったMacの音です、紛らわしくてごめん。)
2chのスレやしたらば、カキコなどの掲示板をSoftalkで読ませるフロントエンドはあるんだけど、Twitterのタイムラインを読ませるっていうのは見つからなかったので作ってみた。
TwitterのAPIを読むだけなので、スクラッチで書いてもそんなに難しいものではないんだけど、勉強がてらPythonのpython-twitterというライブラリを使ってみる。
追記:新しくエントリーを書きました
TwitterをSoftalkのゆっくりボイスでしゃべらせる 2 | クレコ
python-twitterの導入
実はこれがくそめんどいw
python-twitterまとめ ~導入まで – テックノート@ama-ch
を参考にして導入する。
simplejsonは、WindowsでCのコンパイラ環境が必要になったりする。詳しくないので、書いてある通りに実行していった。
Python 2.6ではhashlibなんちゃらの警告がでます
別にそのままつかっても問題ないけど毎回警告がでるので直し方。
@aoshimanさんに教えていただいた解決法、
2009-02-18 – nakkuの日記 [python]python2.6にtwitterのモジュールを入れる
にpatchがあるので、twitter.pyを書き換えればいい。
具体的には、simplejsonモジュールを使っているところをjsonモジュール、md5モジュールを使っているところをhashlibモジュールを使うようにそれぞれ書き換える。
TwitterのTLをSoftalkでしゃべらせるPythonスクリプト
import twitter, os, nkf, re, time # config userName = "username" passWord = "password" softalkPath = "C:\hogehoge\softalk.exe" softalkSpeed = "120" lastSinceTime = 0 lastGetTime = 0 # convert string def convertString(string): # remove HTML entity string = re.sub('&.+;', ' ', string) # remove quote string = re.sub('"', ' ', string) string = re.sub("'", ' ', string) # remove my username string = re.sub('^@' + userName + ' ', '', string) # convert unicode to sjis using nkf module string = nkf.nkf("-sX", string.encode("utf8")) return string # get twitter timeline def getTimeline(): global lastSinceTime api = twitter.Api(userName, passWord) statuses = api.GetFriendsTimeline(userName) #statuses = api.GetUserTimeline(userName) #statuses = api.GetReplies() for i in statuses[::-1]: if i.created_at_in_seconds > lastSinceTime: print "%s : %s" % (convertString(i.user.name), convertString(i.text)) os.system('"' + softalkPath + '" /V:60 /S:'+softalkSpeed+' /T:1 /W:' + convertString(i.user.name)) # when find my name and change voice if re.search(userName, i.text): os.system('"' + softalkPath + '" /V:60 /S:'+softalkSpeed+' /T:0 /W:' + convertString(i.text)) else: os.system('"' + softalkPath + '" /V:60 /S:'+softalkSpeed+' /T:3 /W:' + convertString(i.text)) lastSinceTime = i.created_at_in_seconds while True: # time span of get timeline if time.time() > lastGetTime + 60: lastGetTime = time.time() getTimeline() else: time.sleep(5)
twitterモジュール
api = twitter.Api(userName, passWord)
statuses = api.GetFriendsTimeline(userName)
で、認証してタイムライン(ここではFriendTimeline)を取ってくる。
んで、そのリストは時系列昇順にしゃべらせるために、スライスを使って逆順にし、forで回してやる。
osモジュール
os.system(‘”‘ + softalkPath + ‘” /V:60 /S:’+softalkSpeed+’ /T:1 /W:’ + convertString(i.user.name))
外部コマンドでSoftalkを実行する。softalkPathにsoftalk.exeの位置を設定して、あとはパラメータ。つぶやきの中に自分のユーザー名があったら音声を変えたり。
/V:ボリューム、/S:スピード、/T:音声パターン、/W:しゃべらせたいテキスト
Softalkのソフトについては後述。
nkfモジュール
NkfPython – Ma2
Softalkにコマンド引数として値を渡すときに、UnicodeからS-JISへ変換してやる必要があるんだけど、この変換でencode()を使うとウムラウトとかが原因でエラー。
nkfを使えばいいらしいので、nkf使って変換。
string = nkf.nkf(“-sX”, string.encode(“utf8”))
reモジュール
string = re.sub(‘&.+;’, ‘ ‘, string)
HTMLエンティティをそのまま渡すと、コマンド引数が途切れたりしたので、HTMLエンティティはばっさり消しちゃうことにした。re.sub()は正規表現で置き換え。
同様に、先頭に自分のユーザー名が来てるようなreplyメッセージでのユーザー名とか、クォート符号も消す。
他にも何かエラー引き起こす文字があったら、深く考えないで消す。とても適当でごめんなさい。
timeモジュール
実行したら無限ループに入れてやり、前回の取得時間より1分以上経っていたら取得しに行く、それ以外なら5秒スリープしてループの先頭に戻る。
利用するSoftalkのバージョン
実行してみると、Softalkが実行するときにいちいちWindowがピョコンとでてきて、終了をしてあげないと次のつぶやきをしゃべってくれない。
なんか以前と違うなぁって不思議に思っていたんだけど、
ニコニコ動画のニコ生(生で配信)用のツール
NicoRequest Ver.2.3.2 – ExceptionErrorMessage
NicoRequestのドキュメントを読んでみると、どうやらSoftalkの最新バージョンで挙動が変わったらしい。
ver0151に置き換えて実行してみたところ、ちゃんとうまくいって、一番はじめの動画のようにゆっくりボイスでしゃべってくれた。
感想
- 声でタイムラインを読んでくれるっていうのは新鮮でおもしろいよ
- Softalkは英語が不得意なので、無理にローマ字読みして何いってるかわからないことしばしば
- 移動体ライブ配信の読み上げに使おうとおもったけど、よく考えると60秒更新スパンくらいが負荷で限界なので、ものすっごくタイムラグ発生するかもね
- PythonよりもNicoRequestみたいにJavaScriptで実現したほうがいいかも
- SoftalkとそのライブラリAques TalkはWindows版でしか無償でつかえないので、環境を選ぶ
つぶやきを送ると、ゆっくりボイスで変換してくれるBOTとか作ったら面白そう。