2012年05月01日

Open JTalk を Windows でビルドするバッチファイル

前回、hts_engine_API の最新バージョンを間違えてしまったので、書き換えたものを作ろうとしたのですが、折角なのでバッチファイルの内部でバージョン番号を書き換えないでいいものを作ったほうが便利そうだったので、そうしてみました。

さらに、以前ソルーションファイルを作って、VC++を起動してビルドできるようにしていましたが、そのファイルも今回の成果をいろいろ追加して入れてみました。VC++2008用ですが、2010で開けば自動的に変換するので利用できます。

ojtalk.bat の仕様も変えて、他の音声に切り替えやすいようにしてみました。あとで説明しますが、音響モデルのフォルダに省略時のパラメータを書いたテキストがあれば、それを使うようにしています。

 

■ ビルド方法

open_jtalk.exe のビルドには、Visual Studio C++ 2010Visual Studio C++ 2008 のどちらかが必要です。2010Express 版でもいいはずです。それからファイルの解凍のために 7zip か tar が必要です。

ファイルは次のリンクからダウンロードします。

openjtalk_buildbatch-003.zip

展開して、そのフォルダに、Open JTalkのビルドに必要な3つのアーカイブを入れます。リンク先から最新版をダウンロードしてください。
open_jtalk-*
hts_voice_nitech_jp_atr503_m001-*
hts_engine_API-*

最初に、prepare.bat を実行します。すると、アーカイブを展開し、インストール先(標準設定でc:\open_jtalk)に、この時点で転送できるファイルを全て転送してくれます。

prepare.bat で準備がすんだら、make.bat を実行します。すると、各フォルダーの Makefile.mak の手順に従い open_jtalk.exe を生成し、インストール先のbinフォルダーに転送します。これで終わりです。

ちゃんと動くかどうかは、インストール先にある ojtalk.bat をダブルクリックして実行すれば確かめられます。「open jtalk」としゃべってくれれば、とりあえずOKです。一度ojtalk.bat を実行すると、インストール先に text.txt が作られるので、このファイルに文章を書き込み、その都度、ojtalk.bat をダブルクリックすると、その内容を読み上げてくれるはずです。

 

■ ソルーションファイル

make.bat を使えば、十分なのですが、open_jtalk\open_jtalk の中にある open_jtalk.sln を使うと、Visual Studio の画面を開いて、ビルドできます。ただし、通常は、ソルーション構成は Release か Debug、ソルーションプラットフォームは Win32 にしてください。必要ないとは思いますが、他の設定を利用するには、prepare.bat の実行前に、 build.info を編集しておく必要があります。

なお、Visual Studio を通して辞書をコンパイルすると相当時間がかかります。気長に待ってください。

 

■ 利用例

今回付属してある ojtalk.bat では、インストール先のvoiceフォルダ(デフォルトだとc:\open_jtalk\voice)に音響モデルのファイルをフォルダごと入れるようにしています。さらにその中に voice.info というファイルがあれば、省略時の -s、-p、-a、-g、-b、-u、-z、-jm、-jf、-jl の値があるとします。mei の利用の仕方は以前紹介しましたが、例えば、フォルダ mei_normal の中に、次の内容の voice.info を入れておきます。

s=48000
z=6000
p=240
a=0.55
jm=0.7
jf=0.5
jl=1.0

音響モデルの指定を –vname でできるようにしたので、次のコマンドで Mei が挨拶します。

ojtalk.bat –vname mei_normal こんにちは

さらに、Windows スクリプティングホスト(wsf) を使うと次のようなこともできます。

<job id="time">
<script language="JScript">
d = new Date();
m = d.getMinutes();
m = (m=="0")?"ちょうど":m+"分";
WScript.CreateObject("WScript.Shell").Run("c:\\open_jtalk\\ojtalk.bat -vname mei_normal "+d.getHours()+"時"+m+"です。",0,true);
</script>
</job>

このような内容の time.wsf というファイルを作って、ダブルクリックすると、時報を伝えてくれます。

