玩式草子─ソフトウェアとたわむれる日々

第64回 お家通信カラオケシステムを作ろう[その3]

この記事を読むのに必要な時間:およそ 7 分

前回,通信カラオケ用の検索システムを作るために,VHDディスクから拾った楽曲リストの曲名と歌手名にひらがなの読みを追加する作業について紹介しました。今回は,そうやって作った楽曲リストをデータベースに登録して,実際に動作する通信カラオケシステムを作ってみます。

楽曲リストの校正

前回紹介したように,まずはkakasiを使って楽曲リストの曲名と歌手名にひらがなの読みを付けてみました。

kakasiは,SKKプロジェクトが蓄積した辞書ファイル(ひらがなと漢字の対応リスト)を元に,漢字からひらがなの読みを引けるデータベースをあらかじめ用意しておき,与えられた漢字かな混り文をこのデータベースと照合して,マッチする単語があればその読みを返す,という単純な仕組みになっています。

この変換方法はシンプルではあるものの,データベースに登録されている単語の有無によって読みが左右されるという問題があります。たとえば「中島みゆき」という歌手名をkakasiでひらがなに変換すると,⁠なかしまみゆき」になってしまいます。

$ echo '中島みゆき' | kakasi -JH
なかしまみゆき

この誤変換はkakasiが使っているデータベースに「中島」「なかじま」と読ませる読みが登録されていないことが原因です。⁠中島」が無いため,⁠中島」「中」「島」に分解され,⁠なか」⁠しま」という読みが返されるため,⁠なかしまみゆき」になってしまいます。

この問題は,kakasiが利用するデータベースに「中島:なかじま」という読みを登録してやれば解決するものの,データベースに新しい読みを追加するためには,元となった辞書ファイルに必要な読みを追加した上でmkkanwadictコマンドを使ってkakasi用のデータベースを再生成する必要があって,ちょっと面倒です。

そのため人名やグループ名のような固有名詞にはkakasiを使わず,自前で読みを振るような機能を追加してみました。

  1 # -*- coding: euc-jp -*-;
  2 
  3 def set_namedict():
  4     namedict = {
  5         'ANN':'あん',
  6         'ASKA':'あすか',
  7         "B'Z":'びーず',
  8         'BE-B':'びーび',
... 
110         '梶芽衣子':'かじめいこ',
111         '米米CLUB':'こめこめくらぶ',
112         '千昌夫':'せんまさお',
113         }
114 

"ANN"や"ASKA"といった英語表記の歌手名にはそれぞれひらがなの読みを対応させると共に,誤変換が目についた「梶芽衣子」「千昌夫」といった人名にもそれぞれ適切な読みを対応させています。

kakasiがデフォルトで利用している小規模な辞書ファイルには人名等の固有名詞があまり登録されていないため,⁠梶芽衣子」「かじめころもこ」⁠千昌夫は「ちあきおっと」と変換されてました(笑)⁠SKKにはこれら固有名詞も多数収録している大規模な辞書ファイルも用意されているものの,それを用いたところで"B'z"とか"Dreams Come True"といったアルファベット表記には対応できないので,上記のような「人名リスト」をスクリプトレベルで用意することにしたわけです。

やっていることは簡単で,まずは上記のようなset_namedict()関数を用意して,namedict{}に表記と読みの対応リストを登録していきます。

そして,前回紹介したスクリプトで歌手名にふりがなを付ける際,namedict{}にある名前にはkakasiからではなく,対応リストから得られる読みを使うようにしました。

50        singer2 = singer.upper()
51        
52        if namedict.has_key(singer2):
53            singer_yomi = namedict[singer2]
54        else:
55            singer_yomi = to_hiragana(singer2)

なお,曲目リストに記録した歌手名のアルファベット表記には大文字と小文字の表記揺れがあったので,揺れを吸収するために歌手名はいったん大文字に統一して(50行め)⁠その上でname_dict{}を引くようにしています。

目につくアルファベット表記や誤変換をnamedict{}に登録してはスクリプトを再実行する,という作業を繰り返して,機械的にひらがなの読みを付けた楽曲リストは完成しました。

  1-1-01 | 愛しつづけるボレロ | あいしつづけるぼれろ | 五木ひろし  | いつきひろし        | 阿久悠              | 筒美京平             |
  1-1-02 | 会津の小鉄         | あいづのこてつ       | 京山幸枝若 | きょうやまこうしわか | 松島一夫            | 和田香苗             |
  1-1-03 | 勘太郎月夜唄       | かんたろうつきようた | 小畑実     | おばたみのる         | 佐伯孝夫            | 清水保雄             |
  1-1-04 | 青葉城恋唄         | あおばじょうこいうた | さとう宗幸 | さとうむねゆき       | 星間船一            | さとうむねゆき
  ...

