動機
- 前回の記事では、Ubuntu 上の Firefox で日本語音声合成をする設定を紹介しました。
- 今回は、より機能強化する設定です。
- 具体的には、声を複数指定する、音量・速度・ピッチ(高低)を Web Speech API から指定する機能が強化されます。
利用する技術
- Web Speech API:ブラウザから発話を制御する Javascript の API。
window.speechSynthesisから利用する。 - speech-dispatcher:Linux系でブラウザなどの発話リクエストを振り分ける機能。
- OpenJTalk:日本語でテキストを発話する機能。
検証環境
- Ubuntu:25.10 amd64
- Firefox:145.0.2 Snap版
設定方法
前回の記事の設定に依存方法しない設定です。前回の記事に続けて行うには、適宜読み替えてください。
以下をインストールします。依存パッケージの一覧が出てきたらインストールするようにしてください。
sudo apt install open-jtalk open-jtalk-mecab-naist-jdic
ブラウザなどで音声データをダウンロードします。
https://sourceforge.net/projects/mmdagent/files/MMDAgent_Example/MMDAgent_Example-1.8/MMDAgent_Example-1.8.zip
zipを展開し、ログインユーザのホームディレクトリの、今回所定のフォルダに配置します。
mkdir ~/htsvoice
mv ~/MMDAgent_Example-1.8/Voice/mei/* ~/htsvoice/
mv ~/MMDAgent_Example-1.8/Voice/takumimei/* ~/htsvoice/
以下のファイルが配置されます。
| ファイル |
|---|
| ~/htsvoice/mei_happy.htsvoice |
| ~/htsvoice/mei_sad.htsvoice |
| ~/htsvoice/mei_bashful.htsvoice |
| ~/htsvoice/mei_normal.htsvoice |
| ~/htsvoice/mei_angry.htsvoice |
| ~/htsvoice/takumi_happy.htsvoice |
| ~/htsvoice/takumi_normal.htsvoice |
| ~/htsvoice/takumi_sad.htsvoice |
| ~/htsvoice/takumi_angry.htsvoice |
ログインユーザの設定一式を作成します。
spd-conf -ucn
コメント化します。
#AudioOutputMethod "pulse"
追加します。
AddModule "openjtalk-generic" "sd_generic" "openjtalk-generic.conf" "spd-openjtalk.log"
汎用モジュールの設定ファイルを新規作成します。
# openjtalkをgeneric pluginで定義する。
Debug 0
# 一気に変換するデータ長の最大値。発話が切れてしまう、open_jtalkは大きめでも大丈夫そうなので設定を変える。
GenericMaxChunkLength 1024
# GenericExecuteSynthに埋め込まれるべき値
# 音量
# 0 to 2 default 1 float : volumeAtWebSpeechAPI
# -100 to 100 default 100 int : volumeAtSpeechDispatcher = (volumeAtWebSpeechAPI - 0) * 100
# 0 to 2 default 1 float : volumeAtPwPlay = $VOLUME = volumeAtSpeechDispatcher * GenericVolumeMultiply / 100 + GenericVolumeAdd
GenericVolumeForceInteger 0
GenericVolumeMultiply 1
GenericVolumeAdd 0
# 速度
# 0 to 2 default 1 float : rateAtWebSpeechAPI
# -100 to 100 default 0 int : rateAtSpeechDispatcher = (rateAtWebSpeechAPI - 1) * 100
# 0 to 2 default 1 float : rateAtOpenJtalk = $RATE = rateAtSpeechDispatcher * GenericRateMultiply / 100 + GenericRateAdd
GenericRateForceInteger 0
GenericRateMultiply 1
GenericRateAdd 1
# ピッチ
# 0 to 2 default 1 float : pitchAtWebSpeechAPI
# -100 to 100 default 0 int : pitchAtSpeechDispatcher = (pitchAtWebSpeechAPI - 1) * 100
# -24 to 24 default 0 int : pitchAtOpenJtalk = $PITCH = (int) pitchAtSpeechDispatcher * GenericPitchMultiply / 100 + GenericPitchAdd
GenericPitchForceInteger 1
GenericPitchMultiply 24
GenericPitchAdd 0
# 実行コマンドを定義する。
# https://htmlpreview.github.io/?https://github.com/brailcom/speechd/blob/master/doc/speech-dispatcher.html#Configuration-of-the-Generic-Output-Module
# $DATA 言うべきテキストデータ。文字列の文字列がsh処理を妨げる文字列の文字はすでにエスケープされています。ただし、その周りに二重引用符を付ける必要がある場合があります(このように:\"$DATA\")。
# $LANGUAGE 言語識別文字列(Generic Languageで定義される)。
# $VOICE 音声識別文字列(AddVoiceで定義されています)。
# $PITCH_RANGE 希望のピッチ範囲(GenericPitchRangeAdd および GenericPitchRangeMultiply で定義された浮動小数点数)。
# その他のパラメータ(generic.cより):$PLAY_COMMAND $TMPDIR $HOMEDIR $LANGUAGE $PUNCT
GenericExecuteSynth \
"echo \'$DATA\' | open_jtalk -x /var/lib/mecab/dic/open-jtalk/naist-jdic -m \'$HOMEDIR/htsvoice/$VOICE.htsvoice\' -r $RATE -fm $PITCH -ow /dev/stdout | pw-play --volume=$VOLUME -"
GenericCmdDependency "open_jtalk"
# 動作確認結果、enに対する定義も有効にする必要がある。
GenericDefaultCharset "utf-8"
GenericLanguage "en" "en_GB" "utf-8"
GenericLanguage "en" "en_US" "utf-8"
GenericLanguage "ja" "ja_JP" "utf-8"
# 3番目の引数が$VOICEに渡る。
# 2番目の引数は次のいずれかである必要がある:CHILD_FEMALE FEMALE1 FEMALE2 FEMALE3 CHILD_MALE MALE1 MALE2 MALE3
AddVoice "ja" "CHILD_FEMALE" "mei_happy"
AddVoice "ja" "FEMALE1" "mei_sad"
AddVoice "ja" "FEMALE2" "mei_bashful"
AddVoice "ja" "FEMALE3" "mei_normal"
AddVoice "ja" "CHILD_MALE" "mei_angry"
AddVoice "ja" "MALE1" "takumi_happy"
AddVoice "ja" "MALE2" "takumi_normal"
AddVoice "ja" "MALE3" "takumi_sad"
#AddVoice "ja" "MALE3" "takumi_angry"
DefaultVoice "mei_happy"
ログインユーザのサービスを再読み込みます。
systemctl --user reload speech-dispatcher.service
ブラウザで読み込んだページのjsから window.speechSynthesis.getVoices()を呼び出すと、順序不明で以下の要素のリストが返ります。
| lang | name |
|---|---|
| ja | mei_happy |
| ja | mei_sad |
| ja | mei_bashful |
| ja | mei_normal |
| ja | mei_angry |
| ja | takumi_happy |
| ja | takumi_normal |
| ja | takumi_sad |
以下のように、声、音量・速度・ピッチを、ブラウザで読み込んだページのjsからopenjtalkとプレーヤーに渡すことができます。
const voices = window.speechSynthesis.getVoices();
// ...
const uttr = new SpeechSynthesisUtterance('おはようございます');
uttr.voice = voices.find(v=>v.name.includes('mei_happy'));
uttr.rate = 1.2;
uttr.pitch = 1.2;
uttr.volume = 0.8;
window.speechSynthesis.speak(uttr);
課題
- 多言語の振り分け指定は未対応。
結語
開発維持保守関連の皆様ありがとうございます。