さらに、これをインストールしたフォルダに入れておいて、デスクトップにショートカットを作ります。ショートカットを作ると、そのプロパティを開いてショートカットキーも登録できるようになります。例えば、それをCTRL+ALT+Tなどとすると、このショートカットキーがかぶらなければ、このキー操作でいつでも時刻を教えてくれます。またこのスクリプトを、タスクスケジューラに登録して、繰り返し間隔などを設定すれば、定期的に現在時刻を教えてくれるようになります。

 

■ ちょっと複雑な設定

普通に使うならば、上に書いた方法で十分ですが、make.bat でテキストの文字セットを UTF-8 や EUC-JP にしたり、x64向けのビルドをする場合は、build.info を書き換えればできるように作っています。ソルーションファイルを使う場合も同じです。

自動でパッチを当てるときは、パッチを当てるかどうかを「=」の右に文字があるかないかで判断しています。ただこの build.info についての説明はあまり必要ないだろうし、説明も長くなるので割愛します。

 

■ patch コマンドの導入

今回の修正程度ならば、手作業の方が手っ取り早いですが、一応 patch コマンドの導入方法も書いておきます。MinGW/MSYS を利用する方法です。次のサイトから、mingw-get-inst-*.exe という名前のインストーラをダウンロードしてきて実行します。(現時点の最新版は mingw-get-inst-20120426.exe)

MinGW - Minimalist GNU for Windows -  Browse Files at SourceForge.net 

インストール場所は標準のC:\MinGWにします。今回の利用だけならば、コンポーネントは何も選択しなくてもいいです。インストーラの使い方が分からないときは、こちらのサイトに詳しく書いてあります。Windows で MinGW バージョン 20110530 のインストールとテスト実行

インストールが終わったら、次のコマンドを、コマンドプロンプトを開いて実行します。

cd c:\MinGW\bin
mingw-get install msys-patch

これで導入完了。この場所にあれば、PATH を通さなくても、今回のバッチファイルでは patch が実行されるようにしています。ついでに、折角調べたので忘れないように書いておくと tar コマンドは「mingw-get install msys-tar-bin」で入ります。

なお、このように patch コマンドを導入しても、現在のバージョンに対応したパッチが用意されていないと自動でパッチは適用されません。今回用意しているのは、open_jtalk-1.05、hts_engine_API-1.06 向けのパッチです。



posted by takayan at 00:38 | Comment(8) | TrackBack(0) | 音声合成 | このブログの読者になる | 更新情報をチェックする

2012年05月02日

「カーネーション」の総集編は5月3日、4日

見たいのに気付いていない人もいるかもしれないので。

カーネーションの総集編が、NHKの「大型連休」中にあります。

連続テレビ小説「カーネーション」総集編 前編「あこがれ」
チャンネル     :総合
放送日     :2012年 5月 3日(木)
放送時間     :午前8:20〜午前9:51(91分)

連続テレビ小説「カーネーション」総集編 後編「あなたの愛は生きています」
チャンネル     :総合
放送日     :2012年 5月 4日(金)
放送時間     :午前8:20〜午前9:51(91分)

ちなみに、サブタイトルはそれぞれ第一週と最終週と同じ

尾野さんの別の顔が見られます!ということで、尾野真千子が出ている「外事警察」の特別編集版もあります。
放送日時:5月4日(金) 午前0:25〜1:54<3日深夜>

ソース:http://www.nhk.or.jp/drama/sp_201205/

 

それから、朝ドラ恒例の「梅ちゃん先生」の開始1ヶ月ダイジェストが総合とBSプレミアムであります。

まだまだ間に合う!「梅ちゃん先生」
○5/3(木)午後5:30〜5:59【総合】
○5/4(金)午後10:30〜10:59【BSプレミアム】

ソース:http://www9.nhk.or.jp/umechan/rel/index.html#rel01

十分間に合います。



posted by takayan at 02:00 | Comment(0) | TrackBack(0) | 映画・ドラマ | このブログの読者になる | 更新情報をチェックする

2012年05月09日

Open JTalk を利用する日本語読み上げ bash スクリプト

