@kongyo2/kongyoroid 1.0.0 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (199) hide show
  1. package/README.md +233 -0
  2. package/dist/cache.d.ts +32 -7
  3. package/dist/cache.d.ts.map +1 -1
  4. package/dist/cache.js +138 -9
  5. package/dist/cache.js.map +1 -1
  6. package/dist/cli/flags.d.ts +270 -0
  7. package/dist/cli/flags.d.ts.map +1 -0
  8. package/dist/cli/flags.js +240 -0
  9. package/dist/cli/flags.js.map +1 -0
  10. package/dist/cli/help.d.ts +11 -0
  11. package/dist/cli/help.d.ts.map +1 -0
  12. package/dist/cli/help.js +336 -0
  13. package/dist/cli/help.js.map +1 -0
  14. package/dist/cli.js +598 -232
  15. package/dist/cli.js.map +1 -1
  16. package/dist/errors.d.ts +43 -3
  17. package/dist/errors.d.ts.map +1 -1
  18. package/dist/errors.js +56 -3
  19. package/dist/errors.js.map +1 -1
  20. package/dist/index.d.ts +59 -22
  21. package/dist/index.d.ts.map +1 -1
  22. package/dist/index.js +32 -14
  23. package/dist/index.js.map +1 -1
  24. package/dist/io.d.ts +11 -0
  25. package/dist/io.d.ts.map +1 -1
  26. package/dist/io.js +149 -5
  27. package/dist/io.js.map +1 -1
  28. package/dist/kongyoroid.d.ts +237 -10
  29. package/dist/kongyoroid.d.ts.map +1 -1
  30. package/dist/kongyoroid.js +777 -86
  31. package/dist/kongyoroid.js.map +1 -1
  32. package/dist/limits.d.ts +5 -0
  33. package/dist/limits.d.ts.map +1 -1
  34. package/dist/limits.js +6 -1
  35. package/dist/limits.js.map +1 -1
  36. package/dist/request.d.ts +1 -0
  37. package/dist/request.d.ts.map +1 -1
  38. package/dist/request.js +102 -15
  39. package/dist/request.js.map +1 -1
  40. package/dist/schema.d.ts +3 -0
  41. package/dist/schema.d.ts.map +1 -1
  42. package/dist/schema.js +271 -68
  43. package/dist/schema.js.map +1 -1
  44. package/dist/song/mml.d.ts +15 -0
  45. package/dist/song/mml.d.ts.map +1 -0
  46. package/dist/song/mml.js +184 -0
  47. package/dist/song/mml.js.map +1 -0
  48. package/dist/song/pitch.d.ts.map +1 -0
  49. package/dist/{pitch.js → song/pitch.js} +1 -1
  50. package/dist/song/pitch.js.map +1 -0
  51. package/dist/song/score.d.ts +92 -0
  52. package/dist/song/score.d.ts.map +1 -0
  53. package/dist/song/score.js +454 -0
  54. package/dist/song/score.js.map +1 -0
  55. package/dist/synth/acoustics.d.ts +27 -0
  56. package/dist/synth/acoustics.d.ts.map +1 -0
  57. package/dist/synth/acoustics.js +608 -0
  58. package/dist/synth/acoustics.js.map +1 -0
  59. package/dist/synth/analysis.d.ts +22 -0
  60. package/dist/synth/analysis.d.ts.map +1 -0
  61. package/dist/synth/analysis.js +170 -0
  62. package/dist/synth/analysis.js.map +1 -0
  63. package/dist/synth/engine.d.ts +115 -0
  64. package/dist/synth/engine.d.ts.map +1 -0
  65. package/dist/synth/engine.js +223 -0
  66. package/dist/synth/engine.js.map +1 -0
  67. package/dist/synth/filters.d.ts +60 -0
  68. package/dist/synth/filters.d.ts.map +1 -0
  69. package/dist/synth/filters.js +166 -0
  70. package/dist/synth/filters.js.map +1 -0
  71. package/dist/synth/glottal.d.ts +20 -0
  72. package/dist/synth/glottal.d.ts.map +1 -0
  73. package/dist/synth/glottal.js +76 -0
  74. package/dist/synth/glottal.js.map +1 -0
  75. package/dist/synth/phonemes.d.ts +42 -0
  76. package/dist/synth/phonemes.d.ts.map +1 -0
  77. package/dist/synth/phonemes.js +311 -0
  78. package/dist/synth/phonemes.js.map +1 -0
  79. package/dist/synth/plan.d.ts +127 -0
  80. package/dist/synth/plan.d.ts.map +1 -0
  81. package/dist/synth/plan.js +81 -0
  82. package/dist/synth/plan.js.map +1 -0
  83. package/dist/synth/prosody.d.ts +30 -0
  84. package/dist/synth/prosody.d.ts.map +1 -0
  85. package/dist/synth/prosody.js +46 -0
  86. package/dist/synth/prosody.js.map +1 -0
  87. package/dist/synth/random.d.ts +15 -0
  88. package/dist/synth/random.d.ts.map +1 -0
  89. package/dist/synth/random.js +59 -0
  90. package/dist/synth/random.js.map +1 -0
  91. package/dist/synth/renderer.d.ts +77 -0
  92. package/dist/synth/renderer.d.ts.map +1 -0
  93. package/dist/synth/renderer.js +343 -0
  94. package/dist/synth/renderer.js.map +1 -0
  95. package/dist/synth/song.d.ts +30 -0
  96. package/dist/synth/song.d.ts.map +1 -0
  97. package/dist/synth/song.js +453 -0
  98. package/dist/synth/song.js.map +1 -0
  99. package/dist/synth/speech.d.ts +49 -0
  100. package/dist/synth/speech.d.ts.map +1 -0
  101. package/dist/synth/speech.js +354 -0
  102. package/dist/synth/speech.js.map +1 -0
  103. package/dist/synth/stream.d.ts +26 -0
  104. package/dist/synth/stream.d.ts.map +1 -0
  105. package/dist/synth/stream.js +67 -0
  106. package/dist/synth/stream.js.map +1 -0
  107. package/dist/synth/textstream.d.ts +35 -0
  108. package/dist/synth/textstream.d.ts.map +1 -0
  109. package/dist/synth/textstream.js +127 -0
  110. package/dist/synth/textstream.js.map +1 -0
  111. package/dist/synth/voice.d.ts +64 -0
  112. package/dist/synth/voice.d.ts.map +1 -0
  113. package/dist/synth/voice.js +208 -0
  114. package/dist/synth/voice.js.map +1 -0
  115. package/dist/text/dictionary.d.ts +50 -0
  116. package/dist/text/dictionary.d.ts.map +1 -0
  117. package/dist/text/dictionary.js +0 -0
  118. package/dist/text/dictionary.js.map +1 -0
  119. package/dist/text/frontend.d.ts +34 -0
  120. package/dist/text/frontend.d.ts.map +1 -0
  121. package/dist/text/frontend.js +550 -0
  122. package/dist/text/frontend.js.map +1 -0
  123. package/dist/text/lexicon.d.ts +10 -0
  124. package/dist/text/lexicon.d.ts.map +1 -0
  125. package/dist/text/lexicon.js +763 -0
  126. package/dist/text/lexicon.js.map +1 -0
  127. package/dist/{mora.d.ts → text/mora.d.ts} +15 -3
  128. package/dist/text/mora.d.ts.map +1 -0
  129. package/dist/{mora.js → text/mora.js} +87 -9
  130. package/dist/text/mora.js.map +1 -0
  131. package/dist/text/normalize.d.ts +34 -0
  132. package/dist/text/normalize.d.ts.map +1 -0
  133. package/dist/text/normalize.js +496 -0
  134. package/dist/text/normalize.js.map +1 -0
  135. package/dist/text/notation.d.ts +32 -0
  136. package/dist/text/notation.d.ts.map +1 -0
  137. package/dist/text/notation.js +182 -0
  138. package/dist/text/notation.js.map +1 -0
  139. package/dist/text/reading.d.ts +52 -0
  140. package/dist/text/reading.d.ts.map +1 -0
  141. package/dist/text/reading.js +32 -0
  142. package/dist/text/reading.js.map +1 -0
  143. package/dist/text/sentences.d.ts +10 -0
  144. package/dist/text/sentences.d.ts.map +1 -0
  145. package/dist/text/sentences.js +84 -0
  146. package/dist/text/sentences.js.map +1 -0
  147. package/dist/{text.d.ts → text/split.d.ts} +2 -2
  148. package/dist/text/split.d.ts.map +1 -0
  149. package/dist/{text.js → text/split.js} +2 -2
  150. package/dist/text/split.js.map +1 -0
  151. package/dist/types.d.ts +58 -3
  152. package/dist/types.d.ts.map +1 -1
  153. package/dist/version.d.ts +4 -0
  154. package/dist/version.d.ts.map +1 -1
  155. package/dist/version.js +5 -1
  156. package/dist/version.js.map +1 -1
  157. package/dist/voicevox/client.d.ts +1 -1
  158. package/dist/voicevox/client.d.ts.map +1 -1
  159. package/dist/voicevox/dictionary.js +1 -1
  160. package/dist/voicevox/dictionary.js.map +1 -1
  161. package/dist/voicevox/song.js +1 -1
  162. package/dist/voicevox/song.js.map +1 -1
  163. package/dist/voicevox/speech.d.ts +1 -0
  164. package/dist/voicevox/speech.d.ts.map +1 -1
  165. package/dist/voicevox/speech.js +8 -2
  166. package/dist/voicevox/speech.js.map +1 -1
  167. package/docs/cli.md +251 -0
  168. package/examples/batch.jsonl +4 -3
  169. package/examples/builtin/dictionary.json +7 -0
  170. package/examples/builtin/song-compact.json +13 -0
  171. package/examples/builtin/song-mml.json +9 -0
  172. package/examples/builtin/song-notes.json +25 -0
  173. package/examples/builtin/speech-dictionary.json +9 -0
  174. package/examples/builtin/speech-kana.json +7 -0
  175. package/examples/builtin/speech.json +7 -0
  176. package/package.json +11 -3
  177. package/dist/formant.d.ts +0 -34
  178. package/dist/formant.d.ts.map +0 -1
  179. package/dist/formant.js +0 -622
  180. package/dist/formant.js.map +0 -1
  181. package/dist/mora.d.ts.map +0 -1
  182. package/dist/mora.js.map +0 -1
  183. package/dist/notation.d.ts +0 -15
  184. package/dist/notation.d.ts.map +0 -1
  185. package/dist/notation.js +0 -114
  186. package/dist/notation.js.map +0 -1
  187. package/dist/pitch.d.ts.map +0 -1
  188. package/dist/pitch.js.map +0 -1
  189. package/dist/score.d.ts +0 -37
  190. package/dist/score.d.ts.map +0 -1
  191. package/dist/score.js +0 -166
  192. package/dist/score.js.map +0 -1
  193. package/dist/text.d.ts.map +0 -1
  194. package/dist/text.js.map +0 -1
  195. package/examples/song-notes.json +0 -24
  196. /package/dist/{pitch.d.ts → song/pitch.d.ts} +0 -0
  197. /package/examples/{song.json → voicevox/song.json} +0 -0
  198. /package/examples/{speech-kana.json → voicevox/speech-kana.json} +0 -0
  199. /package/examples/{speech.json → voicevox/speech.json} +0 -0
