--- title: "ふりがなAPIの core を OSS にしました — ja-furigana 0.1.0 stable リリース" description: "黒猫ゲーム部が運用してきたふりがな変換エンジンを、Rust crate ja-furigana と TOML 辞書 ja-furigana-dict の 2 リポジトリに分けて OSS 公開しました。2026-05-12 に 0.1.0 stable を cut、cargo add ja-furigana で自分のプロダクトに組み込めます。" url: https://ryuuneko.com/blog/api-core-oss-ja-furigana-010-stable published: 2026-05-15 08:39:09.810445 updated: 2026-06-16 09:16:43.979086 --- 黒猫ゲーム部が Discord 読み上げ Bot「ずんだー」やコメント読み上げプラグインのバックエンドとして使ってきた**ふりがな変換エンジン**を、Rust の OSS ライブラリとして切り出しました。 - **`ja-furigana`** — ライブラリ本体 + CLI + HTTP サーバー (MIT) - **`ja-furigana-dict`** — TOML 形式のふりがな辞書 (MIT) 両方とも crates.io / GitHub に公開済み、`cargo add ja-furigana` するだけで自分の Rust プロジェクトに日本語テキストの読み変換を組み込めます。 **2026-05-12 に `0.1.0` stable を cut しました。** ここから先は SemVer で互換を守ります(公開 API / TOML スキーマ / CLI 引数 / HTTP レスポンスは 0.1.x の間 additive only)。 > [ryuuneko.com のふりがな API](/?slug=furigana-api) は、もともと内製エンジン (DB 辞書 + 独自ロジック) で動いてきました。**現在は公開 API のコアもこの OSS の `ja-furigana` ライブラリに置き換え済み**で、辞書は TOML (`ja-furigana-dict`) を唯一の source of truth とし、旧 DB 辞書は撤去済みです。 HTTP インターフェース (`mode` / `text_b64` / `segmented` / `X-API-Key`) は OSS 側と互換に作ってあるので、self-host したい場合は同じ API として差し替えられます。 ## なぜ OSS にしたのか ふりがな API は元々、私たちの読み上げ Bot を支える内製エンジンでした。Rust + Lindera をベースに、辞書・文脈ルール・数値パイプラインを多層に組んだものを、運用しながら育ててきました。 外に出すことにした理由はだいたい次の 3 つです。 - **同じ問題で困っている人は多いはず** — 日本語の自然な読み上げは、形態素解析だけでは難しい - **辞書だけ別 repo にすれば、辞書だけ PR で改善できる** — エンジンと辞書を分離すれば、Rust が書けない人でも TOML 1 行追加で貢献できる - **黒猫ゲーム部の中だけに閉じておくのは惜しい** — Rust 製で軽量、ライセンス上配布しやすい ## 名前まわりで混乱しやすいところ 歴史的経緯で、crate 名と import 名が違います。最初に貼っておきます。 :::feature-grid{} cargo add | `ja-furigana` | crates.io 上の lib crate 名 use | `furigana` | Rust 上の import 名 (`use furigana::Furigana;`) cargo install | `ja-furigana-cli` | crates.io 上の CLI crate 名 バイナリ名 | `furigana` | インストール後の実行コマンド (`furigana lookup ...`) GitHub (本体) | [`RyuuNeko1107/ja-furigana`](https://github.com/RyuuNeko1107/ja-furigana) | lib + CLI + HTTP server GitHub (辞書) | [`RyuuNeko1107/ja-furigana-dict`](https://github.com/RyuuNeko1107/ja-furigana-dict) | 辞書 PR はこっち ::: `furigana` という crate 名は別 OSS に先取りされていたため `ja-` prefix で公開していますが、`[lib] name = "furigana"` の設定で `use` 側は `furigana` のままにしてあります。 ## 何が公開されているか ### `ja-furigana` リポジトリ ライブラリ本体に加えて、すぐ試せる CLI と HTTP サーバーを同梱しています。 ``` ja-furigana = "0.1" # lib として組み込み(マイナー追従。最新版は crates.io 参照) cargo install ja-furigana-cli # CLI として手元で試す ``` CLI は形態素辞書を `feature flag` で切り替えられます。 - **`dict-ipadic`** (default) — IPADIC ベース、現代語中心 - **`dict-unidic`** (cwj) — UniDic ベース。0.2.0 で予定しているイントネーション機能の base data 検討用 ### `ja-furigana-dict` リポジトリ ふりがな変換に使う TOML 辞書を分離しました。リリースは CalVer (`v2026.05.13.7` は 2026 年 5 月時点の例)。最新リリースは [dict リポジトリの Releases](https://github.com/RyuuNeko1107/ja-furigana-dict/releases) を参照してください。 辞書のボリュームは 2026 年 6 月時点でこのくらいです(**直書きの件数は古くなります。最新値は必ず repo の [`STATS.md`](https://github.com/RyuuNeko1107/ja-furigana-dict) を参照**してください。`STATS.md` は GitHub Actions で自動更新されます)。 | カテゴリ | エントリ数 | | --- | ---: | | 単漢字 (`core/unihan/*`、水準別 5 ファイル) | 42,318 | | 熟語 (`core/jukugo/*`、手動 PR メンテ) | 7,949 | | 単漢字 `[[kanji]]` block (default + 文脈分岐 reading) | 1,139 | | 異体字 (`core/compat.toml`、髙→高 等) | 435 | | 作品造語 (`core/works/*`、touhou 等) | 311 | | 外来語 (`core/loanwords/*`、Kubernetes / Docker / TypeScript 等) | 168 | | エンジンルール (`rules/`、助数詞 / 日付 / 大数 / 単位 / 文脈) | 180 | | **合計** | **52,500** | 辞書 PR は **PR を出してマージされれば、次の辞書リリースに自動的に含まれる**仕組みです。`STATS.md` も `[skip stats]` 以外の master push で auto-commit されるので、contributor 側は TOML を編集して出すだけで OK にしています。 ### 登録語句検索 — 辞書をブラウザで眺める 辞書の中身をブラウザから検索・閲覧できる **[登録語句検索ページ](https://ryuuneko1107.github.io/ja-furigana-dict/)** を GitHub Pages で公開しています。 > 「この単語、辞書に入ってるかな?」と思ったときに、Rust も TOML も触らずに確認できます。 - **検索 / pagination** — 表層形 / 読みで絞り込み - **熟語 view / 単漢字 view** — `[[kanji]]` block 形式の文脈分岐ルールも閲覧可能 - **audit dashboard** — 単漢字や冗長 entry の sweep 補助 (PR を出す前のチェック用) 辞書が master push されると GitHub Actions で自動再生成されるので、表示内容は常に最新の master と同期しています。 ## アーキテクチャ — Smart engine + 6 provider ja-furigana の読み解決は、**候補生成 → Viterbi 風のパス選択** という流れに整理されています(0.1.0 stable で旧 priority chain は撤廃済み)。 :::step-list{} **テキスト正規化** — Unicode NFKC 正規化 + 異体字マッピング (髙→高 等) **候補生成 (6 provider)** — 入力文に対して、複数の provider が「ここからここまでをこの読みで読む」候補を出す **パス選択 (Viterbi-like + band lexicographic 比較)** — 候補同士を文単位で組み合わせ、band (`1000 = dict > 950 = 数字/助数詞 > 150 = Lindera 漢字熟語 > 100 = 単漢字 default > 50 = Lindera fallback`) と境界ペナルティで最良パスを選ぶ **後処理** — モード別の正規表現置換、TTS モードでは句読点を休止に置換 ::: 候補を出す 6 つの provider: :::feature-grid{} ProtectToken | 保護トークン抽出 (URL / Email / 絵文字を素通し) AlphabetPassthrough | アルファベット passthrough + 外来語辞書 lookup (Kubernetes / Docker 等) DictBridge | 辞書 hit (jukugo / unihan / `[[kanji]]` block の match) NumberCandidate | 数字 + 助数詞 + 大数スケール + SI 単位 + 日付 + 時刻 Odoriji | 踊り字「々」の連濁処理 (人々 → ひとびと) LinderaFallback | Lindera 形態素解析による band 50 のセーフティネット ::: 「答えを 1 つに絞った辞書」ではなく「**候補を出す辞書**」に作り変えたのが 0.1.0 の大きな変化です。これによって「辞書が誤った答えで決め打ちすると間違いが固定化する」問題を避け、文単位で見たときに最も自然な組み合わせを選べるようになりました。 詳しくは `docs/ARCHITECTURE.md` と `docs/PROPOSALS/scoring-engine.md` を見てください。 ## 期待値の話 `ja-furigana` を試してもらう前に、現実的な期待値について書いておきます。 ### 辞書はまだ小さいので、誤読は普通にあります 52,500 entries という数字は一見大きく見えますが、**日本語の語彙全体から見ると正直まだ小さい**です。特に弱いところ: - **人名・地名** — 「○○さん」「○○市」みたいな固有名詞は、辞書未登録だと当然外します - **新語・専門用語** — IT 用語の主要どころは `core/loanwords/` で拾っていますが、ニッチな業界用語や流行り言葉は穴だらけ - **同字異義語の文脈読み分け** — 「行く / 行った」「人 / 二人」のような形でも、`[[kanji]]` block で個別に書いた範囲しかカバーしていません なので、「自分のユースケースで使ってみたら誤読がある」のは普通に起こります。**そのときに辞書 PR で直せる**設計にしてあるのが、このプロジェクトの一番の特徴です。 ### VOICEVOX を使うなら、単体との差は小さいです VOICEVOX には OpenJTalk が内蔵されていて、日本語テキストをそのまま投げれば VOICEVOX 自身が読みを推定します。なので、**VOICEVOX で読み上げるだけが目的なら、ja-furigana を挟まなくても VOICEVOX 単体でそれなりに読めます**。劇的に読みが変わるわけではありません。 ja-furigana を挟む意味があるのは、 - **TOML 辞書を PR で直接編集できる** — VOICEVOX 内蔵 g2p の読みは外から修正できないが、ja-furigana の読みは辞書 PR で直せる - **VOICEVOX 以外の TTS でも同じ読みを使い回せる** — OpenAI TTS / Aques / クラウド TTS など - **TTS 以外の用途にも使える** — Web ページの `` 自動生成、配信テロップの難読語チェック、DB の人名・地名フィールドへの読みフリガナ付与 「読みのコントロールを持ちたい」「TTS 以外でも使いたい」のときに価値が出るライブラリです。**VOICEVOX 単体で困っていないなら、無理に挟む必要はありません**。 ### 苦手なこと その他、ライブラリ自体の方針として苦手なところ: - **超高精度な文脈読み分け** — ニューラル推論 (BERT 等) は持ち込まない方針 - **古文 / 文語 / 方言** — IPADIC ベースなので現代語が中心 - **辞書にない読みの自動推定** — 「データ駆動 + 決定論」が設計の核なので、「辞書になければ Lindera の素朴な読みに fall back」までしかやりません 読みの上積みは、**コミュニティ PR による辞書拡充**で進める設計になっています。 ## 開発の裏側 — AI 駆動で書いています 少し裏話を。 `ja-furigana` (OSS lib + 辞書 + CLI + HTTP server + doc + corpus regression test 一式) は、**ほぼ全工程を Claude Opus 4.7 を pair programmer として AI 駆動開発**で書いています。 黒猫ゲーム部の中の人は職業エンジニアではありませんが、 **AI が無かった時代は WEB 系 (PHP / JS / HTML / CSS あたり) を自分で書いていた**人間です。 その他の言語も基礎レベルでは触ってきていて、 「この言語はここが強くてここが弱い」 くらいの感覚はそれなりに持っているつもりです。 ここ最近は、 デザイン面の弱さなどを AI に補ってもらう比率が段々増え、 Rust や OSS lib 公開のような今まで踏み込めなかった領域には特に AI を相棒にして踏み出している、 というのが正直なところです (自分で書ける部分も残っていますが、 ここしばらくは自分では書いていません)。 旧バージョンの内製ふりがな API で AI を使って精度を追い込んだ話は[別記事](/?slug=furigana-ai-accuracy) (※旧バージョン基準) にも書きましたが、 **OSS lib 化以降も同じスタイル**で進めています。 - **AI が担当している部分** (= 実装の手を動かす側): Rust コードの書き起こし / TOML 編集 / corpus regression テスト生成 / doc 本文の文章化 / `clippy` 指摘の修正 / `CHANGELOG.md` の整形 - **設計は全部人間がやっています**: アーキテクチャ (Smart engine への移行や Strict 削除、 6 provider への分割、 band lexicographic 比較の方針) / TOML スキーマ (`[meta] schema_version = "2"` / `[[kanji]]` block の matcher vocabulary / bracket notation を 0.2.0 用に forward compat strip しておく判断 等) / API 表面 (`Furigana` / `FuriganaBuilder` のシグネチャと SemVer 約束) - **セキュリティ / 運用面も人間判断**: プライバシー方針 (テレメトリを入れない / lib に学習機能を持ち込まない / 集計 counter と raw_context の切り分け) / 辞書 tarball の SHA-256 検証 / HTTP server の rate limit / `X-API-Key` 認証 / signal_log の size rotation / OSS としての哲学 - **その他、人間が必ず判断するもの**: 辞書 PR の最終 review / 「日本語として自然か」 の最終判断 / `[[kanji]]` block の context rule が本当に妥当か / dict / lib のリリース cut タイミング AI 出力は**仮説として扱う** — そのまま信用しない、 corpus regression / human review を必ず挟む、 というワークフローでぐるぐる回しています。 「いろんな言語を基礎レベルで触ってきた WEB 系の独学者が、 Rust 本格 + OSS lib 公開という今までやってこなかった領域に AI を相棒に踏み出して 0.1.0 stable まで持っていけた事例」 として面白がってもらえれば嬉しいです。 これからの個人 OSS 開発のひとつの形だと思っています。 ## インストールと使い方 ### CLI で試す (一番手軽) ``` cargo install ja-furigana-cli echo "今日は3月14日です。" | furigana --mode tts # => きょうは さんがつじゅうよっか です ``` ### Rust プロジェクトに組み込む ```toml [dependencies] ja-furigana = "0.1" # マイナー追従。最新版は crates.io を参照 ``` ```rust use furigana::Furigana; fn main() { let furigana = Furigana::new(); let result = furigana.to_hiragana("漢字を平仮名に変換します。"); println!("{}", result); // => かんじをひらがなにへんかんします。 } ``` 辞書を読み込ませる場合は、`furigana dict pull` で GitHub Release から tar.gz を取得 (SHA-256 検証付き) して `FuriganaBuilder` に渡します。詳細は repo の `README.md`。 ### HTTP サーバーとして動かす ``` git clone https://github.com/RyuuNeko1107/ja-furigana cd ja-furigana cargo run --bin furigana-server ``` `POST /furigana` に `{"text": "...", "mode": "tts"}` を投げると、ryuuneko.com 上で動いているのと同じ形式の JSON が返ってきます。`SIGHUP` または `POST /admin/reload` で辞書のホットリロードも可能です。 ## 公開 API も OSS lib に統一しました `ryuuneko.com/furigana` で動いている**ふりがな API のコアも、この OSS lib に置き換え済み**です。かつての「DB 辞書 + 内製ロジック + OSS lib」の混在期を経て、現在は `ja-furigana` lib 一本化が完了し、辞書は TOML (`ja-furigana-dict`) を唯一の source of truth としています(旧 DB 辞書は撤去済み)。 lib 一本化と並行して、**辞書改善のためのデータ収集**も導入しました。具体的にはこういう仕組みを公開 API 側に組み込んでいます。 - **改善 signal の集計 counter** — どの単漢字に Lindera fallback がヒットしたか、どのトークンが辞書未登録だったか等を、**集計値だけ**専用ファイル (size rotation あり) に書き出す - **`raw_context` opt-in 収集** — fallback hit したトークンの前後 N=2 トークンだけ、辞書改善判断材料として保存できる (opt-in) - 集まったデータから「辞書に足したい候補」を抽出 → 黒猫ゲーム部側で**人手レビューしてから** PR を出す、というワークフローに乗せる ### プライバシーの方針 ここは特に明示しておきます。 - **生コメント全文は構造的に保存しません** — 集計 counter は読みの統計値のみ、`raw_context` も hit token 周辺 N=2 トークンに限定 - **OSS ライブラリ側にはテレメトリ機能を入れません** — `ja-furigana` lib 自体にはユーザー入力を送信 / 保存する仕組みは一切ありません。データ収集は「黒猫ゲーム部が運用する公開 API サーバー側」だけで行われ、self-host した場合は当然データは黒猫ゲーム部に届きません - **改善 signal の抽出 API は `inspect` 系の純関数** — `extract_dict_gap_candidates` のような形で OSS lib に置かれていますが、これは「入力テキストに対して dict 未登録 surface を抽出する関数」であって、勝手にどこかに送信したりはしません。 caller (公開 API サーバー) が**意図的に集計してファイルに書き出す**設計です 「データ駆動で辞書が育つ」OSS にしたいので、**プライバシーと OSS の純粋さを犠牲にしない形で改善ループを回す**ことを最優先しています。 ## これから — 0.2.0 でイントネーション `0.1.0` stable は「**文脈依存ふりがな振りが確実に動く**」段階で cut しました。 次の `0.2.0` stable に向けては、**イントネーション (アクセント・韻律) 対応**が目玉になります。 - **bracket notation** (`[`, `]`, `/`) の parse 実装 — 0.1.0 では forward compat で strip だけしている記法 - **`--mode=voicevox-query`** — VOICEVOX の `/synthesis` に直叩きできる `AccentPhrase[]` JSON 出力 (pitch / mora pause length 込み) - **`--mode=voicevox-aques`** — AquesTalk 風記法での出力 - **`--mode=accent`** — エンジン非依存の中立 accent annotation JSON - **動的 accent shift rules** — 連濁 / 動詞活用 / 複合語 deaccenting / 助数詞拡充 stable cut は**ライブラリの完成度ドリブン**で、期日駆動ではありません。「いつ 0.2.0 が出るか」よりも「**出たときに壊れていない**」を優先しています。 ## 貢献の入口 ### 辞書 PR (おすすめ) 「この単語の読みがおかしい」と気づいたら、`ja-furigana-dict` の TOML ファイルに数行追加するだけで PR を出せます。エンジン側の Rust を理解する必要はありません。 ```toml # core/jukugo/general.toml 等に追加 [entries.所謂] reading = "イワユル" ``` 文脈依存の読み分け (例: 「一日」→ ツイタチ / イチニチ) は `[[kanji]]` block で書けます (`docs/RECIPES.md` に cookbook あり)。 ### ライブラリの Issue / PR エンジン側のバグ報告や機能提案は `ja-furigana` の Issue へどうぞ。`ROADMAP.md` の範囲外の大きな機能追加は、まず Issue で議論してからの方が安全です。 ### こんな貢献は受け入れが難しいです OSS の方針として最初に書いておきます。 - **形態素解析エンジンの差し替え** — Lindera を前提に最適化を入れているため、別エンジンへの差し替え PR は受け入れが難しいです - **テレメトリ / 学習機能** — OSS ライブラリ側にユーザー入力を収集する仕組みは入れない方針です。改善はコーパス + 手書き PR で進めます ## まとめ `ja-furigana` は、黒猫ゲーム部が運用してきたふりがな API の**核**を OSS として切り出したものです。 ryuuneko.com の公開 API も**この OSS lib に統一済み**で、辞書は TOML を唯一の source of truth とし、privacy-safe な辞書改善データ収集も導入しています。 - **試したい**: `cargo install ja-furigana-cli` → `echo "..." | furigana --mode tts` - **プロダクトに組み込みたい**: `ja-furigana = "0.1"`(最新版は crates.io 参照) - **読みを直したい**: [ja-furigana-dict](https://github.com/RyuuNeko1107/ja-furigana-dict) に PR (TOML 編集だけで OK) - **エンジンのバグ報告**: [ja-furigana](https://github.com/RyuuNeko1107/ja-furigana) に Issue API そのものの使い方は[ふりがな API ドキュメント](/?slug=furigana-api)も合わせてどうぞ。技術的な質問は[お問い合わせフォーム](/contact/)からお気軽に。 > **既存記事についての注記**: [ふりがな API ドキュメント](/?slug=furigana-api) と [ふりがな API の精度を生成 AI と一緒に追い込んだ話](/?slug=furigana-ai-accuracy) は、**OSS 化以前の旧バージョン (DB 辞書 + 独自ロジック時代) の記述**を含んでいます。アーキテクチャ・パイプライン構成・辞書件数などが現在の `ja-furigana` (Smart engine + 6 provider + TOML 辞書) とは異なります。これらの記事は**今後、OSS lib 一本化に合わせて書き直す予定**です。最新の挙動を知りたい場合は本記事と [GitHub の README](https://github.com/RyuuNeko1107/ja-furigana) を参照してください。 --- *※本記事は2026年6月時点の情報をもとにしています。サービス・コマンド・仕様は予告なく変わることがあります。*