先日、Windows 用にバッチファイル ojtalk.bat を作ってみましたが、今度は似たような内容で Linux 用に bash スクリプトを作ってみました。対象は Ubuntu 12.04 と MinGW です。それ以外の場合は、実際にインストールされている場所に DICDIR と VDIRBASE の値を書き換えれば、おそらく動くでしょう。このスクリプトを /usr/local/bin あたりにコピーして使います。

Ubuntu 12.04 では、open-jtalk、open-jtalk-mecab-naist-jdic、hts-voice-nitech-jp-atr503-m001が apt-get や Ubuntuソフトウェアセンターでインストールできるので、それでインストールされているとします。

このスクリプトでは読み上げ文字列の指定は三種類あります。

まず、ちょっとした言葉はコマンドラインに書きます。

ojtalk こんにちは
長い文章の時は、ファイルに utf-8 エンコードで保存して -f オプションで指定します。
ojtalk -f hoge.txt
標準入力を読ませたいときは、文字を付けない '-' をコマンドラインに置きます。
cat hoge.txt|ojtalk -
上記の読み上げ文字列の指定が複数あるときは、左から順に処理します。ただし文字列の合計の長さは bash の限界までです。

その他に、音声ファイルを作るときは、-ow hoge.wav とします。このとき、しゃべらせたくないときは、-quiet も一緒に指定します。hts-voice フォルダに他の音声データが入っているときは -vname mei_normal といった感じで音声を替えられます。このとき、その中に voice.info ファイルが入っていると、その情報を参照します。

さて、以前からの課題である GNOME orca の日本語化の件ですが、この bash スクリプトを使えば、python から次の形で呼び出せますから、以前よりシンプルに作れると思います。

os.system(u'ojtalk こんにちは'.encode('utf8'))

まず、このスクリプトを利用したものを作ってから、そのあとで Speech Dispatcher 経由のものを考えることにします。

以下、ojtalk ソース:

#!/bin/bash

if [ `uname|grep "MINGW"` ]; then
	DICDIR=/usr/local/dic
	VDIRBASE=/usr/local/hts-voice
	DEFAULT_VOICE_NAME=hts_voice_nitech_jp_atr503_m001
	mingw=1
else
	DICDIR=/var/lib/mecab/dic/open-jtalk/naist-jdic
	VDIRBASE=/usr/share/hts-voice
	DEFAULT_VOICE_NAME=nitech-jp-atr503-m001
	mingw=0
fi

# default parameters
MESSAGE='open jtalk'
S=48000
P=240
A=0.55
G=0
B=0.0
U=0.5
Z=1600
JM=1.0
JF=1.0
JL=1.0
MEI_S=48000
MEI_P=240
MEI_A=0.55
MEI_G=0
MEI_B=0.0
MEI_U=0.5
MEI_Z=6000
MEI_JM=0.7
MEI_JF=0.5
MEI_JL=1.0

if [ $mingw == 1 ]; then
	CURDIR=`dirname $0`
	TEMPTXTFILE=$CURDIR/_text.txt
	TEMPWAVFILE=$CURDIR/_wave.wav
else
	TEMPTXTFILE=$(mktemp /tmp/ojtalk_txt_XXXXXXXX)
	TEMPWAVFILE=$(mktemp /tmp/ojtalk_wav_XXXXXXXX)
fi

L_SWITCH=
QUIET_SWITCH=0
VNAME_VALUE=
VDIR_VALUE=
S_VALUE=
P_VALUE=
A_VALUE=
G_VALUE=
B_VALUE=
U_VALUE=
Z_VALUE=
JM_VALUE=
JF_VALUE=
JL_VALUE=
OT_VALUE=/dev/null
OW_VALUE=
TEXT=

error(){
	cmd=`basename $0`
	message="Bad parameter!"
	if [ "$1" ]; then message=$1; fi
	echo "$cmd: $message";
	exit 1;
}

if [ ! -d $DICDIR ]; then
	error "No dic directory : $DICDIR"
fi

if [ ! -d $VDIRBASE ]; then
	error "No voice directory : $VDIRBASE"
fi

