はじめに
みなさん、こんにちは。
アイカツ!再放送が始まりましたね(見てない人は見ましょう!)。
せっかく1話から再放送始まるし、面白いこと出来ないかな〜と考えた結果、
1話から178話までの字幕をもとに文章自動生成するbotを作るアイデアを思いつきました。
話数を追うごとに成長していくアイカツ!のキャラのようにbotも成長して行くんですよ、面白くないですか!?
我ながら良いアイデアだと思います。
が、しかし、今回の再放送では字幕が付かないようで出鼻をくじかれました...
ということで、
字幕付きのアニメを片っ端から録画して字幕を抽出し文章自動生成botを作ることにしました。
アニメ見て日本語覚えたっていう外国の強いオタク良く見かけますよね。
これと同じことを文章自動生成botでやってみます。
概要
アニメの字幕データをもとに形態素解析マルコフ連鎖で文章自動生成をしてみました。
結果、こんな感じの文章が自動生成されました。
私も食べて寝るのがお前の身体機能を奪ってゆく。
ものやニャ。
おし!燃えてきたですね。
虹ノ咲さ〜ん。
鵺!
うん?
カメムシのにおいは仲間を集めるために…。
数が多すぎるよ。
ソラノお姉様がピッカピカになっちゃって…。
癒やしの効果が切れて元の島から逃げてってやるから!
位置について用意スタート!
ディアクラウンの店長さんがおりました内閣総理大臣より伝言です「わたしも監督の映画大すき!
あぁその…。
風呂場にまで感染の疑いが広がる。
ド…ドラえもん!
これにつかまるんじゃなかったし。
「もっとドキドキな?もっとフワフワな?」
あのね!
今日からモンスターになるかもな。こっちじゃ。アンアン!
いやいやいや!
環境
ubuntu 18.04 LTS / python 3.6.7
字幕抽出
こちらの記事(テレビ放送から諸々扱えそうなテキストを取得する - Qiita)の方法をそのまま使わせていただきました。
こんな感じのディレクトリ構造にして
~/workspace/
┣ assdumper/
┣ Videos/
┃ 録画した.tsファイルをすべてここに入れておく
┣ wakatigaki.txt
┗ ass2text.py
下記のコマンドで分かち書きデータを1ファイル(wakatigaki.txt)にまとめます。
cd ~/workspace
: > wakatigaki.txt
for file in `\find . -maxdepth 2 -name '*.ts'`; do
./assdumper/assdumper $file > tmp1.txt
python3 ass2text.py tmp1.txt > tmp2.txt
mecab -Owakati tmp2.txt >> wakatigaki.txt
rm tmp1.txt
rm tmp2.txt
done
こんな感じで分かち書きされます。
カラッ と ジュエル に キラ に ち は 〜 !
そこ に いる のに ここ に い ない !?
バーチャルプリ・チャンアイドル だい あ だ もん !
みんな ジュエル オーディション が 始まっ た の は もう 知っ てる よ ね ?
それ に 出る の に 必要 な の が う 〜 この ジュエルパクト だ もん !
みんな は もう 持っ てる か な ?
けど けど そ〜 ん な 大事 な もの を み らい ちゃんと ご っ つ ん こし て 落とし ちゃっ た 子 が いたん だ もん 。
み らい ちゃん は 落とし た 子 が 誰 だ か 知っ てる みたい だ けど … 。
さて さて み らい ちゃん どう する の ?
ドキドキ ワクワク キ 〜 ラキラ !
みんな の プリ・チャン 今日 も 元気 に オンエア ! だ もん 。
30分アニメ1本でだいたい15kByteくらいのデータ量になるようです。
マルコフ連鎖で文章自動生成
こちらの記事(マルコフ連鎖による文章生成)のコードを参考に少し手を加えました。
import random
#分かち書きデータの取得と前処理
filename = "wakatigaki.txt"
src = open( filename, "r" ).read()
wordlist = ( "_END _BEGIN " + src ).replace( "\n\n", "\n" ).replace( "\n", " _END _BEGIN ").split()
#マルコフ連鎖用のテーブルを生成
markov = {}
w1 = ""
w2 = ""
for word in wordlist :
if w1 and w2 :
if w2 != "_END":
if ( w1, w2 ) not in markov :
markov[ ( w1, w2 ) ] = []
markov[ ( w1, w2 ) ].append( word )
w1 , w2 = w2 ,word
#文章の自動生成
num_sentence = 20 #生成する行数
count_end = 0 #文末「_END」の数
sentence = ""
w1, w2 = "_END", "_BEGIN"
while count_end < num_sentence :
tmp = random.choice( markov[ ( w1, w2 ) ] )
if ( tmp == "_END" ) :
count_end += 1
sentence += '\n'
w1, w2 = "_END", "_BEGIN"
else :
sentence += tmp
w1, w2 = w2, tmp
print( sentence )
このファイルをworkspace直下に置いて実行します。
cd ~/workspace
python3 generate_text.py
よし!
キャ〜!
あれ?スマホから声が…キングコンブが…グレート・アリみたいにドロップ消したらええんニャ。
ひぃ〜っ!?
うう〜!
ここより楽しい場所なら行ってきてくれよ!
なんでも取り戻す!
そんな…
あの枯れた花に投げてみろ。
うう…。
違った。
ギャッなんニャ。
キャー!
ようすがおかしいのさ!
えっ!?タマには殺さぬぞ。
大丈夫だよ。
宇宙に輝くキラキラ星!キュアスター!
私が解決法を出して左足が沈む前に食べたくなった。
もう!
しんちゃん!次のバトルだってよ!
あとがき
字幕を使うと短文になりがちのようで微妙な結果になりました…。データ量が少ないせいか原文ママっぽい文章も目立ちます。
あとやり始めてから気づいたんですが、深夜アニメはほとんど字幕が付いてないようです(というかMXのアニメは全て字幕がついてない)。ということで、文章にキッズ向けアニメの雰囲気がどことなく漂っていますね。
今回は集まったデータがまだ300kByte程度しかないので、データ量が少なくてもそれっぽい文章になるマルコフ連鎖を使いましたが、ある程度データが集まってきたらLSTMでも試してみたいです。近いうちにtwitterbotも作れたらな〜と思っています。