package/README.md CHANGED
@@ -2,6 +2,239 @@
2
2
 
3
3
  LLM エージェントが CLI やライブラリとして扱う前提で作った、日本語の**読み上げ**と**歌唱**のツールです。
4
4
 
5
+ - **内蔵エンジンが本体**です。外部サービスも GPU も不要で、`npm install` だけで漢字かな交じり文を読み、歌います。同じリクエストからは常にビット単位で同じ WAV が出ます。
6
+ - **JSON で会話します。** 入力は JSON Schema 付きのリクエスト、出力は 1 行 1 JSON。失敗は構造化エラー (`code` / `path` / `hint` / `repairOptions`) と終了コードで返します。
7
+ - **レンダリングの前に確認できます。** `validate` と `plan` が読み (アクセント付きかな)、音素、音符の時刻、推定尺、警告を返すので、エージェントは音声を書き出す前に直せます。
8
+
9
+ ## 要件とインストール
10
+
11
+ - Node.js 22.18 以上 (ESM)。
12
+ - 依存は日本語テキストフロントエンド `kanji2koe-openjtalk` (jpreprocess + NAIST-JDic の WebAssembly、約 20 MB) のみ。初回ロードに 0.5 秒前後かかり、以降はプロセス内で再利用されます。
13
+
14
+ ```sh
15
+ npm install @kongyo2/kongyoroid
16
+ npx kongyoroid doctor
17
+ ```
18
+
19
+ `doctor` が `"ok": true` を返せば、フロントエンドと合成器が動いています。
20
+
21
+ ## 30 秒で使う
22
+
23
+ ```sh
24
+ # 読み上げ (漢字・数字・日付・英単語をそのまま)
25
+ kongyoroid speak --text "テストが3件失敗しました。ログを確認してください。" -o result.wav
26
+
27
+ # 歌唱 (歌詞 + 音名 + 拍)
28
+ kongyoroid sing --lyrics "きらきらぼし" --melody "C4 C4 G4 G4 A4 A4" --beats "1 1 1 1 1 2" -o twinkle.wav
29
+
30
+ # 書き出す前に読みを確認する
31
+ kongyoroid plan --text "橋の端で箸を使う" | jq .plan.reading.kana
32
+ # "ハシ'ノ/ハシデ/ハ'シヲ/_ツカウ。"
33
+
34
+ # 読みを直す
35
+ kongyoroid speak --text "kongyoroidは便利です" --dict-entry kongyoroid=コンギョロイド:0 -o dict.wav
36
+ kongyoroid speak --text "橋の端" --kana "ハシ'ノ/ハシ" -o hashi.wav
37
+
38
+ # 文が届き次第、音声を流す (LLM の出力をそのまま再生)
39
+ llm-agent run | kongyoroid speak --input - --stream --output - --format pcm | aplay -f S16_LE -r 24000 -c 1
40
+ ```
41
+
42
+ すべてのコマンドは標準出力に 1 行の JSON を書きます。
43
+
44
+ ```json
45
+ {"ok":true,"path":"/work/result.wav","written":true,"unchanged":false,"engine":"formant","engineVersion":"formant-2.0.0","kind":"speech","voice":"neutral","kana":"テ'_ストガ/サン'ゲン/シッパイ/シマ'_シタ。","sha256":"66b3…","requestHash":"42de…","bytes":108942,"sampleRate":24000,"channels":1,"frames":54449,"durationSeconds":2.269,"peak":0.4772,"rms":0.081,"limitedSamples":0,"warnings":[],"adjustments":[]}
46
+ ```
47
+
48
+ ## エージェント向けの作法
49
+
50
+ 1. **`validate` → `plan` → `speak` / `sing` / `render`** の順に使うと、失敗を最短で直せます。`validate` は構造と意味 (読める文字か、音符が短すぎないか、音域内か) を検査して推定尺とハッシュを返し、`plan` は読みと時刻表を返します。どちらも音声を書きません。
51
+ 2. **エラーは `code` で分岐**してください。メッセージは人間向けで変わり得ます。`path` は JSON Pointer 風 (`$.notes[1].beats`、フラグなら `$flags.speed`)、`repairOptions[].action` は機械可読な修正案です。
52
+ 3. **終了コード**: `0` 成功、`1` 内部エラー、`2` 入力エラー (直して再送)、`3` エンジン利用不可 (VOICEVOX 未起動やフロントエンド破損)、`4` 入出力エラー (上書き拒否など)、`130` 中断。
53
+ 4. **同じ内容の再書き出しは no-op** です。`--output` の既存ファイルが同一内容なら `"unchanged": true`、異なる内容なら `IO_ERROR` と `use-force` の修正案を返します。
54
+ 5. **決定性**: 同じリクエスト・同じ `seed`・同じバージョンなら WAV は同一です。`requestHash` (正規化したリクエスト) と `planHash` (合成計画) で差分を追えます。
55
+ 6. **長文は `--stream`** で文単位に流し、短い通知はキャッシュ (`--cache-dir`) を効かせてください。
56
+
57
+ エラーの例:
58
+
59
+ ```json
60
+ {"ok":false,"error":{"code":"NOTE_TOO_SHORT","message":"Note n1 (カ) leaves only 25 ms for 1 vowel(s); at least 30 ms are needed.","retryable":false,"path":"$.notes[0].beats","hint":"Give the note more beats, lower the tempo, or use fewer moras in the lyric.","detail":{"availableMs":25,"requiredMs":30,"noteId":"n1"},"repairOptions":[{"action":"increase-duration","description":"Give the note more beats or lower the tempo.","path":"$.notes[0].beats"},{"action":"use-vowel-continuation","description":"Move some moras to neighbouring notes or hold the previous vowel.","path":"$.notes[0].lyric"}]}}
61
+ ```
62
+
63
+ コマンドの完全な一覧と出力形式は [docs/cli.md](docs/cli.md)にあります。
64
+
65
+ ## テキストの読み方
66
+
67
+ 内蔵エンジンは次の順で文章を読みます。
68
+
69
+ 1. **正規化**: 日付 (`2026/09/07` → 2026年9月7日)、時刻 (`9:05` → 9時5分)、バージョン (`v1.2.3` → ブイ1テン2テン3)、単位 (`3ms` → 3ミリ秒、`100kg`、`25℃`)、通貨 (`¥1,200`、`$5`)、符号と範囲 (`-5`、`10〜20`)、`#42`、URL とメールアドレス (記号を読み下し、`URL_READ_LITERALLY` の助言付き)、Markdown の行頭記号、全角/半角。
70
+ 2. **英単語**: 約 500 語の技術系レキシコン (`npm`、`API`、`Claude Code`、`GitHub`、`deploy` …) をカタカナとアクセントに置き換えます。頭字語は「最後の文字の先頭にアクセント」(エーピーア'イ) で読み、フロントエンドが文字ごとに分割してしまう読みを 1 つのアクセント句にまとめます。未知の 5 文字以上の英単語には `ASCII_WORD_UNKNOWN` の助言が付きます。
71
+ 3. **形態素解析とアクセント**: jpreprocess (OpenJTalk の Rust 実装) と NAIST-JDic で読みとアクセント核、アクセント句境界を決めます。数詞・助数詞 (3件 → サン'ゲン、一本 → イッ'ポン)、助詞の付属、母音の無声化 (デ_ス) を含みます。
72
+ 4. **辞書**: リクエストの `dictionary`、`--dict-entry`、`--dictionary` ファイル (`KONGYOROID_DICTIONARY`) の順で表記を読みに置き換え、指定があればアクセントも上書きします。同じ読みが文中に複数ある場合は位置で照合するので、「橋の端」で `端 → ハシ (0)` を登録しても橋のアクセントは変わりません。
73
+ 5. **読めない文字**: フロントエンドが黙って落とす文字 (幽霊文字、ハングル、絵文字など) は既定で `UNREADABLE_TEXT` エラーになり、位置 (`sourceSpan`) と修正案 (かな指定・辞書追加・削除) を返します。`strictReading: false` (`--no-strict-reading`) なら警告付きで読み飛ばします。
74
+
75
+ 読みは `reading` コマンドか `plan` で確認できます。各アクセント句には `accentSource` (`frontend` / `dictionary` / `lexicon` / `user` / `rule`) が付き、どこから来た読みかが分かります。
76
+
77
+ ### かな記法
78
+
79
+ `kana` を与えるとテキスト解析を飛ばして、その通りに読みます。
80
+
81
+ | 記号 | 意味 | 例 |
82
+ | --- | --- | --- |
83
+ | `'` | 直前のモーラがアクセント核。無ければ平板 (0 型) | `ハ'シ` (橋)、`ハシ'` (端…尾高)、`ハシ` (平板) |
84
+ | `/` | アクセント句の境界 (ポーズなし) | `コンニチワ'/セカ'イ` |
85
+ | `、` | 短いポーズ (既定 0.2 秒) | `ハ'イ、ワカリマ'_シタ` |
86
+ | `。` `?` `!` | 文末。`?` は文末上昇、`!` は文全体を強める | `デ_スカ?` |
87
+ | `_` | 直後のモーラを無声化 | `_シテ`、`デ_ス` |
88
+ | `ー` | 長音 | `トーキョー` |
89
+
90
+ ひらがなでもカタカナでも構いません。`_` が 1 つも無い場合は、無声化規則 (無声子音に挟まれた イ・ウ、文末の ス) を自動で適用します。末尾の `、` は末尾ポーズとして残り、`。` などの文末記号は末尾に無音を足しません (末尾の無音は `postPause` で決めます)。
91
+
92
+ ## 読み上げのパラメータ
93
+
94
+ | フィールド (CLI フラグ) | 既定 | 内容 |
95
+ | --- | --- | --- |
96
+ | `voice` (`--voice`) | `neutral` | 内蔵ボイス: `neutral` `female` `male` `child` `soft` `bright` `deep` |
97
+ | `speed` (`--speed`) | 1 | 話速倍率 0.25–4。子音・母音・ポーズを一様に縮めます |
98
+ | `pitchSemitones` (`--pitch-semitones`) | 0 | 基本ピッチの半音シフト −24..24 |
99
+ | `pitch` (`--pitch`) | – | VOICEVOX 互換の `pitchScale` (F0 × 2^pitch)。`pitchSemitones` と排他 |
100
+ | `intonation` (`--intonation`) | 1 | 抑揚の幅 0–3。0 でほぼ平坦 |
101
+ | `volume` / `gainDb` | 1 / – | 出力レベル (線形 0–3、または dB)。ソフトリミッターの前段 |
102
+ | `breathiness` (`--breathiness`) | 0 | 声門の張り −1..1.5。正で息っぽく |
103
+ | `prePause` / `postPause` | 0.1 / 0.1 | 前後の無音 (秒) |
104
+ | `pauseLength` / `pauseScale` | – / 1 | `、` の絶対長 (秒) と、全ポーズの倍率 |
105
+ | `upspeak` (`--no-upspeak`) | true | 疑問文末の上昇 |
106
+ | `sampleRate` (`--sample-rate`) | 24000 | 8000–48000 Hz |
107
+ | `seed` (`--seed`) | 1 | ノイズ・揺らぎの種 |
108
+
109
+ イントネーションは藤崎モデル (フレーズ指令 + アクセント指令) で生成し、文末の下降、疑問の上昇、感嘆の強調、段落末の長いポーズを付けます。
110
+
111
+ ## 歌唱
112
+
113
+ 譜面は 3 つの形で渡せます。
114
+
115
+ ```jsonc
116
+ // 1. 音符リスト (最も細かい制御)
117
+ { "kind": "song", "tempo": 90, "voice": "male",
118
+ "notes": [
119
+ { "key": null, "beats": 0.5 },
120
+ { "id": "sa", "key": "E4", "beats": 1, "lyric": "さ" },
121
+ { "id": "ku", "key": "E4", "beats": 1, "lyric": "く", "velocity": 110 },
122
+ { "id": "ra", "key": "F4", "beats": 2, "lyric": "ら" },
123
+ { "id": "ra-hold", "key": "F4", "beats": 2, "continuation": "tie", "vibrato": { "depthCents": 45 } },
124
+ { "id": "ra-up", "key": "G4", "beats": 1, "continuation": "melisma" },
125
+ { "key": "C4", "beats": 2, "lyric": "きら" } // 1 音に複数モーラ (最大 8)
126
+ ] }
127
+
128
+ // 2. コンパクト譜 (歌詞 + 音名 + 拍)
129
+ { "kind": "song", "notes": { "lyrics": "きらきらぼし", "melody": "C4 C4 G4 G4 A4 ~ ~G4 R", "beats": "1 1 1 1 1 1 1 1" } }
130
+
131
+ // 3. MML
132
+ { "kind": "song", "notes": { "mml": "t132 o4 l8 e e r e r c e4 g4 r4 <g4", "lyrics": "ららららら" } }
133
+ ```
134
+
135
+ - `~` (タイ) は直前の母音を同じ高さで伸ばし、`~G4` (メリスマ) は高さを変えて伸ばします。母音は再アタックせず、ポルタメント (`portamentoMs`、既定 60 ms) で滑らかにつながります。
136
+ - 同じ母音が続く音符 (「ああ」) は既定で再アーティキュレーション (`rearticulate`: 短い減衰と再アタック) になり、`articulation: "legato"` で連結できます。
137
+ - `velocity` (1–127) または `gainDb` で音ごとの強さ、`vibrato` (`depthCents` / `rateHz` / `delayMs` / `fadeMs` または `false`) で持続音ごとのビブラート、`portamentoMs` で音ごとの移行時間を指定できます。`scoopCents` / `scoopMs` はフレーズ頭のしゃくりです。
138
+ - 子音は前の休符・前の音符の末尾 (最大 40 %) から借りて、母音が拍頭に乗るように配置します。足りない時は子音を短縮して `CONSONANT_COMPRESSED` を `adjustments` に記録し、`consonantCompression: false` なら `NOTE_TOO_SHORT` で失敗します。母音が 30 ms を切る音符は常に `NOTE_TOO_SHORT` です。
139
+ - 音域は 30–2500 Hz (かつサンプルレートの 20 %)。外れると `PITCH_OUT_OF_RANGE`、ボイスの得意音域を外れると `F0_OUTSIDE_VOICE_RANGE` の警告です。
140
+ - 音高精度: 持続母音で 1 セント以内、拍ごとに変わる音階で 8 セント以内 (テストで検証)。
141
+
142
+ `plan` の `notes[]` には音ごとの開始・母音開始・終了時刻、`sustainId`、`continuation`、`articulation` が入ります。
143
+
144
+ ## ストリーミング
145
+
146
+ ```sh
147
+ # 文が確定するたびに合成し、PCM (s16le mono) を流す
148
+ kongyoroid speak --input - --stream --output - --format pcm
149
+
150
+ # 未確定長 WAV / NDJSON (文イベント + base64 音声ブロック)
151
+ kongyoroid speak --input - --stream --output - --format wav
152
+ kongyoroid speak --input - --stream --output - --format ndjson
153
+
154
+ # ファイルへ (最後にヘッダーを書き戻す)
155
+ kongyoroid speak --input - --stream -o long.wav --progress
156
+ ```
157
+
158
+ 文の切れ目 (`。!?` と改行) で分割し、次の文を先読みして合成するので、途切れません。文間ポーズは次の文の先頭に付くため、一括合成した場合と同じ長さになります。ライブラリでは `agent.speakStream(asyncIterable)` が `sentence` / `audio` / `end` イベントを返します。
159
+
160
+ ## 内蔵ボイス
161
+
162
+ | id | 基本 F0 | 特徴 |
163
+ | --- | --- | --- |
164
+ | `neutral` | 170 Hz | 中性的な中音域。通知・検証の既定 |
165
+ | `female` | 225 Hz | 短めの声道、やや息混じり |
166
+ | `male` | 115 Hz | 長めの声道、張りのある声門 |
167
+ | `child` | 290 Hz | 小さな声道と高いピッチ |
168
+ | `soft` | 185 Hz | 息の多い穏やかな声、抑揚控えめ |
169
+ | `bright` | 215 Hz | 張った明瞭な声、抑揚大きめ |
170
+ | `deep` | 92 Hz | とても低い声、落ち着いた調子 |
171
+
172
+ `kongyoroid voices` で音域とハッシュを確認できます。歌唱でも同じボイスを使います。
173
+
174
+ ## キャッシュとファイル
175
+
176
+ - `--cache-dir DIR` (または `KONGYOROID_CACHE_DIR`) を与えると、`DIR/kongyoroid-cache/` の中だけに `.kcache` ファイルを書きます。`cache prune` / `cache clear` はこの名前空間の外に触りません。無関係なファイルが混ざっていても消しません。
177
+ - キャッシュキーはエンジン・パッケージ版・エンジン版・フロントエンド版・辞書ダイジェスト・正規化リクエストから作るので、更新後に古い音声が返ることはありません。
178
+ - 同時に同じリクエストが来た場合は 1 回だけ合成します (in-flight dedupe)。
179
+ - 出力は一時ファイルに書いてからハードリンク/リネームするので、途中で落ちても壊れたファイルは残りません。
180
+
181
+ ## ライブラリとして使う
182
+
183
+ ```ts
184
+ import { Kongyoroid } from "@kongyo2/kongyoroid";
185
+
186
+ const agent = new Kongyoroid({
187
+ voice: "female",
188
+ dictionary: [{ surface: "kongyoroid", reading: "コンギョロイド", accent: 0 }],
189
+ cache: { directory: "./cache" },
190
+ });
191
+
192
+ // 読み上げ
193
+ const speech = await agent.speak("kongyoroidは便利です。");
194
+ speech.audio; // Uint8Array (WAV)
195
+ speech.kana; // "コンギョロイドワ/ベ'ンリデ_ス。"
196
+
197
+ // 歌唱
198
+ const song = await agent.sing({ notes: { lyrics: "ドレミ", melody: "C4 D4 E4" }, tempo: 100 });
199
+
200
+ // 確認してから書き出す
201
+ const check = await agent.validate({ kind: "speech", text: "…" });
202
+ if (check.renderable) {
203
+ const plan = await agent.plan({ kind: "speech", text: "…" }, "phonemes");
204
+ const compiled = await agent.compile({ kind: "speech", text: "…" });
205
+ const result = await agent.renderPlan(compiled.plan, { requestHash: compiled.requestHash });
206
+ }
207
+
208
+ // 文単位のストリーミング
209
+ for await (const event of agent.speakStream(tokens())) {
210
+ if (event.type === "audio") play(event.block.samples); // Float32Array
211
+ }
212
+ ```
213
+
214
+ `Kongyoroid` の他に、テキスト処理 (`readJapanese`、`normalizeForReading`、`parseKanaNotation`、`LocalDictionary`)、計画 (`compileRequest`、`planSpeech`、`planSong`)、レンダリング (`PlanRenderer`、`renderPcm`、`renderPcmStream`、`encodePlanAsync`)、解析 (`estimatePitch`、`inspectWav`)、譜面 (`parseMml`、`parseScoreText`) を個別に import できます。型はすべて `dist/index.d.ts` に含まれます。
215
+
216
+ ## VOICEVOX (任意)
217
+
218
+ VOICEVOX ENGINE が起動していれば、`--speaker` / `--singer` / `--teacher` (id か名前) を付けるだけで、そのスタイルで合成します。`--engine auto` はエンドポイントが応答すれば VOICEVOX、応答しなければ内蔵エンジンにフォールバックします。`dict --scope voicevox` でユーザー辞書、`voices --engine voicevox` でスタイル一覧、`doctor --engine voicevox` で診断ができます。VOICEVOX の歌唱は 1 音 1 モーラで、タイ・メリスマ・複数モーラは内蔵エンジン専用です。
219
+
220
+ ## 制限と環境変数
221
+
222
+ | 項目 | 値 |
223
+ | --- | --- |
224
+ | テキスト / かな | 20,000 文字 |
225
+ | 音符 | 4,096 個 |
226
+ | 内蔵エンジンの 1 リクエスト | 1,800 秒 |
227
+ | 入力ファイル | 8 MiB |
228
+ | バッチ行数 / 並列度 | 10,000 / 16 |
229
+ | 辞書エントリ | 20,000 |
230
+
231
+ 環境変数: `KONGYOROID_ENGINE`、`KONGYOROID_VOICE`、`KONGYOROID_DICTIONARY`、`KONGYOROID_CACHE_DIR`、`KONGYOROID_ENDPOINT` (別名 `VOICEVOX_URL`)、`KONGYOROID_SPEAKER`、`KONGYOROID_SINGER`、`KONGYOROID_TEACHER`。`kongyoroid capabilities` が対応機能・制限・エラーコードを JSON で返します。
232
+
233
+ ## ドキュメント
234
+
235
+ - [docs/cli.md](docs/cli.md): コマンドと出力形式のリファレンス
236
+ - `examples/`: 内蔵エンジン向け (`builtin/`)、VOICEVOX 向け (`voicevox/`)、バッチ (`batch.jsonl`) の実例
237
+
5
238
  ## ライセンス
6
239
 
7
240
  MIT
package/dist/cache.d.ts CHANGED
@@ -1,8 +1,15 @@
1
1
  export declare function cacheKey(...parts: readonly unknown[]): string;
2
+ export interface CacheStats {
3
+ readonly entries: number;
4
+ readonly bytes: number;
5
+ readonly budget: number | null;
6
+ readonly directory?: string;
7
+ }
2
8
  export interface RenderCache {
3
9
  get(key: string): Promise<Uint8Array | undefined>;
4
10
  set(key: string, value: Uint8Array): Promise<void>;
5
- clear(): Promise<void>;
11
+ clear(): Promise<number>;
12
+ stats(): Promise<CacheStats>;
6
13
  }
7
14
  export declare class MemoryCache implements RenderCache {
8
15
  private readonly entries;
@@ -11,26 +18,44 @@ export declare class MemoryCache implements RenderCache {
11
18
  constructor(budgetBytes: number);
12
19
  get(key: string): Promise<Uint8Array | undefined>;
13
20
  set(key: string, value: Uint8Array): Promise<void>;
14
- clear(): Promise<void>;
15
- stats(): {
21
+ clear(): Promise<number>;
22
+ stats(): Promise<CacheStats>;
23
+ statsSync(): {
16
24
  readonly entries: number;
17
25
  readonly bytes: number;
18
26
  readonly budget: number;
19
27
  };
20
28
  }
29
+ export declare const CACHE_NAMESPACE: string;
30
+ export declare const CACHE_FORMAT: string;
31
+ export declare const CACHE_EXTENSION: string;
32
+ export interface DiskCacheOptions {
33
+ readonly maxBytes?: number;
34
+ readonly maxEntries?: number;
35
+ }
21
36
  export declare class DiskCache implements RenderCache {
22
- private readonly directory;
23
- constructor(directory: string);
37
+ readonly root: string;
38
+ readonly directory: string;
39
+ private readonly maxBytes;
40
+ private readonly maxEntries;
41
+ private prepared;
42
+ constructor(directory: string, options?: DiskCacheOptions);
24
43
  private pathFor;
44
+ private prepare;
25
45
  get(key: string): Promise<Uint8Array | undefined>;
26
46
  set(key: string, value: Uint8Array): Promise<void>;
27
- clear(): Promise<void>;
47
+ private entries;
48
+ stats(): Promise<CacheStats>;
49
+ clear(): Promise<number>;
50
+ prune(maxBytes?: number | undefined, maxEntries?: number | undefined): Promise<number>;
51
+ remove(): Promise<void>;
28
52
  }
29
53
  export declare class LayeredCache implements RenderCache {
30
54
  private readonly layers;
31
55
  constructor(layers: readonly RenderCache[]);
32
56
  get(key: string): Promise<Uint8Array | undefined>;
33
57
  set(key: string, value: Uint8Array): Promise<void>;
34
- clear(): Promise<void>;
58
+ clear(): Promise<number>;
59
+ stats(): Promise<CacheStats>;
35
60
  }
36
61
  //# sourceMappingURL=cache.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"cache.d.ts","sourceRoot":"","sources":["../src/cache.ts"],"names":[],"mappings":"AAKA,wBAAgB,QAAQ,CAAC,GAAG,KAAK,EAAE,SAAS,OAAO,EAAE,GAAG,MAAM,CAE7D;AAED,MAAM,WAAW,WAAW;IAC1B,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,GAAG,SAAS,CAAC,CAAC;IAClD,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACnD,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACxB;AAED,qBAAa,WAAY,YAAW,WAAW;IAC7C,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA0D;IAClF,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,IAAI,CAAa;gBAEN,WAAW,EAAE,MAAM;IAI/B,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,GAAG,SAAS,CAAC;IAQjD,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;IAkBlD,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAMtB,KAAK,IAAI;QAAE,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;KAAE;CAG9F;AAED,qBAAa,SAAU,YAAW,WAAW;IAC3C,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;gBAEhB,SAAS,EAAE,MAAM;IAIpC,OAAO,CAAC,OAAO;IAIF,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,GAAG,SAAS,CAAC;IAQjD,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;IAYlD,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAIpC;AAED,qBAAa,YAAa,YAAW,WAAW;IAC9C,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAyB;gBAE7B,MAAM,EAAE,SAAS,WAAW,EAAE;IAI1C,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,GAAG,SAAS,CAAC;IAY3C,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;IAIlD,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAGpC"}
1
+ {"version":3,"file":"cache.d.ts","sourceRoot":"","sources":["../src/cache.ts"],"names":[],"mappings":"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"}
package/dist/cache.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { createHash, randomUUID } from "node:crypto";
2
- import { mkdir, readFile, rename, unlink, writeFile } from "node:fs/promises";
2
+ import { mkdir, readFile, readdir, rename, rm, stat, unlink, writeFile } from "node:fs/promises";
3
3
  import { join, resolve } from "node:path";
4
4
  import { integer } from "./validate.js";
5
5
  export function cacheKey(...parts) {
@@ -40,23 +40,58 @@ export class MemoryCache {
40
40
  return Promise.resolve();
41
41
  }
42
42
  clear() {
43
+ const count = this.entries.size;
43
44
  this.entries.clear();
44
45
  this.used = 0;
45
- return Promise.resolve();
46
+ return Promise.resolve(count);
46
47
  }
47
48
  stats() {
49
+ return Promise.resolve({ entries: this.entries.size, bytes: this.used, budget: this.budget });
50
+ }
51
+ statsSync() {
48
52
  return { entries: this.entries.size, bytes: this.used, budget: this.budget };
49
53
  }
50
54
  }
55
+ export const CACHE_NAMESPACE = "kongyoroid-cache";
56
+ export const CACHE_FORMAT = "v2";
57
+ export const CACHE_EXTENSION = ".kcache";
58
+ const MARKER_NAME = "CACHEDIR.TAG";
59
+ const MARKER_TEXT = "Signature: 8a477f597d28d172789f06886806bc55\n# This directory is a kongyoroid render cache. Files here may be deleted at any time.\n";
60
+ const KEY_PATTERN = /^[0-9a-f]{64}$/u;
51
61
  export class DiskCache {
62
+ root;
52
63
  directory;
53
- constructor(directory) {
54
- this.directory = resolve(directory);
64
+ maxBytes;
65
+ maxEntries;
66
+ prepared;
67
+ constructor(directory, options = {}) {
68
+ this.root = resolve(directory);
69
+ this.directory = join(this.root, CACHE_NAMESPACE, CACHE_FORMAT);
70
+ this.maxBytes = options.maxBytes;
71
+ this.maxEntries = options.maxEntries;
55
72
  }
56
73
  pathFor(key) {
57
- return join(this.directory, key.slice(0, 2), `${key}.wav`);
74
+ return join(this.directory, key.slice(0, 2), `${key}${CACHE_EXTENSION}`);
75
+ }
76
+ prepare() {
77
+ this.prepared ??= (async () => {
78
+ await mkdir(this.directory, { recursive: true });
79
+ const marker = join(this.root, CACHE_NAMESPACE, MARKER_NAME);
80
+ try {
81
+ await stat(marker);
82
+ }
83
+ catch {
84
+ await writeFile(marker, MARKER_TEXT);
85
+ }
86
+ })().catch((error) => {
87
+ this.prepared = undefined;
88
+ throw error;
89
+ });
90
+ return this.prepared;
58
91
  }
59
92
  async get(key) {
93
+ if (!KEY_PATTERN.test(key))
94
+ return undefined;
60
95
  try {
61
96
  return new Uint8Array(await readFile(this.pathFor(key)));
62
97
  }
@@ -65,6 +100,9 @@ export class DiskCache {
65
100
  }
66
101
  }
67
102
  async set(key, value) {
103
+ if (!KEY_PATTERN.test(key))
104
+ return;
105
+ await this.prepare();
68
106
  const target = this.pathFor(key);
69
107
  const temp = `${target}.${randomUUID()}.tmp`;
70
108
  await mkdir(join(this.directory, key.slice(0, 2)), { recursive: true });
@@ -72,13 +110,98 @@ export class DiskCache {
72
110
  await writeFile(temp, value);
73
111
  await rename(temp, target);
74
112
  }
75
- catch {
113
+ catch (error) {
76
114
  await unlink(temp).catch(() => undefined);
115
+ throw error;
116
+ }
117
+ if (this.maxBytes !== undefined || this.maxEntries !== undefined)
118
+ await this.prune();
119
+ }
120
+ async entries() {
121
+ const out = [];
122
+ let shards;
123
+ try {
124
+ shards = await readdir(this.directory);
125
+ }
126
+ catch {
127
+ return out;
128
+ }
129
+ for (const shard of shards) {
130
+ if (!/^[0-9a-f]{2}$/u.test(shard))
131
+ continue;
132
+ let names;
133
+ try {
134
+ names = await readdir(join(this.directory, shard));
135
+ }
136
+ catch {
137
+ continue;
138
+ }
139
+ for (const name of names) {
140
+ const stem = name.endsWith(CACHE_EXTENSION) ? name.slice(0, -CACHE_EXTENSION.length) : undefined;
141
+ const isTemp = /\.tmp$/u.test(name);
142
+ if (stem === undefined || !KEY_PATTERN.test(stem)) {
143
+ if (isTemp)
144
+ out.push({ path: join(this.directory, shard, name), bytes: 0, mtime: 0 });
145
+ continue;
146
+ }
147
+ try {
148
+ const info = await stat(join(this.directory, shard, name));
149
+ out.push({ path: join(this.directory, shard, name), bytes: info.size, mtime: info.mtimeMs });
150
+ }
151
+ catch {
152
+ continue;
153
+ }
154
+ }
77
155
  }
156
+ return out;
157
+ }
158
+ async stats() {
159
+ const entries = (await this.entries()).filter((entry) => entry.mtime > 0);
160
+ let bytes = 0;
161
+ for (const entry of entries)
162
+ bytes += entry.bytes;
163
+ return { entries: entries.length, bytes, budget: this.maxBytes ?? null, directory: this.directory };
78
164
  }
79
165
  async clear() {
80
- const { rm } = await import("node:fs/promises");
81
- await rm(this.directory, { recursive: true, force: true });
166
+ const entries = await this.entries();
167
+ let removed = 0;
168
+ for (const entry of entries) {
169
+ try {
170
+ await unlink(entry.path);
171
+ removed += 1;
172
+ }
173
+ catch {
174
+ continue;
175
+ }
176
+ }
177
+ return removed;
178
+ }
179
+ async prune(maxBytes = this.maxBytes, maxEntries = this.maxEntries) {
180
+ const entries = (await this.entries()).filter((entry) => entry.mtime > 0).sort((a, b) => a.mtime - b.mtime);
181
+ let bytes = 0;
182
+ for (const entry of entries)
183
+ bytes += entry.bytes;
184
+ let count = entries.length;
185
+ let removed = 0;
186
+ for (const entry of entries) {
187
+ const overBytes = maxBytes !== undefined && bytes > maxBytes;
188
+ const overCount = maxEntries !== undefined && count > maxEntries;
189
+ if (!overBytes && !overCount)
190
+ break;
191
+ try {
192
+ await unlink(entry.path);
193
+ removed += 1;
194
+ bytes -= entry.bytes;
195
+ count -= 1;
196
+ }
197
+ catch {
198
+ continue;
199
+ }
200
+ }
201
+ return removed;
202
+ }
203
+ async remove() {
204
+ await rm(join(this.root, CACHE_NAMESPACE), { recursive: true, force: true });
82
205
  }
83
206
  }
84
207
  export class LayeredCache {
@@ -103,7 +226,13 @@ export class LayeredCache {
103
226
  await Promise.all(this.layers.map((layer) => layer.set(key, value)));
104
227
  }
105
228
  async clear() {
106
- await Promise.all(this.layers.map((layer) => layer.clear()));
229
+ const counts = await Promise.all(this.layers.map((layer) => layer.clear()));
230
+ return counts.reduce((sum, count) => sum + count, 0);
231
+ }
232
+ async stats() {
233
+ const all = await Promise.all(this.layers.map((layer) => layer.stats()));
234
+ const last = all.at(-1);
235
+ return last ?? { entries: 0, bytes: 0, budget: null };
107
236
  }
108
237
  }
109
238
  //# sourceMappingURL=cache.js.map
package/dist/cache.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"cache.js","sourceRoot":"","sources":["../src/cache.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"cache.js","sourceRoot":"","sources":["../src/cache.ts"],"names":[],"mappings":"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"}