while [ $1 ]; do
	if [ $1 == -l ]; then
		L_SWITCH=-l
	elif [ $1 == - ]; then
		data=$(tr '\n\r' '  ')
		TEXT="$TEXT $data"
	elif [ $1 == -vname ]; then
		shift
		if [ ! $1 ]; then error; fi
		VNAME_VALUE=$1
	elif [ $1 == -vdir ]; then
		shift
		if [ ! $1 ]; then error; fi
		VDIR_VALUE=$1
	elif [ $1 == -quiet ]; then
		QUIET_SWITCH=1
	elif [ $1 == -f ]; then
		shift
		if [ ! $1 ]; then error; fi
		if [ -f $1 ]; then
			data=$(cat $1|tr '\n\r' '  ')
			TEXT="$TEXT $data"
		else
			error "No text file: $1"
		fi

	elif [ $1 == -ow ]; then
		shift
		if [ ! $1 ]; then error; fi
		OW_VALUE=$1
	elif [ $1 == -ot ]; then
		shift
		if [ ! $1 ]; then error; fi
		OT_VALUE=$1
	elif [ $1 == -s ]; then
		shift
		if [ ! $1 ]; then error; fi
		S_VALUE=$1
	elif [ $1 == -p ]; then
		shift
		if [ ! $1 ]; then error; fi
		P_VALUE=$1
	elif [ $1 == -a ]; then
		shift
		if [ ! $1 ]; then error; fi
		A_VALUE=$1
	elif [ $1 == -g ]; then
		shift
		if [ ! $1 ]; then error; fi
		G_VALUE=$1
	elif [ $1 == -b ]; then
		shift
		if [ ! $1 ]; then error; fi
		B_VALUE=$1
	elif [ $1 == -u ]; then
		shift
		if [ ! $1 ]; then error; fi
		U_VALUE=$1
	elif [ $1 == -jm ]; then
		shift
		if [ ! $1 ]; then error; fi
		JM_VALUE=$1
	elif [ $1 == -jf ]; then
		shift
		if [ ! $1 ]; then error; fi
		JF_VALUE=$1
	elif [ $1 == -jl ]; then
		shift
		if [ ! $1 ]; then error; fi
		JL_VALUE=$1
	elif [ $1 == -z ]; then
		shift
		if [ ! $1 ]; then error; fi
		Z_VALUE=$1
	else
		TEXT="$TEXT $1"
	fi
	shift
done

if [ ! $VDIR ]; then
	if [ $VNAME_VALUE ]; then
		VDIR=$VDIRBASE/$VNAME_VALUE
	else
		VDIR=$VDIRBASE/$DEFAULT_VOICE_NAME
	fi
fi
if [ ! -d $VDIR ]; then
	error "No voice directory : $VDIR"
fi

if [ -f $VDIR/voice.info ]; then
	while read line; do
		if [[ $line =~ ^MESSAGE= ]]; then
			MESSAGE=`echo $line|sed "s/^MESSAGE=//"`
		fi
		if [[ $line =~ ^s=  ]]; then
			S=`echo $line |sed "s/^s=//"`
		fi
		if [[ $line =~ ^p=  ]]; then
			P=`echo $line |sed "s/^p=//"`
		fi
		if [[ $line =~ ^a=  ]]; then
			A=`echo $line |sed "s/^a=//"`
		fi
		if [[ $line =~ ^g=  ]]; then
			G=`echo $line |sed "s/^g=//"`
		fi
		if [[ $line =~ ^b=  ]]; then
			B=`echo $line |sed "s/^b=//"`
		fi
		if [[ $line =~ ^u=  ]]; then
			U=`echo $line |sed "s/^u=//"`
		fi
		if [[ $line =~ ^z=  ]]; then
			Z=`echo $line |sed "s/^z=//"`
		fi
		if [[ $line =~ ^jm= ]]; then
			JM=`echo $line |sed "s/^jm=//"`
		fi
		if [[ $line =~ ^jf= ]]; then
			JF=`echo $line |sed "s/^jf=//"`
		fi
		if [[ $line =~ ^jl= ]]; then
			JL=`echo $line |sed "s/^jl=//"`
		fi
	done < $VDIR/voice.info
fi

