凹みTips

C++、JavaScript、Unity、ガジェット等の Tips について雑多に書いています。

OpenJTalk を使って Node.js で音声合成するモジュール作った

はじめに

OpenJTalk はフリーの日本語音声合成エンジンです。

以前、Node.js 用 Open JTalk アドオンを作ってみた - 凹みTipsというエントリを書きましたが、当時は古い waf 環境のもとで作っており、同期的に動くため、喋り終わるまで処理が返ってこない状態でした。
そこで、最新の gyp 対応、非同期対応に加えて MacOS XUbuntuクロスプラットフォーム対応を行いました。

出来るようになること

var OpenJTalk = require('openjtalk');
var mei = new OpenJTalk({ // 引数は省略可
	voice   : './voice/mei_normal',
	dic     : './dic/open_jtalk_dic_utf_8-1.05',
	options : {
		sampling_rate   : 48000,
		stage           : 0,
		audio_buff_size : 48000,
		alpha           : 0.5,
		beta            : 0.8,
		uv_threshold    : 0.5,
		gv_weight_mgc   : 1.0,
		gv_weight_lf0   : 1.0,
		gv_weight_lpf   : 1.0
	}
});
mei.talk( '喋るよ!', function(err) { mei.talk('コールバックあるよ'); } );

ダウンロード

環境

MacOS X 10.8.2 および Ubuntu 10.04 で動作を確認しています。
コンパイルには以下のものが必要です。()内はこちらで動作させたバージョンになります。

aptitude なり brew なりでインストールして下さい。

インストール

$ cd YOUR_NODE_PROJECT_DIR
$ git clone https://github.com/hecomi/node-openjtalk
$ mkdir node_modules
$ mv node-julius node_modules/openjtalk
$ cd node_modules/julius
$ npm install

無事インストールされたら、以下のコマンドでテストしてみて下さい。

$ npm test

喋りだせば成功です。

使い方

音声ファイルを含んだディレクトリ、辞書ファイルを含んだディレクトリ、OpenJTalk の設定オプションを引数に渡せます。
引数は省略することもできます。省略した場合は MMDAgent のメイちゃんの声をデフォルトとして喋ります。
音声ファイルを複数用意すれば以下のように喋り分け出来ます。

var OpenJTalk = require('openjtalk');
var mei1 = new OpenJTalk(); // mei_normal を使用
var mei2 = new OpenJTalk({voice: './voice/mei_sad'});
var mei3 = new OpenJTalk({voice: './voice/mei_happy'});

mei1.talk('これはテストです'); // コールバックは省略できる
setTimeout(function() {
	mei2.talk('喋り終わり次第コールバックを呼びます', function(err) {
		console.log('コールバックを呼んだ');
		mei3.talk('エラーが発生したらコールバックの引数からチェックできます', function(err) {
			if (err) console.log('err', err);
			else mei1.talk('エラーは発生しませんでした');
		});
	});
}, 2000);

同期して喋らせたい場合は、async 等のモジュールを使えば綺麗に書けると思います。
設定値を変える場合は以下のようにします。

var OpenJTalk = require('./openjtalk');
var mei = new OpenJTalk({
	voice   : './voice/mei_normal',
	dic     : './dic/open_jtalk_dic_utf_8-1.05',
	options : {
		sampling_rate   : 48000,
		stage           : 0,
		audio_buff_size : 48000,
		alpha           : 0.5,
		beta            : 0.8,
		uv_threshold    : 0.5,
		gv_weight_mgc   : 1.0,
		gv_weight_lf0   : 1.0,
		gv_weight_lpf   : 1.0
	}
});

// 喋る速度を調整することもできます
mei.talk('すっごい速いです', 100, function(err) {
	mei.talk('普通くらいです', 200, function(err) {
		mei.talk('ゆっくり喋るよ', 300);
	});
});

options の各設定値は省略可能です。ちなみに上記がデフォルト値になります。

処理的には、OpenJTalk で wav を生成、それを portaudio で再生、喋り終わったら削除、としているので、しゃべっている途中に中断すると wav ファイルが実行しているディレクトリに残ります。手動で削除して下さい。

声を変えたい!

MMDAgent 用に音素ファイルを配布してくださっている方もいらっしゃるのでお借りすると別の声でしゃべってくれます。

上記サイトではミクさんの音素ファイルを公開してくださっています。

ちなみに

単純にコンソールで喋らせたいだけの場合は Mac なら saykana を利用すれば簡単に出来ます。

var exec = require('child_process').exec;

function say(str, callback) {
	exec('saykana ' + str, function(err, stdout, stderr) {
		if (callback) callback(err);
	});
}

function saykanji(str, callback) {
	exec('echo ' + str + ' | mecab -O yomi | saykana', function(err, stdout, stderr) {
		if (callback) callback(err);
	});
}

say('ゆっくりしていってね!', function() {
	saykanji('漢字も喋れるよ!');
});

saykana は AquesTalk をベースにしています。ゆっくりさんボイス良いですね!

おわりに

Twitter で @ が飛んできたら喋らせるだけでも割りと楽しいですので是非喋らせてみて下さい。