表記に対して、読みがなだけあって音声表記がないときに何とかする
タイトルのような状況を、主に音声関係の人のツイートで見かける。
読みがな・音声表記の変換は、"ou"->"o:"のような単純な処理をすると、「子牛」が「コーシ」になってしまったりして悲しいことになる。
そこで、自分は音声関係ではないのだが、Perl と MeCab でなんとかする方法を考えてみた。
perl -CSD -Mutf8 -F/\\t/ -nale 'BEGIN{$max=20;}@results=`echo $F[0] | mecab -N$max`;$processed=$simple=$no_daku=$F[1]; @yomi=@pron=();$i=0; $unknown_flag=0; $is_ok=0; $a_dan="[アカサタナハマヤラワガザダバパァャ]";$i_dan="[イキシチニヒミリギジヂビピィ]";$u_dan="[ウクスツヌフムユルグズヅブプゥュ]";$e_dan="[エケセテネヘメレゲゼデベペェ";$o_dan="[オコソトノホモヨロヲゴゾドボポォョ]"; if ($simple!~s/((?<=${a_dan})ア|(?<=${i_dan})イ|(?<=${u_dan})ウ|(?<=${e_dan})エ|(?<=${o_dan})[ウオ])/ー/g) { $is_ok=1; } else { for (@results) {chop;++$i,next if /^EOS/; /\*,\*$/?(/(^\p{Katakana}+)/ or $unknown_flag=1):/([^,]+),([^,]+)$/; next if $unknown_flag; $yomi[$i].=$1;$pron[$i].=$2||$1;} map{tr/ガギグゲゴザジズゼゾダヂヅデドバビブベボパピプペポ/カキクケコサシスセソタチツテトハヒフヘホハヒフヘホ/}@yomi,@pron,$no_daku;$matched_pron=""; for $i(0..$max) { if ($no_daku eq $yomi[$i]) { $matched_pron=$pron[$i]; last;}} if ($matched_pron) { for $i(1..length($processed)) { substr($processed,$i,1,"ー") if substr($matched_pron,$i,1) eq "ー";} } } $processed=~tr/ヂヅヲ/ジズオ/; $simple=~tr/ヂヅヲ/ジズオ/; $processed=~s/(?<=$a_dan)ァ|(?<=$i_dan)ィ|(?<=$u_dan)ゥ|(?<=$e_dan)ェ|(?<=$o_dan)ォ/ー/g; print "$F[0]\t$F[1]\t".(($is_ok || $matched_pron) ? $processed:"-".$simple);' < input.txt
input.txt には次のような内容を用意。
夫婦茶碗 メオトヂャワン 塩豆腐 シオドウフ 21世紀 ニジュウイッセイキ テザリング機能 テザリングキノウ 待宵草 マツヨイグサ 文科省 モンカショウ 子牛 コウシ 中央揃え チュウオウゾロエ 大江戸線 オオエドセン
出力は、次のようになる。
夫婦茶碗 メオトヂャワン メオトジャワン 塩豆腐 シオドウフ シオドーフ 21世紀 ニジュウイッセイキ -ニジューイッセイキ テザリング機能 テザリングキノウ テザリングキノー 待宵草 マツヨイグサ マツヨイグサ 文科省 モンカショウ モンカショー 子牛 コウシ コウシ 中央揃え チュウオウゾロエ チューオーゾロエ 大江戸線 オオエドセン オーエドセン
3列目が "-" になっているものは単純な変換なのでチェックが必要。
仕組みは、次の通り。
まず、長音の可能性が(「ネエ」「コウ」など)がなければ、次のブロックを飛ばす。
表記を MeCab に渡し、20-best (数は適当)で解析結果を受け取る。
その中で、読みがなが元ファイルの読みがなと一致するものを探す。
この時、濁点は無視して比較する。
MeCab は連濁処理に弱いところがあり、例えば「中央揃え」の N-best をどこまで取っても「チュウオウゾロエ」は見つからないからだ。
一致するものがあれば、それに対応する発音表記を取得。
しかし、これはそのままでは使えない。
「チュウオウソロエ」に対応する発音表記は、もちろん「チューオーソロエ」であり、望む「チューオーゾロエ」にはなってくれないからだ。そこで、元の読みをベースにする。
そもそも、音声表記への変換で一番の難所は長音(ー)だ。
元の読みの中で、取得した発音表記が「ー」になっている位置の文字を、同じく「ー」で置き換える。
元の読みの「ヂ」「ヅ」「ヲ」はそのまま残っているので、それを単純置換で「ジ」「ズ」「オ」にする。
「カァ」→「カー」などの置換を行う。
以上。
「21世紀」のように数字が入っているものは、MeCab で読めないので仕方がない。
「待宵草」は、「待:マツ」のペアが入っていないので、本来MeCabでは読めないところだが、長音の可能性がないのでそのまま出している。
失敗するものは多くないと思う。
いろいろテストした。
可読性の非常に悪いワンライナーだが、使い所はあると思うので、よかったら使ってみていただければと。
(追記1)実際はこんなに簡単な話ではないようだ。恥ずかしいけど自戒をこめてこのままにしておく。
(追記2)長音の可能性がなければ処理を飛ばすようにした。
(追記3)変換に失敗にした時、単純な置換にフォールバックするようにした。