if [[ $VNAME_VALUE =~ ^mei_ ]]; then
	if [ ! $S_VALUE  ]; then  S_VALUE=$MEI_S;  fi
	if [ ! $P_VALUE  ]; then  P_VALUE=$MEI_P;  fi
	if [ ! $A_VALUE  ]; then  A_VALUE=$MEI_A;  fi
	if [ ! $G_VALUE  ]; then  G_VALUE=$MEI_G;  fi
	if [ ! $B_VALUE  ]; then  B_VALUE=$MEI_B;  fi
	if [ ! $U_VALUE  ]; then  U_VALUE=$MEI_U;  fi
	if [ ! $Z_VALUE  ]; then  Z_VALUE=$MEI_Z;  fi
	if [ ! $JM_VALUE ]; then JM_VALUE=$MEI_JM; fi
	if [ ! $JF_VALUE ]; then JF_VALUE=$MEI_JF; fi
	if [ ! $JL_VALUE ]; then JL_VALUE=$MEI_JL; fi
else
	if [ ! $S_VALUE  ]; then  S_VALUE=$S;  fi
	if [ ! $P_VALUE  ]; then  P_VALUE=$P;  fi
	if [ ! $A_VALUE  ]; then  A_VALUE=$A;  fi
	if [ ! $G_VALUE  ]; then  G_VALUE=$G;  fi
	if [ ! $B_VALUE  ]; then  B_VALUE=$B;  fi
	if [ ! $U_VALUE  ]; then  U_VALUE=$U;  fi
	if [ ! $Z_VALUE  ]; then  Z_VALUE=$Z;  fi
	if [ ! $JM_VALUE ]; then JM_VALUE=$JM; fi
	if [ ! $JF_VALUE ]; then JF_VALUE=$JF; fi
	if [ ! $JL_VALUE ]; then JL_VALUE=$JL; fi
fi

if [ "$TEXT" ]; then
	echo $TEXT>$TEMPTXTFILE
else
	echo $MESSAGE>$TEMPTXTFILE
fi
if [ ! -f $TEMPTXTFILE ]; then
	error "No temp file : $TEMPTXTFILE"
fi

open_jtalk \
-x  $DICDIR \
-td $VDIR/tree-dur.inf \
-tm $VDIR/tree-mgc.inf \
-tf $VDIR/tree-lf0.inf \
-tl $VDIR/tree-lpf.inf \
-md $VDIR/dur.pdf \
-mm $VDIR/mgc.pdf \
-mf $VDIR/lf0.pdf \
-ml $VDIR/lpf.pdf \
-dm $VDIR/mgc.win1 \
-dm $VDIR/mgc.win2 \
-dm $VDIR/mgc.win3 \
-df $VDIR/lf0.win1 \
-df $VDIR/lf0.win2 \
-df $VDIR/lf0.win3 \
-dl $VDIR/lpf.win1 \
-ow $TEMPWAVFILE \
-ot $OT_VALUE \
-s  $S_VALUE \
-p  $P_VALUE \
-a  $A_VALUE \
-g  $G_VALUE \
-b  $B_VALUE \
$L_SWITCH \
-u  $U_VALUE \
-em $VDIR/tree-gv-mgc.inf \
-ef $VDIR/tree-gv-lf0.inf \
-cm $VDIR/gv-mgc.pdf \
-cf $VDIR/gv-lf0.pdf \
-jm $JM_VALUE \
-jf $JF_VALUE \
-jl $JL_VALUE \
-k  $VDIR/gv-switch.inf \
-z  $Z_VALUE \
$TEMPTXTFILE

if [ $mingw == 0 ]; then
	if [ -f "$TEMPWAVFILE" ]; then
		if [ $QUIET_SWITCH == 0 ]; then
			aplay -q $TEMPWAVFILE
		fi
	fi
fi
if [ "$OW_VALUE" ]; then
	cp $TEMPWAVFILE $OW_VALUE
fi
rm -f $TEMPWAVFILE
rm -f $TEMPTXTFILE

exit 0


posted by takayan at 02:30 | Comment(0) | TrackBack(0) | 音声合成 | このブログの読者になる | 更新情報をチェックする