歌手名は複数回出てくる可能性があるのでスクリプトレベルで対応した方がいいものの,タイトルの当て字読みやアルファベット表記はたいてい1回限りしか出てこないので,namedict{}に登録して直すよりも出力結果を直接修正する方が楽でしょう。そう考えて,楽曲リストをさらに手動で直していくことにしました。

  ...
  8175-2-01 | 名もなき詩(うた) | めいもなきし(うた) | Mr.Children  | みすたーちるどれん | 桜井和寿 | 桜井和寿 
  8175-2-02 | FOREVER           | FOREVER             | 岡本真夜     | おかもとまよ       | 岡本真夜 | 岡本真夜 
  8175-2-02 | river             | river               | CHAGE&ASKA  | ちゃげあんどあすか | 飛鳥涼   | 飛鳥涼 
  8175-2-04 | 幸せになりたい     | しあわせになりたい   | 内田有紀     | うちだゆき         | 広瀬香美 | 広瀬香美 
  ...

「ああ,この頃はバンドブームだったなぁ…」⁠この頃は小室哲也の絶頂期だっけ…」などと追憶にふけりつつ,⁠めいもなきし(うた)⁠「なもなきうた」に直したり,"Forever"に「ふぉーればー」と読みを付けたりする退屈な作業を進めました。

データベースの構築

ひらがな読みを付けた楽曲リストの修正を一通り終えてから,このリストをSQLite3のデータベースに登録するためのPythonスクリプトを書きました。

 1 # -*- coding: euc-jp -*-;
 2 
 3 import sqlite3, os, sys
 4 
 5 def init_db(dbname):
 6     conn = sqlite3.connect(dbname)
 7     conn.isolation_level = None
 8     cursor = conn.cursor()
 9     cursor.execute('''create table titles
10        (id text, title text, title_yomi text, singer text, singer_yomi text, songwriter, composer)''')
11     return conn
12 
13 def insert_db(cursor, t):
14     try:
15         # print "inserting ", t
16         cursor.execute('insert into titles values(?, ?, ?, ?, ?, ?, ?)', t)
17     except sqlite3.Error, e:
18         print "An error occurred:", e.args[0]
19 
20 def main():
21     dbname = 'karaoke-titles.sql'
22 
23     if os.path.isfile(dbname) == False:
24         connection = init_db(dbname)
25     else:
26         connection = sqlite3.connect(dbname)
27     cursor = connection.cursor()
28 
29     datafile = 'karaoke-yomi.dat'
30     if os.path.isfile(datafile):
31         f = open(datafile, 'r')
32         lines = f.readlines()
33         for line in lines:
34             dt = line.split(" | ")
35             if len(dt) != 7:
36                 print("Data count {} error at {}:".format(len(dt), line))
37                 continue
38                 
39             id          = dt[0]
40             title       = dt[1].decode('euc-jp')
41             title_yomi  = dt[2].decode('euc-jp')
42             singer      = dt[3].decode('euc-jp')
43             singer_yomi = dt[4].decode('euc-jp')
44             songwriter  = dt[5].decode('euc-jp')
45             composer    = dt[6].decode('euc-jp')
46 
47             insert_db(cursor, (id, title, title_yomi, singer, singer_yomi, songwriter, composer))
48 
49 if __name__ == "__main__":
50     main()

このスクリプトでは,1行に7つのテキスト形式のコラムを持つSQLite3形式のデータベース("karaoke-titles.sql")を作り,そこにひらがなの読みをつけた楽曲リスト("karaoke-yomi.dat")のデータを流し込んでいます。これくらいの処理ならスクリプトを書くまでもないかな,とも思いましたが,データに修正が必要な場合は楽曲リストに戻って修正し,データベースも再生成することになるので,スクリプト化しておく方が作業をくりかえすには楽でしょう。

スクリプトを使って作成したデータベースを確認するために,シェルからsqlite3コマンドを使って操作してみます。なお,SQLite3の扱うテキストデータはUTF-8形式なので,端末ソフトの文字コードもUTF-8に変更しています。

 $ sqlite3 karaoke-titles.sql 
 SQLite version 3.8.5 2014-06-04 14:06:34
 Enter ".help" for usage hints.
 sqlite> select id,title,singer from titles where singer_yomi like "なか%";
    14-2-11|かもめはかもめ      |中島みゆき          
    20-2-02|秋冬                |中山丈二            
    23-2-06|悪女                |中島みゆき          
    26-1-09|ひとり              |中島みゆき          
   305-2-10|十戒(1984)          |中森明菜            
 ...
  8222-1-04|鳶                  |中村美律子          
     9-2-03|船頭小唄            |中山歌子

ざっと見,データベースは正しく作成できているようなので,Web経由でこのデータベースを利用するためのコードを書く段階に移りました。

著者プロフィール

こじまみつひろ

Plamo Linuxとりまとめ役。もともとは人類学的にハッカー文化を研究しようとしていたものの,いつの間にかミイラ取りがミイラになってOSSの世界にどっぷりと漬かってしまいました。最近は田舎に隠棲して半農半自営な生活をしながらソフトウェアと戯れています。

URLhttp://www.linet.gr.jp/~kojima/Plamo/index.html

コメント

コメントの記入