先日、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