2012年05月28日

Windows での mecab 0.993 python バインディングモジュール(32/64ビット)の作り方メモ

MeCab サイトでは、pythonバインディングのファイルを配布していますが、setup.py は Windows 環境向けには書かれていません。そこで、修正してVC++でコンパイルしたときのメモを書いておきます。以前も同じようなことを書きましたが、それはビルド環境が VC2003 でなければならない5年ほど前でした。

今回ビルドした環境は、Windows7で、32ビット版python2.7 と VC2008 がインストールされています。まず、python2.7 は http://www.python.org/ からダウンロードした通常の32bit版です。VC++はpython2.7では2008版が必要になります。

まず、Windows 向けの MeCab をインストールします。現在の最新版は0.993で、ファイル名は、mecab-0.993.exe です。下記のMeCabのダウンロードサイトからダウンロードし、インストールします。

http://code.google.com/p/mecab/downloads/list

インストール中、辞書の文字コードを聞いてきますが、文字コードは特に理由が無い限り WindowsではSHIFT-JISを選んだほうがいいでしょう。インストールが終わったら、mecab.dll があるフォルダまでPATHを通しておきます。

次に、同じダウンロードサイトから、python バインディングのソースファイルもダウンロードし展開します。最新版のファイル名は、mecab-python-0.993.tar.gz です。ダウンロードし、展開しておきます。

展開したファイルの中にあるsetup.py を次の内容に書き換えます。linux などでは、プログラム中でコマンドの実行結果を値にするのですが、Windows ではそのコマンドがないため、直接その結果を与えています。将来バージョンや配置先が変わった場合は、それに合わせて修正することになります。

#!/usr/bin/env python
from distutils.core import setup,Extension
if platform.machine() == 'AMD64':
    dir = 'C:/Program Files (x86)/MeCab/sdk'
else:
    dir = 'C:/Program Files/MeCab/sdk'
setup(name = 'mecab-python',
	version = '0.993',
	py_modules=['MeCab'],
	ext_modules = [
		Extension('_MeCab',
			['MeCab_wrap.cxx',],
			include_dirs=[dir],
			library_dirs=[dir],
			libraries=['libmecab'])])

次に、setup.pyがある場所に次の内容のバッチファイルを作って実行します。python のインストール場所などが違う場合は適宜書き換えます。

set MACHINE=x86
set PROGRAMFILESx86_PATH=%PROGRAMFILES%
if not "%PROCESSOR_ARCHITECTURE%" == "x86" set PROGRAMFILESx86_PATH=%PROGRAMFILES(x86)%
call "%PROGRAMFILESx86_PATH%\Microsoft Visual Studio 9.0\VC\vcvarsall.bat" %MACHINE%
c:\python27\python setup.py bdist_wininst
echo %PROGRAMFILESx86_PATH%

うまくいけば、distフォルダの中に、mecab-python-0.993.win32-py2.7.exe というファイルができているはずです。mecab.dll までパスが通っていないときは、このままでは実行できません。パスを通すか、python インストールフォルダの Lib\site-packages にmecab.dll をコピーします。

動作テストは、mecab-python-0.993.tar.gz 内にある test.py を使います。ただし、mecab の辞書の文字コードとtest.pyが保存されている文字コードが同じでないといけません。またSHIFT-JIS以外のときはコマンドプロンプト画面では文字化けします。

こんな結果が出ます:

0.993
太郎	名詞,固有名詞,人名,名,*,*,太郎,タロウ,タロー
は	助詞,係助詞,*,*,*,*,は,ハ,ワ
この	連体詞,*,*,*,*,*,この,コノ,コノ
本	名詞,一般,*,*,*,*,本,ホン,ホン
を	助詞,格助詞,一般,*,*,*,を,ヲ,ヲ
二	名詞,数,*,*,*,*,二,ニ,ニ
郎	名詞,一般,*,*,*,*,郎,ロウ,ロー
を	助詞,格助詞,一般,*,*,*,を,ヲ,ヲ
見	動詞,自立,*,*,一段,連用形,見る,ミ,ミ
た	助動詞,*,*,*,特殊・タ,基本形,た,タ,タ
女性	名詞,一般,*,*,*,*,女性,ジョセイ,ジョセイ
に	助詞,格助詞,一般,*,*,*,に,ニ,ニ
渡し	動詞,自立,*,*,五段・サ行,連用形,渡す,ワタシ,ワタシ
た	助動詞,*,*,*,特殊・タ,基本形,た,タ,タ
。	記号,句点,*,*,*,*,。,。,。
EOS

 	BOS/EOS,*,*,*,*,*,*,*,*
