Skip to content

Commit abd0cd3

Browse files
committed
update posts
1 parent c40e88b commit abd0cd3

File tree

1 file changed

+60
-46
lines changed

1 file changed

+60
-46
lines changed
Lines changed: 60 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -22,67 +22,81 @@ ignorePublish: false
2222
面白そうですね。やってみましょう。
2323

2424
……とは言ったものの、どうやって実現するのかはまったく分かりませんでした。
25-
でも、**AI**時代の今なら何とかなるはず。なにより、アントニオ猪木(**A**ntonio **I**noki)さんもこう言ってます。
25+
でも、**AI**時代の今なら何とかなるはず。
26+
なにより、[アントニオ猪木(**A**ntonio **I**noki)さん][Antonio Inoki]もこう言ってます。
2627

2728
> 元氣があれば何でもできる
2829
29-
そんなわけで勢いに任せて挑戦してみたわけですが、Open JTalkを適切にビルドすること自体がなかなかの深い沼でした
30+
そんなわけで勢いに任せて挑戦してみたわけですが、[Open JTalk]を適切にビルドすること自体がなかなかの深い沼でした
3031

31-
その試行錯誤のなかで、Elixir や Nerves と組み合わせて扱いやすくするためのライブラリ [open_jtalk_elixir] を作るに至りました。
32+
その試行錯誤のなかで、[Elixir][Nerves] と組み合わせて扱いやすくするためのライブラリ[open_jtalk_elixir] を作るに至りました。
3233

3334
このライブラリは:
3435

35-
- Open JTalk のネイティブCLIを Elixir コンパイル時に自動ビルド
36+
- [Open JTalk] のネイティブCLIを [Elixir] コンパイル時に自動ビルド
3637
- 必要な辞書・音声資源をあらかじめ同梱(設定不要)
37-
- Linux / macOS / Nerves(Raspberry Pi)でそのまま動作
38-
39-
[open_jtalk_elixir]: https://hex.pm/packages/open_jtalk_elixir
38+
- Linux / macOS / [Nerves] でそのまま動作
4039

4140
本記事では、次のような内容を紹介します:
4241

43-
- Open JTalk とは何か?
44-
- Elixir から日本語の音声を生成して発話させる方法
45-
- open_jtalk_elixir の使い方と設計ポイント
46-
- Nerves 対応のための工夫と注意点
42+
- [Open JTalk] とは何か?
43+
- [Elixir] から日本語の音声を生成して発話させる方法
44+
- [open_jtalk_elixir] の使い方と設計ポイント
45+
- [Nerves] 対応のための工夫と注意点
4746
- つまずいたポイントや設計の工夫
4847

49-
ラズパイや Elixir を使った日本語音声合成に興味のある方の参考になれば幸いです。
48+
[Elixir]: https://elixir-lang.org/
49+
[Nerves]: https://nerves-project.org/
50+
[open_jtalk_elixir]: https://hex.pm/packages/open_jtalk_elixir
51+
[Open JTalk]: https://open-jtalk.sp.nitech.ac.jp/
52+
[Antonio Inoki]: https://www.google.co.jp/search?q=antonio+inoki
53+
[raspberrypi.org/computers]: https://www.raspberrypi.org/computers
54+
[名古屋工業大学]: https://www.nitech.ac.jp/
55+
[Text to Speech]: https://www.google.com/search?q=text+to+speech+%E3%81%A8%E3%81%AF
56+
[WAVファイル]: https://www.google.com/search?q=WAVファイル+%E3%81%A8%E3%81%AF
57+
[HMM/DNN-based Speech Synthesis System (HTS)]: https://hts.sp.nitech.ac.jp/
58+
[MeCab]: https://taku910.github.io/mecab/
59+
[HTS Engine]: https://hts-engine.sourceforge.net/
5060

5161
## Open JTalk とは
5262

