@@ -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
88102https://github.com/mnishiguchi/open_jtalk_elixir
@@ -130,7 +144,7 @@ OpenJTalk.say("元氣ですかあ 、元氣が有れば、なんでもできる"
130144このライブラリは以下の OS / プラットフォームで動作確認済みです:
131145
132146* ✅ Linux (x86_64 / ARM )
133- * ✅ Nerves (Raspberry 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 JTalk を Elixir から呼び出す方法としては、いくつかの選択肢がありました。
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` に応じてクロスコンパイル設定を
2222365 . ** 辞書・音声の導入**
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 JTalk / MeCab / HTS 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
261275mix firmware
262276```
263277
264- * ` MIX_TARGET ` を設定すると、Nerves 用のツールチェーンが自動で選択されます。
278+ * ` MIX_TARGET ` を設定すると、[ Nerves] 用のツールチェーンが自動で選択されます。
265279* MeCab / HTS Engine / Open JTalk などの
266280C言語ライブラリ群も、ターゲット向けに構築され` 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