太郎 	名詞,固有名詞,人名,名,*,*,太郎,タロウ,タロー
は 	助詞,係助詞,*,*,*,*,は,ハ,ワ
この 	連体詞,*,*,*,*,*,この,コノ,コノ
本 	名詞,一般,*,*,*,*,本,ホン,ホン
を 	助詞,格助詞,一般,*,*,*,を,ヲ,ヲ
二 	名詞,数,*,*,*,*,二,ニ,ニ
郎 	名詞,一般,*,*,*,*,郎,ロウ,ロー
を 	助詞,格助詞,一般,*,*,*,を,ヲ,ヲ
見 	動詞,自立,*,*,一段,連用形,見る,ミ,ミ
た 	助動詞,*,*,*,特殊・タ,基本形,た,タ,タ
女性 	名詞,一般,*,*,*,*,女性,ジョセイ,ジョセイ
に 	助詞,格助詞,一般,*,*,*,に,ニ,ニ
渡し 	動詞,自立,*,*,五段・サ行,連用形,渡す,ワタシ,ワタシ
た 	助動詞,*,*,*,特殊・タ,基本形,た,タ,タ
。 	記号,句点,*,*,*,*,。,。,。
 	BOS/EOS,*,*,*,*,*,*,*,*
EOS
EOS
filename: C:\Program Files (x86)\MeCab\etc\..\dic\ipadic\sys.dic
charset: SHIFT-JIS
size: 392126
type: 0
lsize: 1316
rsize: 1316
version: 102

 

これだけだと面白くないので、64ビット版も作ってみました。

64ビット版のpython2.7を入れ直します。http://www.python.org/ から。最新版は、python-2.7.3.amd64.msi です。MeCab の方は、32ビット版の設定をそのまま流用したほうが楽なので、そのままインストールされているものとします。

モジュールをビルドするには、64ビット版の libmecab.lib が必要になるので、ソースからmecabをビルドします。ソースは上記のMeCabのダウンロードサイトからダウンロードしてきます。最新版 mecab-0.993.tar.gz です。

以前指摘したように、MeCab をWindowsの64ビットアプリケーションとしてコンパイルすると、型があいまいなせいでとエラーになるので、修正します。参考にしたのは以前も紹介したこのページです。今回のバージョン 0.993 での修正箇所は下のpatchに書いてある二カ所です。

diff -ru mecab-0.993.orginal/src/feature_index.cpp mecab-0.993/src/feature_index.cpp
--- mecab-0.993.orginal/src/feature_index.cpp	2012-02-11 00:35:10 +0900
+++ mecab-0.993/src/feature_index.cpp	2012-05-27 14:52:56 +0900
@@ -308,7 +308,7 @@
               if (!r) goto NEXT;
               os_ << r;
             } break;
-            case 't':  os_ << (size_t)path->rnode->char_type;     break;
+            case 't':  os_ << (unsigned int)path->rnode->char_type;     break;
             case 'u':  os_ << ufeature; break;
             default:
               CHECK_DIE(false) << "unknown meta char: " <<  *p;
diff -ru mecab-0.993.orginal/src/writer.cpp mecab-0.993/src/writer.cpp
--- mecab-0.993.orginal/src/writer.cpp	2012-02-11 00:35:10 +0900
+++ mecab-0.993/src/writer.cpp	2012-05-27 14:51:41 +0900
@@ -257,7 +257,7 @@
             // input sentence
           case 'S': os->write(lattice->sentence(), lattice->size()); break;
             // sentence length
