ネイティブスピーカーなsaykanji作り
前回までのsaykanjiコマンドの能力は、漢字・仮名・英単語混じりの文章を辛うじて棒読みするレベルであった。はっきり言ってかなり不自然だ。言葉のもつアクセントはすべて無視されている。まるで、お経を読み上げるような感じ。
saykanaコマンドの性能を引き出すべく、より自然な日本語での読み上げを目指してみた!
関連ページ
- プロジェクトコード
数字の読み上げ
- 数字をNUMKタグに変換することにした。
- COUNTER属性を利用するため、助数詞辞書を作成した。
- これで「10分」が「じゅっぷん」と発音される。(今までは「いちぜろふん」だった)
アクセントの付与
- アクセント付きの読みに変換するため、発音辞書を作成した。
- 項目は「"原文","発音"」の2項目のみ。
- 発音は、AquesTalk音声記号列仕様書の書き方
"Rails","れ'いるず" "準備","じゅ'んび" "今度","こ'んど" "もう少し","もうすこ'し" "アクセント","あ'_クせんと" "(","、か'っこ、" ")","、か'っこ/とじ'る、" ...
カタカナ語のアクセントのルール
- カタカナ語の後ろから3拍目がアクセントになるルールを適用した。
コンピュ'ータ キーボ'ード スクリ'プト
-
- NADのカタカナ英語辞書の結果を変換する場合のコード
REG_HIRA="(.*[^っー])([っー]?)([^ぁぃぅぇぉゃゅょ][ぁぃぅぇぉゃゅょ]?[^ぁぃぅぇぉゃゅょ][ぁぃぅぇぉゃゅょ]?)$" add_accent_to() { ruby -e "require 'jcode';\$KCODE='u';print('$1'.sub(/$REG_HIRA/, '\1\'\2\3'));" }
-
- 上記辞書にヒットしないカタカナ語を変換する場合のコード
REG_KATA="(.*[^ッー])([ッー]?)([^ァィゥェォャュョ][ァィゥェォャュョ]?[^ァィゥェォャュョ][ァィゥェォャュョ]?)$" add_accent_to_if_need() { ruby -e "require 'jcode';\$KCODE='u';print('$1'.sub(/$REG_KATA/, '\1\'\2\3')) if /[ァ-ンー]{3,}/=~'$1';" }
カタカナ → ひらがな変換
- 発音情報を全てひらがなで(saykanaに)渡した方が発音が良くなる(良きに計らってくれる)ようなので、ひらがなに変換した。
kata_to_hira() { ruby -e "require 'jcode';\$KCODE='u';print('$1'.tr('ァ-ン', 'ぁ-ん'));" }
アクセントと区切り
- アクセントは「/」で区切る文節に1つだけ設定する必要がある。
- もし、一文節に二つ以上のアクセントがあっても、最後のアクセントしか有効にならない。
- アクセントを利用するためには、必然的に文章をいくつもの「/」で区切ることになる。
$ <span style="font-weight:bold;">echo "日本語を話そう"|mecab -O wakati</span> 日本語 を 話そ う
- ところが、自然な日本語で発音するためには、主要な品詞 + 助詞類を含めた、意味の通じる単位に区切る必要がある。
にほんごを/はなそ'う
- 最適な区切りを導き出すために、mecabコマンドはオプション無しで実行して、品詞等の詳細情報も利用することにした。
$ <span style="font-weight:bold;">echo "日本語を話そう"|mecab</span> 日本語 名詞,一般,*,*,*,*,日本語,ニホンゴ,ニホンゴ を 助詞,格助詞,一般,*,*,*,を,ヲ,ヲ 話そ 動詞,自立,*,*,五段・サ行,未然ウ接続,話す,ハナソ,ハナソ う 助動詞,*,*,*,不変化型,基本形,う,ウ,ウ EOS
区切りの基本方針
- 基本的に、助詞または助動詞で区切る。
- アクセントがない場合は、無駄に区切らない。
- 助詞、助動詞以外でもアクセントが連続する場合は区切る。
名詞が連続する場合の取り扱い
- 名詞は連続すると、アクセントが後ろの単語の最初に変化する場合が多い。
速度(そ'くど) + 制限(せいげ'ん) = 速度制限(そくどせ'いげん)
- よって、名詞が連続する場合は、例えアクセントが連続しても区切らない。
- アクセントが連続した場合、後ろのアクセントが有効になるので、結果OK。
そくどせ'いげん = そ'くどせ'いげん
以上を踏まえたコードは...
- 名詞が連続しない時だけ区切る処理(=名詞が連続する時は区切らない処理)
add_kugiri_if_need() { if [ "$kind_stock" = '名詞,副詞可能,*,*' -o "$hinsi_stock" != '名詞' -o "$hinsi" != '名詞' ] then res="$res$kugiri" fi }
- 後に続く単語のアクセントを再設定する処理
reset_top_accent_if_need() { if [ "$kind_stock" != '名詞,副詞可能,*,*' -a "$hinsi_stock" = '名詞' -a "$hinsi" = '名詞' ] then ruby -e "require 'jcode';\$KCODE='u';print(\"$1\".gsub(/\'/, '').sub(/^(.)(.*)/, '\1\'\2'));" fi }
連続する助詞・助動詞の取り扱い
- 助詞、助動詞にもアクセントが必要なときがある。
- 多くの助詞は1文字であることが多い。
- アクセントは助詞、助動詞が連続する時に発生する。
そこで、連続する助詞は一つのフレーズとして扱うことにした。
- 助詞は、発音情報と関係ない( )で囲うことにした。
- 以下の例では、(なので) が連続したフレーズとして扱われている。
$ saykanji "シンプルなスクリプトなので、" 記号,空白,*,*,*,*, , , シンプル 名詞,形容動詞語幹,*,*,*,*,シンプル,シンプル,シンプル な 助動詞,*,*,*,特殊・ダ,体言接続,だ,ナ,ナ スクリプト 名詞,一般,*,*,*,*,スクリプト,スクリプト,スクリプト な 助動詞,*,*,*,特殊・ダ,体言接続,だ,ナ,ナ ので 助詞,接続助詞,*,*,*,*,ので,ノデ,ノデ 、 記号,読点,*,*,*,*,、,、,、 EOS し'んぷる(な)/すくり'ぷと/(な'ので)、
- もし、フレーズとして扱わないと、アクセント無しの"しんぷる「な」"と区別できなくて困る。
動詞,非自立,*,*の取り扱い
- 動詞の中でも「動詞,非自立,*,*」で区別される品詞は、助動詞のような性格と感じた。
そこで、上記については助詞、助動詞と同等に扱うことにした。
句読点での区切りの取り扱い
- 句読点「、。」= 区切り「/」+ ポーズ(無音の待機時間)である。
- 句読点の手前に区切りが入ると、直前の音声が途切れてしまう。
そこで、句読点の手前では区切りは不要なので、強制的に排除することにした。
同字・同音、ところが異アクセントな場合
- 発音辞書は、原文と発音のcsvファイル。
- アクセントは「'」で設定する。
"理解","り'かい"
- 原文は漢字、ひらがな、カタカナ、英語の可能性がある。
- 漢字の場合、複数の読みを持っている可能性がある。
- 同じ漢字を区別する必要がある場合は、以下のように原文を「|」で区切って「読み」を続けることにした。
"中|ちゅう","ちゅう" "中|なか","な'か"
- 同じ漢字かつ同じ読みだが、アクセントが異なる場合がある。
- 原文を「|」で区切って「品詞名」を続けることにした。
今の気持ち "今|名詞","い'ま'" 今はやり "今|接頭詞","いま''"
AppleScriptとシェルスクリプトと日本語の正規表現について
ruby -e "\$KCODE=..."
`ruby -e "\\\$KCODE=..."`
saykanjiが返す情報
$ saykanji "あと30分はかかりそうです。" 記号,空白,*,*,*,*, , , あと 名詞,一般,*,*,*,*,あと,アト,アト 30 名詞,数,*,*,*,*,* 分 名詞,接尾,助数詞,*,*,*,分,フン,フン は 助詞,係助詞,*,*,*,*,は,ハ,ワ かかり 動詞,自立,*,*,五段・ラ行,連用形,かかる,カカリ,カカリ そう 名詞,接尾,助動詞語幹,*,*,*,そう,ソウ,ソー です 助動詞,*,*,*,特殊・デス,基本形,です,デス,デス 。 記号,句点,*,*,*,*,。,。,。 EOS あ'と/(わ)/かかりそ'う(です)。
$ saykanji "速度と制限で速度制限。"
記号,空白,*,*,*,*, , ,
速度 名詞,一般,*,*,*,*,速度,ソクド,ソクド
と 助詞,格助詞,一般,*,*,*,と,ト,ト
制限 名詞,サ変接続,*,*,*,*,制限,セイゲン,セイゲン
で 助詞,格助詞,一般,*,*,*,で,デ,デ
速度 名詞,一般,*,*,*,*,速度,ソクド,ソクド
制限 名詞,サ変接続,*,*,*,*,制限,セイゲン,セイゲン
。 記号,句点,*,*,*,*,。,。,。
EOS
そ'くど(と)/せいげ'ん(で)/そ'くどせ'いげん。
上記情報をもとに、不足している情報を発音辞書に追加して行けば、いつかは流暢な日本語で読み上げてくれるのではないかと期待している。
所感
参考ページと目標
やってる途中で、日本語のスーパーネイティブスピーカーを見つけた!
目指すレベルはここだけど、かなりレベルが高い。ちょっと無理そう...。
以下のページが大変参考になりました。感謝です!
- bash
- #085 正規表現の落とし穴
- シェルスクリプト入門 (サンプルスクリプト集)
- Oracle Technology Network (OTN) Japan - 掲示板 : シェルの戻り値 ...
- (linux-users:96156) (bash)whileループ内変数値の扱いについて教えてください。
- シェルの変数に慣れる
- if 文と test コマンド - UNIX & Linux コマンド・シェルスクリプト リファレンス
- case 文の使用方法 - UNIX & Linux コマンド・シェルスクリプト リファレンス
- AWK リファレンス - UNIX & Linux コマンド・シェルスクリプト リファレンス