53-
[Open JTalk](https://open-jtalk.sourceforge.net/) は、名古屋工業大学によって開発された日本語テキスト音声合成(Text-to-Speech, TTS)システムです。
63+
[Open JTalk] は、[名古屋工業大学]で開発された日本語向け[テキスト音声合成(Text to Speech, TTS)][Text to Speech]システムです。
5464

55-
日本語の文章を入力として、自然な音声波形(WAVファイル)を合成でき、以下のような特徴を備えています:
65+
日本語の文章を入力として、自然な[音声波形(WAVファイル)][WAVファイル]を合成できます。
5666

57-
- 日本語に特化した TTS システムで、文解析や音素変換に対応
58-
- 統計的音声合成方式 HTS(HMM-based Speech Synthesis System)に基づく高品質な音声生成
59-
- MeCab 形式の辞書および HTS Voice(音声モデル)を用いた柔軟な音声合成
60-
- コマンドラインベースで軽量・高速に動作し、Linux/Unix 系環境と高い親和性
67+
メモリ消費が少なく、組み込み用途にも向いているそうです。
6168

62-
Open JTalk は基本的にコマンドラインツール(CLI)として提供されており、
63-
そのままでは Elixir から直接扱うには少し手間がかかる構成となっています。
69+
[Open JTalk] は基本的にコマンドラインツールとして提供され、以下の構成で利用されます:
70+
- **Open JTalk 本体**
71+
- コマンドラインで動く実行ファイル(テキストを受け取って音声を合成)
72+
- **MeCab 辞書**
73+
- 形態素解析や読み・発音情報を返す[MeCab]用の日本語辞書
74+
- **HTS 音声データファイル**
75+
- [HMMベースの統計的音声合成(HTS)][HMM/DNN-based Speech Synthesis System (HTS)]で使う音声モデルファイル(拡張子は `.htsvoice`)。
76+
- 例:`mei_normal.htsvoice`(MMDAgent の Mei)
6477

6578
## open_jtalk_elixir ライブラリの紹介
6679

67-
`open_jtalk_elixir` は、Open JTalk を Elixir から簡単に扱えるようにするためのラッパーライブラリです。
80+
[open_jtalk_elixir] は、Open JTalk を [Elixir] から簡単に扱えるようにするためのラッパーライブラリです。
6881

69-
Open JTalk は本来 C 言語で実装されたコマンドラインツールであり、辞書や音声モデルの準備・管理、各種オプションの指定などに一定の手間がかかります。また、Elixir 環境に組み込むにはビルドやパス解決などの工夫が必要です。
82+
[Open JTalk] は本来 C 言語で実装されたコマンドラインツールであり、辞書や音声モデルの準備・管理、各種オプションの指定などに一定の手間がかかります。
83+
また、[Elixir] 環境に組み込むにはビルドやパス解決などの工夫が必要です。
7084

71-
このライブラリでは、以下のような工夫を通じて、Open JTalk を Elixir プロジェクトに統合しやすくしています:
85+
このライブラリでは、以下のような工夫を通じて、[Open JTalk][Elixir] プロジェクトに統合しやすくしています:
7286

7387
-**Open JTalk のネイティブバイナリを自動ビルド**
74-
コンパイル時に必要なバイナリをビルドし、Elixir 側からすぐに使えるように配置します。
88+
コンパイル時に必要なバイナリをビルドし、[Elixir] 側からすぐに使えるように配置します。
7589

7690
-**辞書・音声モデル(HTS Voice)を同梱済み**
7791
特別な設定なしで、標準の辞書・音声資源がそのまま使えます。
7892

7993
-**Linux / macOS / Nerves に対応**
80-
Raspberry Pi を含む Nerves 環境でも動作確認済みです。
94+
Raspberry Pi を含む [Nerves] 環境でも動作確認済みです。
8195

8296
-**シンプルな API**
83-
`OpenJTalk.say("こんにちは")` のような感覚で、音声ファイルを出力できます
97+
`OpenJTalk.say("元氣ですかあ")` のように、簡単に音声ファイルを出力できます
8498

85-
裏側では CLI を叩いていますが、Elixir らしいインターフェースを通じて扱えるため、
99+
裏側では CLI を叩いていますが、[Elixir] らしいインターフェースを通じて扱えるため、
86100
音声合成を組み込んだアプリケーションの開発が手軽に行えるようになります。
87101

88102
https://github.com/mnishiguchi/open_jtalk_elixir
@@ -130,7 +144,7 @@ OpenJTalk.say("元氣ですかあ 、元氣が有れば、なんでもできる"
130144
このライブラリは以下の OS / プラットフォームで動作確認済みです:
131145

132146
*Linux(x86_64 / ARM
133-
*NervesRaspberry Pi 3, 4 で確認済み)
147+
*[Nerves]Raspberry Pi 3, 4 で確認済み)
134148
* ✅ macOS(Intel / Apple Silicon
135149

136150
:::note warn
@@ -142,13 +156,13 @@ OpenJTalk.say("元氣ですかあ 、元氣が有れば、なんでもできる"
142156

143157
## 仕組みと設計ポイント
144158

145-
`open_jtalk_elixir` を開発するうえで特に意識したのは、Elixir から簡単に扱えて、どの環境でも同じように動作することでした。
159+
`open_jtalk_elixir` を開発するうえで特に意識したのは、[Elixir] から簡単に扱えて、どの環境でも同じように動作することでした。
146160

147161
ここでは設計上の工夫をいくつか紹介します。
148162

149163
### アプローチの選択
150164

151-
Open JTalkElixir から呼び出す方法としては、いくつかの選択肢がありました。
165+
[Open JTalk][Elixir] から呼び出す方法としては、いくつかの選択肢がありました。
152166

153167
#### NIF(Native Implemented Function)
154168
高速に動作しますが、ネイティブコードがクラッシュすると BEAM VM ごと落ちるリスクがあります。
@@ -159,24 +173,24 @@ Open JTalk を Elixir から呼び出す方法としては、いくつかの選
159173
#### CLI ラッパー(`System.cmd/3`)
160174
シンプルで安全、かつ移植性も高いアプローチです。
161175

162-
今回は CLI ラッパー方式 を採用しました。移植性を確保でき、無理なくElixir の文脈に統合できるシンプルな構成と判断したためです。Elixir 側は薄く、ネイティブの沼は外部プロセスに閉じ込める方針です。
176+
今回は CLI ラッパー方式 を採用しました。移植性を確保でき、無理なく[Elixir] の文脈に統合できるシンプルな構成と判断したためです。[Elixir] 側は薄く、ネイティブの沼は外部プロセスに閉じ込める方針です。
163177

164178
### 辞書と音声モデルの同梱
165179

166180
通常の Open JTalk では、ユーザーが MeCab 辞書や HTS 音声モデルを手動で用意し、パス指定する必要があります。
167181

168182
このライブラリでは、標準の辞書と音声モデルをあらかじめ同梱し、導入直後からすぐに使える体験を提供しています。
169183

170-
ただし、Nerves などファームウェア環境では容量制約もあります。
184+
ただし、[Nerves] などファームウェア環境では容量制約もあります。
171185
そのため、環境変数を使って 外部ファイルを指定できる仕組みも用意し、利便性と柔軟性のバランスを取りました。
172186

173187
### クロスプラットフォーム対応
174188

175-
最も苦労したのは、Linux / macOS / Nerves といった異なるプラットフォーム間の差異をどう吸収するかでした。
189+
最も苦労したのは、Linux / macOS / [Nerves] といった異なるプラットフォーム間の差異をどう吸収するかでした。
176190

177-
設計方針としては、Elixir コード自体は環境に依存させず、差異はビルドスクリプトや再生コマンド側で吸収するようにしました。
191+
設計方針としては、[Elixir] コード自体は環境に依存させず、差異はビルドスクリプトや再生コマンド側で吸収するようにしました。
178192

179-
こうした工夫により、Elixir 側のコードは一切変更せずに、あらゆる環境で同じように動作することを目指しました。
193+
こうした工夫により、[Elixir] 側のコードは一切変更せずに、あらゆる環境で同じように動作することを目指しました。
180194

181195
#### Linux(x86_64 / ARM)
182196

@@ -190,7 +204,7 @@ Apple Silicon 環境では静的リンクが難しく、動的リンクに切り
190204

191205
#### Nerves
192206

193-
Nerves 向けには、`MIX_TARGET` に応じてクロスコンパイル設定を切り替える必要がありました。
207+
[Nerves] 向けには、`MIX_TARGET` に応じてクロスコンパイル設定を切り替える必要がありました。
194208

195209
また、辞書や音声ファイルはサイズが大きいため、ファームウェア容量の制約を常に意識する必要があります。必要に応じて外部ファイルを読み込む構成にも対応させています。
196210

@@ -222,15 +236,15 @@ Nerves 向けには、`MIX_TARGET` に応じてクロスコンパイル設定を
222236
5. **辞書・音声の導入**
223237
標準の辞書や音声ファイルを `priv/` にインストール。
224238

225-
この一連は Makefile のターゲットから呼び出され、Elixir 側は `mix compile` だけで完走します。
239+
この一連は Makefile のターゲットから呼び出され、[Elixir] 側は `mix compile` だけで完走します。
226240
また キャッシュ戦略として、一度ビルドした成果物は `priv/` 配下に保持し、再コンパイルを高速化。必要に応じて `mix clean` や `OpenJTalk.Assets.reset_cache/0` でリセットできます。
227241

228-
ちなみに再生コマンドの選択(`aplay`, `afplay` など)は、Elixir 側で `System.find_executable/1` により動的に解決する方針にしました。
242+
ちなみに再生コマンドの選択(`aplay`, `afplay` など)は、[Elixir] 側で `System.find_executable/1` により動的に解決する方針にしました。
229243

230244
### ディレクトリ構成
231245

232-
Elixir のソース(`lib/`)、ビルド資源(`vendor/`)、辞書・音声(`priv/`)を分離して管理しています。
233-
C ソースは Open JTalkMeCabHTS Engine の 公式配布物をダウンロードして `vendor/` に展開し、そこからビルドします。
246+
[Elixir] のソース(`lib/`)、ビルド資源(`vendor/`)、辞書・音声(`priv/`)を分離して管理しています。
247+
C ソースは [Open JTalk]/[MeCab]/[HTS Engine] の 公式配布物をダウンロードして `vendor/` に展開し、そこからビルドします。
234248

235249
```text
236250
.
@@ -248,7 +262,7 @@ C ソースは Open JTalk/MeCab/HTS Engine の 公式配布物をダウン
248262

249263
## Nerves 対応のポイント
250264

251-
`open_jtalk_elixir` は Nerves を意識して設計しています。
265+
`open_jtalk_elixir`[Nerves] を意識して設計しています。
252266
基本的には、`MIX_TARGET` を設定して `mix compile` するだけでクロスコンパイルと資産の同梱が完了します。
253267

254268
### 1. クロスコンパイルの流れ
@@ -261,7 +275,7 @@ mix compile
261275
mix firmware
262276
```
263277

264-
* `MIX_TARGET` を設定すると、Nerves 用のツールチェーンが自動で選択されます。
278+
* `MIX_TARGET` を設定すると、[Nerves] 用のツールチェーンが自動で選択されます。
265279
* MeCab / HTS Engine / Open JTalk などの
266280
C言語ライブラリ群も、ターゲット向けに構築され`priv/` に配置されます。
267281

@@ -292,7 +306,7 @@ OpenJTalk.Assets.reset_cache()
292306

293307
`OpenJTalk.say/2` は、合成した音声(WAV)を デバイス上の再生コマンドを使って鳴らします。
294308

295-
* Linux/Nerves: `aplay`(多くの Nerves イメージに標準で含まれています)
309+
* Linux/[Nerves]: `aplay`(多くの [Nerves] イメージに標準で含まれています)
296310
* macOS: `afplay`(参考)
297311

298312
もし音が出ない場合は:
@@ -308,7 +322,7 @@ IO.inspect(info.audio_player, label: "audio player")
308322

309323
### 4. 実機での最小動作確認
310324

311-
Nerves 実機に接続後:
325+
[Nerves] 実機に接続後:
312326

313327
```elixir
314328
{:ok, info} = OpenJTalk.info()
@@ -318,12 +332,12 @@ OpenJTalk.say("元氣ですかあ 、元氣が有れば、何でもできる")
318332

319333
## おわりに
320334

321-
本記事では、Elixir から日本語音声合成を行うためのライブラリ `open_jtalk_elixir` と、その裏側にある設計・工夫について紹介しました。
335+
本記事では、[Elixir] から日本語音声合成を行うためのライブラリ `open_jtalk_elixir` と、その裏側にある設計・工夫について紹介しました。
322336

323337
もともとは「ラズパイで Open JTalk を動かしたい」という軽い問いかけから始まりましたが、
324338
辞書・音声資源の取り扱い、クロスコンパイル、環境ごとのビルド差分など、深い学びのある取り組みとなりました。
325339

326-
Elixir / Nerves の文脈で日本語音声合成を扱いたい方にとって、少しでも参考になれば幸いです。
340+
[Elixir] / [Nerves] の文脈で日本語音声合成を扱いたい方にとって、少しでも参考になれば幸いです。
327341

328342
もし不具合や改善案などあれば、ぜひ [GitHub Issues](https://github.com/mnishiguchi/open_jtalk_elixir/issues) からお気軽にお知らせください。
329343

0 commit comments

Comments
 (0)