-          case 'L': *os << lattice->size(); break;
+          case 'L': *os << (unsigned int)lattice->size(); break;
             // morph
           case 'm': os->write(node->surface, node->length); break;
           case 'M': os->write(reinterpret_cast<>

そのあと、Makefile.msvc を MinGW か CYGWIN を使って./configure を実行して Makefile.msvc を作り、さらに X64向けにほんの少し書き換えます。 Makefile.msvc.in と修正結果の差分は以下の通りです。

--- mecab-0.993.original/src/Makefile.msvc.in	Wed Nov 02 23:40:30 2011
+++ mecab-0.993/src/Makefile.msvc	Sun May 27 03:15:57 2012
@@ -3,10 +3,10 @@
 LINK=link.exe
 
 CFLAGS = /EHsc /O2 /GL /GA /Ob2 /nologo /W3 /MT /Zi /wd4800 /wd4305 /wd4244
-LDFLAGS = /nologo /OPT:REF /OPT:ICF /LTCG /NXCOMPAT /DYNAMICBASE /MACHINE:X86 ADVAPI32.LIB
+LDFLAGS = /nologo /OPT:REF /OPT:ICF /LTCG /NXCOMPAT /DYNAMICBASE /MACHINE:X64 ADVAPI32.LIB
 DEFS =  -D_CRT_SECURE_NO_DEPRECATE -DMECAB_USE_THREAD \
-        -DDLL_EXPORT -DHAVE_GETENV -DHAVE_WINDOWS_H -DDIC_VERSION=@DIC_VERSION@ \
-        -DVERSION="\"@VERSION@\"" -DPACKAGE="\"mecab\"" \
+        -DDLL_EXPORT -DHAVE_GETENV -DHAVE_WINDOWS_H -DDIC_VERSION=102 \
+        -DVERSION="\"0.993\"" -DPACKAGE="\"mecab\"" \
         -DUNICODE -D_UNICODE \
         -DMECAB_DEFAULT_RC="\"c:\\Program Files\\mecab\\etc\\mecabrc\""
 INC = -I. -I..

修正がすんだら、make.bat の内容を次のようにして実行します。64ビットOSだと分かっているのでシンプルです。

call "%PROGRAMFILES(x86)%\Microsoft Visual Studio 9.0\VC\vcvarsall.bat" X64
nmake -f Makefile.msvc

できあがった libmecab.lib を setup.py と同じディレクトリに置き、setup.py のライブラリを指定する箇所を library_dirs=['.'] とし、上記の setup.py を実行するバッチファイルの一行目を set MACHINE=X64 と書き換えて、このバッチファイルを実行します。これでdistに mecab-python-0.993.win-amd64-py2.7.exe が作成されます。

しかし、mecab-python-0.993.win-amd64-py2.7.exe を実行し、インストールしただけでは使えません。このままだと、32ビット版の libmecab.dll をロードしようとして、「%1 は有効な Win32 アプリケーションではありません。」なんて言われてしまいます。これを回避するために 64ビット版 MeCab のビルドでできた libmecab.dll を python インストールフォルダの Lib\site-packages にコピーします。これで完了です。

うまくいくかどうかは、32ビットのときと同じように、test.py を実行して確認します。

なお今回の方法では標準の辞書は mecabrc のdicdir = 行に指定されている辞書になります。mecabrc は Makefile.mvsc で指定されている C:\Program Files (x86)\MeCab\etc もしくは C:\Program Files\MeCab\etc にあって、その記述をもとに C:\Program Files (x86)\MeCab\dic\ipadic もしくは C:\Program Files\MeCab\dic\ipadic になっています。

せっかくなので、今回作ったファイルを置いておきます。
mecab-python-0.993.win32-py2.7.exe
mecab-python-0.993.win-amd64-py2.7.exe
の二つの他、64ビット版の libmecab.dll とそのインポートライブラリなども入れておきます。

ダウンロード:mecab-python-0.993.win-build.zip
(MD5:88b64ac95c08181d84398ac9f2f9a36a)



posted by takayan at 01:00 | Comment(0) | TrackBack(0) | プログラミング | このブログの読者になる | 更新情報をチェックする
×

この広告は90日以上新しい記事の投稿がないブログに表示されております。