[{"data":1,"prerenderedAt":1177},["ShallowReactive",2],{"content-/ja-furigana-tts-reading":3,"related-/ja-furigana-tts-reading":1127,"all-pages-for-dir":1175,"og-image-/ja-furigana-tts-reading":1176},{"id":4,"title":5,"body":6,"category":1108,"description":1109,"extension":1110,"meta":1111,"navigation":277,"path":1112,"project_name":1113,"published":1114,"publishedAt":1115,"seo":1116,"stem":1117,"tags":1118,"todo":1125,"unpublished":1114,"updatedAt":1125,"__hash__":1126},"pages/2026-06/2026-06-12/ja-furigana-tts-reading.md","ja-furigana——文脈を見て「正しい読み」を当てるRust製OSSがTTSの読み間違い対策に効く",{"type":7,"value":8,"toc":1090},"minimark",[9,13,22,54,58,65,72,120,127,130,133,136,190,193,222,232,235,240,316,320,337,467,487,490,497,501,512,563,566,666,669,672,764,794,801,822,826,839,842,905,916,920,923,976,983,987,993,1001,1023,1027,1034,1041,1055,1058,1061,1080,1086],[10,11,5],"h1",{"id":12},"ja-furigana文脈を見て正しい読みを当てるrust製ossがttsの読み間違い対策に効く",[14,15,16,17,21],"p",{},"日本語の文章に、文脈を見て「正しい読み」を当ててくれるOSS ",[18,19,20],"strong",{},"ja-furigana"," を動かしてみた。「一日署長」を「いちにちしょちょう」、「明日」を「あした」と読み分けてくれる。HTTPサーバーも内蔵しているので、Claude CodeやCodexからPOSTすれば正規化済みの読みがJSONで返ってくる。TTS（音声合成）の読み間違い対策として、かなり本命に近いライブラリだと思う。",[23,24,25,38,46],"ul",{},[26,27,28,29],"li",{},"開発者ブログ: ",[30,31,37],"a",{"href":32,"target":33,"rel":34},"https://ryuuneko.com/blog/api-core-oss-ja-furigana-010-stable","_blank",[35,36],"noopener","noreferrer","→ ja-furigana 0.1.0 stable リリース記事（ryuuneko.com）",[26,39,40,41],{},"リポジトリ: ",[30,42,45],{"href":43,"target":33,"rel":44},"https://github.com/RyuuNeko1107/ja-furigana",[35,36],"→ RyuuNeko1107/ja-furigana（GitHub）",[26,47,48,49],{},"辞書リポジトリ: ",[30,50,53],{"href":51,"target":33,"rel":52},"https://github.com/RyuuNeko1107/ja-furigana-dict",[35,36],"→ RyuuNeko1107/ja-furigana-dict（GitHub）",[55,56,57],"h2",{"id":57},"ja-furiganaとは",[14,59,60,61,64],{},"Discord読み上げBot「ずんだー」で使われてきた",[18,62,63],{},"ふりがな変換エンジンを、Rust製OSSとして切り出したもの","。形態素解析（Lindera）だけでは届かない「文脈に応じた読み分け」を、データ駆動の辞書・ルールで補うのがコンセプト。",[14,66,67,68,71],{},"設計上のポイントは",[18,69,70],{},"エンジンと辞書の分離",":",[73,74,75,91],"table",{},[76,77,78],"thead",{},[79,80,81,85,88],"tr",{},[82,83,84],"th",{},"リポジトリ",[82,86,87],{},"中身",[82,89,90],{},"ライセンス",[92,93,94,108],"tbody",{},[79,95,96,102,105],{},[97,98,99],"td",{},[100,101,20],"code",{},[97,103,104],{},"ライブラリ本体 + CLI + HTTPサーバー（Rust）",[97,106,107],{},"MIT",[79,109,110,115,118],{},[97,111,112],{},[100,113,114],{},"ja-furigana-dict",[97,116,117],{},"TOML形式のふりがな辞書",[97,119,107],{},[14,121,122,123,126],{},"辞書がTOMLの手書きファイルなので、",[18,124,125],{},"Rustを書けなくても辞書PRだけで貢献できる","。誤読を見つけたら該当TOMLを直してPRを出せば、マージ後の次リリースに自動的に含まれる仕組み。",[14,128,129],{},"なお開発自体も「AI駆動開発」で、Rustコードの実装・テスト生成・ドキュメント化はAI（Claude Opus 4.7）、アーキテクチャ設計・スキーマ定義・辞書PRレビューは人間、という分担で作られているとブログに明記されている。",[55,131,132],{"id":132},"実際に試した読み分け",[14,134,135],{},"手元で試して効いた例:",[73,137,138,151],{},[76,139,140],{},[79,141,142,145,148],{},[82,143,144],{},"入力",[82,146,147],{},"出力（読み）",[82,149,150],{},"コメント",[92,152,153,164,175],{},[79,154,155,158,161],{},[97,156,157],{},"一日署長",[97,159,160],{},"いちにちしょちょう",[97,162,163],{},"「ついたち」「いちにち」の文脈判定が必要な難所",[79,165,166,169,172],{},[97,167,168],{},"明日",[97,170,171],{},"あした",[97,173,174],{},"「あす」「みょうにち」と多義",[79,176,177,180,183],{},[97,178,179],{},"今日",[97,181,182],{},"きょう / こんにち",[97,184,185,186,189],{},"accent/analyzeモードで",[18,187,188],{},"候補と重み付き","で返る（後述）",[14,191,192],{},"一方で外す語もある:",[73,194,195,206],{},[76,196,197],{},[79,198,199,201,203],{},[82,200,144],{},[82,202,147],{},[82,204,205],{},"正しくは",[92,207,208],{},[79,209,210,213,219],{},[97,211,212],{},"辛いラーメン",[97,214,215,218],{},[18,216,217],{},"つらい","ラーメン",[97,220,221],{},"からいラーメン",[14,223,224,225,227,228,231],{},"「辛い」は「からい/つらい」の多義語で、後続の名詞（ラーメン）を見れば「からい」一択なのだが、現状は判定できなかった。ただしこの種の文脈ルールは ",[100,226,114],{}," の ",[100,229,230],{},"[[kanji]]"," ブロックや文脈ルールTOMLで改善されていく構造なので、辞書PRで直せる類いの弱点ではある。",[55,233,234],{"id":234},"インストールと基本の使い方",[236,237,239],"h3",{"id":238},"cli","CLI",[241,242,247],"pre",{"className":243,"code":244,"language":245,"meta":246,"style":246},"language-bash shiki shiki-themes vitesse-light vitesse-light","cargo install ja-furigana-cli\n# GitHub ReleasesからOS別バイナリの取得、Dockerでの実行も可能\n\necho \"今日は3月14日です。\" | furigana --mode tts\n# => きょうは さんがつじゅうよっか です\n","bash","",[100,248,249,265,272,279,310],{"__ignoreMap":246},[250,251,254,258,262],"span",{"class":252,"line":253},"line",1,[250,255,257],{"class":256},"senZ8","cargo",[250,259,261],{"class":260},"sdGka"," install",[250,263,264],{"class":260}," ja-furigana-cli\n",[250,266,268],{"class":252,"line":267},2,[250,269,271],{"class":270},"sxvE3","# GitHub ReleasesからOS別バイナリの取得、Dockerでの実行も可能\n",[250,273,275],{"class":252,"line":274},3,[250,276,278],{"emptyLinePlaceholder":277},true,"\n",[250,280,282,286,290,293,296,300,303,307],{"class":252,"line":281},4,[250,283,285],{"class":284},"sz8Xr","echo",[250,287,289],{"class":288},"sMJiu"," \"",[250,291,292],{"class":260},"今日は3月14日です。",[250,294,295],{"class":288},"\"",[250,297,299],{"class":298},"stQ0i"," |",[250,301,302],{"class":256}," furigana",[250,304,306],{"class":305},"snbK4"," --mode",[250,308,309],{"class":260}," tts\n",[250,311,313],{"class":252,"line":312},5,[250,314,315],{"class":270},"# => きょうは さんがつじゅうよっか です\n",[236,317,319],{"id":318},"rustライブラリとして","Rustライブラリとして",[241,321,325],{"className":322,"code":323,"language":324,"meta":246,"style":246},"language-toml shiki shiki-themes vitesse-light vitesse-light","[dependencies]\nja-furigana = \"0.1\"\n","toml",[100,326,327,332],{"__ignoreMap":246},[250,328,329],{"class":252,"line":253},[250,330,331],{},"[dependencies]\n",[250,333,334],{"class":252,"line":267},[250,335,336],{},"ja-furigana = \"0.1\"\n",[241,338,342],{"className":339,"code":340,"language":341,"meta":246,"style":246},"language-rust shiki shiki-themes vitesse-light vitesse-light","use furigana::Furigana;\n\nfn main() {\n    let furigana = Furigana::new();\n    let result = furigana.to_hiragana(\"漢字を平仮名に変換します。\");\n    println!(\"{}\", result);\n    // => かんじをひらがなにへんかんします。\n}\n","rust",[100,343,344,363,367,381,403,433,455,461],{"__ignoreMap":246},[250,345,346,350,352,355,359],{"class":252,"line":253},[250,347,349],{"class":348},"sHkkW","use",[250,351,302],{"class":256},[250,353,354],{"class":298},"::",[250,356,358],{"class":357},"sSkh3","Furigana",[250,360,362],{"class":361},"shFtX",";\n",[250,364,365],{"class":252,"line":267},[250,366,278],{"emptyLinePlaceholder":277},[250,368,369,372,375,378],{"class":252,"line":274},[250,370,371],{"class":348},"fn",[250,373,374],{"class":256}," main",[250,376,377],{"class":361},"()",[250,379,380],{"class":361}," {\n",[250,382,383,386,389,392,395,397,400],{"class":252,"line":281},[250,384,385],{"class":298},"    let",[250,387,302],{"class":388},"s4oTP",[250,390,391],{"class":361}," =",[250,393,394],{"class":357}," Furigana",[250,396,354],{"class":298},[250,398,399],{"class":256},"new",[250,401,402],{"class":361},"();\n",[250,404,405,407,410,412,414,417,420,423,425,428,430],{"class":252,"line":312},[250,406,385],{"class":298},[250,408,409],{"class":388}," result",[250,411,391],{"class":361},[250,413,302],{"class":388},[250,415,416],{"class":298},".",[250,418,419],{"class":256},"to_hiragana",[250,421,422],{"class":361},"(",[250,424,295],{"class":288},[250,426,427],{"class":260},"漢字を平仮名に変換します。",[250,429,295],{"class":288},[250,431,432],{"class":361},");\n",[250,434,436,439,441,443,446,448,451,453],{"class":252,"line":435},6,[250,437,438],{"class":256},"    println!",[250,440,422],{"class":361},[250,442,295],{"class":288},[250,444,445],{"class":361},"{}",[250,447,295],{"class":288},[250,449,450],{"class":361},",",[250,452,409],{"class":388},[250,454,432],{"class":361},[250,456,458],{"class":252,"line":457},7,[250,459,460],{"class":270},"    // => かんじをひらがなにへんかんします。\n",[250,462,464],{"class":252,"line":463},8,[250,465,466],{"class":361},"}\n",[14,468,469,470,472,473,475,476,479,480,483,484,486],{},"crate名は ",[100,471,20],{}," だが、",[100,474,349],{}," する名前は ",[100,477,478],{},"furigana","、CLIのcrateは ",[100,481,482],{},"ja-furigana-cli","、バイナリ名は ",[100,485,478],{},"。最初ちょっと混乱するので注意。",[236,488,489],{"id":489},"辞書の取得",[14,491,492,493,496],{},"エンジン本体には熟語辞書が同梱されないため、",[100,494,495],{},"furigana dict pull"," でGitHub Releasesから辞書（tar.gz、SHA-256検証付き）を取得する。辞書なしでも形態素解析ベースで動くが、熟語ヒット・助数詞・文脈ルールが無効のdegraded modeになる。",[55,498,500],{"id":499},"httpサーバーclaude-code-codexから叩ける","HTTPサーバー——Claude Code / Codexから叩ける",[14,502,503,504,507,508,511],{},"ここが今回いちばん刺さったところ。",[100,505,506],{},"furigana serve"," でローカルHTTPサーバーが立つ（デフォルト ",[100,509,510],{},"127.0.0.1:8000","）。",[241,513,515],{"className":243,"code":514,"language":245,"meta":246,"style":246},"furigana serve                       # 127.0.0.1:8000\nfurigana serve --auto-pull           # 起動前に辞書を自動pull\nFURIGANA_TOKEN=\u003Csecret> furigana serve   # 認証有効化\n",[100,516,517,527,539],{"__ignoreMap":246},[250,518,519,521,524],{"class":252,"line":253},[250,520,478],{"class":256},[250,522,523],{"class":260}," serve",[250,525,526],{"class":270},"                       # 127.0.0.1:8000\n",[250,528,529,531,533,536],{"class":252,"line":267},[250,530,478],{"class":256},[250,532,523],{"class":260},[250,534,535],{"class":305}," --auto-pull",[250,537,538],{"class":270},"           # 起動前に辞書を自動pull\n",[250,540,541,544,547,550,553,556,558,560],{"class":252,"line":274},[250,542,543],{"class":388},"FURIGANA_TOKEN",[250,545,546],{"class":361},"=",[250,548,549],{"class":298},"\u003C",[250,551,552],{"class":260},"secret",[250,554,555],{"class":298},">",[250,557,302],{"class":256},[250,559,523],{"class":260},[250,561,562],{"class":270},"   # 認証有効化\n",[236,564,565],{"id":565},"エンドポイント",[241,567,569],{"className":243,"code":568,"language":245,"meta":246,"style":246},"# ヘルスチェック（認証不要）。dict_sizeが0なら辞書未配置\ncurl http://127.0.0.1:8000/healthz\n# => {\"status\":\"ok\",\"dict_size\":44354}\n\n# GET でもPOSTでも叩ける\ncurl 'http://127.0.0.1:8000/furigana?text=灰桜の道&mode=ruby'\n# => {\"result\":\"{灰桜|はいざくら}の{道|みち}\",\"mode\":\"ruby\"}\n\ncurl -X POST http://127.0.0.1:8000/furigana \\\n  -H 'Content-Type: application/json' \\\n  -d '{\"text\":\"一日署長を務めた\",\"mode\":\"tts\"}'\n",[100,570,571,576,584,589,593,598,611,616,620,637,653],{"__ignoreMap":246},[250,572,573],{"class":252,"line":253},[250,574,575],{"class":270},"# ヘルスチェック（認証不要）。dict_sizeが0なら辞書未配置\n",[250,577,578,581],{"class":252,"line":267},[250,579,580],{"class":256},"curl",[250,582,583],{"class":260}," http://127.0.0.1:8000/healthz\n",[250,585,586],{"class":252,"line":274},[250,587,588],{"class":270},"# => {\"status\":\"ok\",\"dict_size\":44354}\n",[250,590,591],{"class":252,"line":281},[250,592,278],{"emptyLinePlaceholder":277},[250,594,595],{"class":252,"line":312},[250,596,597],{"class":270},"# GET でもPOSTでも叩ける\n",[250,599,600,602,605,608],{"class":252,"line":435},[250,601,580],{"class":256},[250,603,604],{"class":288}," '",[250,606,607],{"class":260},"http://127.0.0.1:8000/furigana?text=灰桜の道&mode=ruby",[250,609,610],{"class":288},"'\n",[250,612,613],{"class":252,"line":457},[250,614,615],{"class":270},"# => {\"result\":\"{灰桜|はいざくら}の{道|みち}\",\"mode\":\"ruby\"}\n",[250,617,618],{"class":252,"line":463},[250,619,278],{"emptyLinePlaceholder":277},[250,621,623,625,628,631,634],{"class":252,"line":622},9,[250,624,580],{"class":256},[250,626,627],{"class":305}," -X",[250,629,630],{"class":260}," POST",[250,632,633],{"class":260}," http://127.0.0.1:8000/furigana",[250,635,636],{"class":305}," \\\n",[250,638,640,643,645,648,651],{"class":252,"line":639},10,[250,641,642],{"class":305},"  -H",[250,644,604],{"class":288},[250,646,647],{"class":260},"Content-Type: application/json",[250,649,650],{"class":288},"'",[250,652,636],{"class":305},[250,654,656,659,661,664],{"class":252,"line":655},11,[250,657,658],{"class":305},"  -d",[250,660,604],{"class":288},[250,662,663],{"class":260},"{\"text\":\"一日署長を務めた\",\"mode\":\"tts\"}",[250,665,610],{"class":288},[14,667,668],{},"普通のHTTP APIなので、Claude CodeやCodexのBashツールからcurlでPOSTするだけで正規化済みの読みがJSONで返る。「読み上げ前にテキストをja-furiganaに通す」パイプラインがAIエージェントから組みやすい。リポジトリにはPython / Node.js / curlの最小クライアント例も同梱されている。",[236,670,671],{"id":671},"modeとパラメータ",[73,673,674,684],{},[76,675,676],{},[79,677,678,681],{},[82,679,680],{},"mode",[82,682,683],{},"出力",[92,685,686,697,707,720,730,744,754],{},[79,687,688,694],{},[97,689,690,693],{},[100,691,692],{},"tts","（デフォルト）",[97,695,696],{},"TTS整形ひらがな（句読点をポーズに置換）",[79,698,699,704],{},[97,700,701],{},[100,702,703],{},"hiragana",[97,705,706],{},"プレーンひらがな",[79,708,709,714],{},[97,710,711],{},[100,712,713],{},"ruby",[97,715,716,719],{},[100,717,718],{},"{漢字|ひらがな}"," 形式のルビ",[79,721,722,727],{},[97,723,724],{},[100,725,726],{},"kanji",[97,728,729],{},"入力そのまま（no-op）",[79,731,732,741],{},[97,733,734,737,738],{},[100,735,736],{},"romaji"," / ",[100,739,740],{},"romaji-kunrei",[97,742,743],{},"ヘボン式 / 訓令式ローマ字",[79,745,746,751],{},[97,747,748],{},[100,749,750],{},"analyze",[97,752,753],{},"採択された読み + token単位の詳細（候補・境界）",[79,755,756,761],{},[97,757,758],{},[100,759,760],{},"accent",[97,762,763],{},"アクセント句 + 曖昧語の代替候補つき中立JSON",[14,765,766,767,770,771,737,774,777,778,781,782,785,786,789,790,793],{},"主なパラメータ: ",[100,768,769],{},"text_b64","（URL-safe base64入力）、",[100,772,773],{},"short_pause",[100,775,776],{},"long_pause","（TTSのポーズ文字列）、",[100,779,780],{},"segmented","（分割配列の同梱）、",[100,783,784],{},"debug","（処理時間の同梱）。最大入力長は10,000文字。認証は ",[100,787,788],{},"X-API-Key"," ヘッダまたは ",[100,791,792],{},"Bearer"," トークン。",[14,795,796,797,800],{},"地味に良い仕様として、",[18,798,799],{},"辞書にない英単語はASCIIのまま読みなしで返す","（Linderaに渡さないので誤読しない）。外来語辞書にある語はカタカナ化される:",[241,802,804],{"className":243,"code":803,"language":245,"meta":246,"style":246},"curl 'http://127.0.0.1:8000/furigana?text=Kubernetesが安定&mode=ruby'\n# => {\"result\":\"{Kubernetes|クバネティス}{が|が}{安定|あんてい}\",\"mode\":\"ruby\"}\n",[100,805,806,817],{"__ignoreMap":246},[250,807,808,810,812,815],{"class":252,"line":253},[250,809,580],{"class":256},[250,811,604],{"class":288},[250,813,814],{"class":260},"http://127.0.0.1:8000/furigana?text=Kubernetesが安定&mode=ruby",[250,816,610],{"class":288},[250,818,819],{"class":252,"line":267},[250,820,821],{"class":270},"# => {\"result\":\"{Kubernetes|クバネティス}{が|が}{安定|あんてい}\",\"mode\":\"ruby\"}\n",[55,823,825],{"id":824},"accentモード読みの判断をaiに委ねられる","accentモード——読みの判断をAIに委ねられる",[14,827,828,829,831,832,834,835,838],{},"面白いのが ",[100,830,760],{},"（と ",[100,833,750],{},"）モード。「今日（きょう/こんにち）」のような曖昧な語に対して、",[18,836,837],{},"採択した読みに加えて、採択しなかった候補を重み付きで返してくれる","。",[14,840,841],{},"レスポンスのtoken構造（型定義より）:",[241,843,847],{"className":844,"code":845,"language":846,"meta":246,"style":246},"language-jsonc shiki shiki-themes vitesse-light vitesse-light","{\n  \"surface\": \"今日\",\n  \"reading\": \"きょう\",          // 採択された読み\n  \"accent_phrases\": [...],      // アクセント句（モーラ数・アクセント核）\n  \"ambiguous\": true,            // 同一位置に代替候補があるか\n  \"alternatives\": [             // 採択されなかった候補（weight降順）\n    { \"reading\": \"こんにち\", \"sense\": \"今日的、の意\", \"weight\": 30 }\n  ]\n}\n","jsonc",[100,848,849,854,859,867,875,883,891,896,901],{"__ignoreMap":246},[250,850,851],{"class":252,"line":253},[250,852,853],{},"{\n",[250,855,856],{"class":252,"line":267},[250,857,858],{},"  \"surface\": \"今日\",\n",[250,860,861,864],{"class":252,"line":274},[250,862,863],{},"  \"reading\": \"きょう\",",[250,865,866],{},"          // 採択された読み\n",[250,868,869,872],{"class":252,"line":281},[250,870,871],{},"  \"accent_phrases\": [...],",[250,873,874],{},"      // アクセント句（モーラ数・アクセント核）\n",[250,876,877,880],{"class":252,"line":312},[250,878,879],{},"  \"ambiguous\": true,",[250,881,882],{},"            // 同一位置に代替候補があるか\n",[250,884,885,888],{"class":252,"line":435},[250,886,887],{},"  \"alternatives\": [",[250,889,890],{},"             // 採択されなかった候補（weight降順）\n",[250,892,893],{"class":252,"line":457},[250,894,895],{},"    { \"reading\": \"こんにち\", \"sense\": \"今日的、の意\", \"weight\": 30 }\n",[250,897,898],{"class":252,"line":463},[250,899,900],{},"  ]\n",[250,902,903],{"class":252,"line":622},[250,904,466],{},[14,906,907,908,911,912,915],{},"これが効くのは、",[18,909,910],{},"最終判断をLLMに委ねるパイプライン","を組むとき。ja-furiganaが「機械的に決められるところ」を高速に確定させ、",[100,913,914],{},"ambiguous: true"," の語だけ候補と重みを添えてLLMに渡せば、LLM側は曖昧箇所の裁定に集中できる。全文をLLMに読ませて読み仮名を振らせるより、速くて安くて再現性が高い。",[55,917,919],{"id":918},"仕組みsmart-engine-6-provider","仕組み——Smart engine + 6 provider",[14,921,922],{},"内部は「6つのproviderが読み候補を出し、Viterbi風のパス選択で最良の読み列を選ぶ」構造。",[924,925,926,932,961,970],"ol",{},[26,927,928,931],{},[18,929,930],{},"テキスト正規化",": Unicode NFKC + 異体字マッピング（髙→高）",[26,933,934,937,938],{},[18,935,936],{},"候補生成（6 provider）",":\n",[23,939,940,943,946,952,955,958],{},[26,941,942],{},"ProtectToken: URL / Email / 絵文字を保護",[26,944,945],{},"AlphabetPassthrough: 外来語辞書（Kubernetes / Docker等）",[26,947,948,949,951],{},"DictBridge: 辞書マッチ（熟語 / 単漢字 / ",[100,950,230],{}," 文脈ブロック）",[26,953,954],{},"NumberCandidate: 数字・助数詞・日付・時刻・SI単位（連濁「三羽→さんば」促音「六匹→ろっぴき」も処理）",[26,956,957],{},"Odoriji: 踊り字「々」の連濁処理（人々→ひとびと）",[26,959,960],{},"LinderaFallback: 形態素解析のセーフティネット",[26,962,963,966,967],{},[18,964,965],{},"パス選択",": 候補にband（信頼度の階層）を付けて比較。",[100,968,969],{},"辞書完全一致(1000) > 数字・助数詞(950) > Lindera漢字熟語(150) > 単漢字デフォルト(100) > Linderaフォールバック(50)",[26,971,972,975],{},[18,973,974],{},"後処理",": モード別整形。TTSモードでは句読点をポーズに置換。文脈依存の読み補正（「小腹が空いた」を「すいた」に直す類い）もpost-passで適用",[14,977,978,979,982],{},"「辞書が最優先、形態素解析は最後の砦」という優先順位が明確で、",[18,980,981],{},"誤読を見つけたら辞書に1エントリ足せば必ず勝つ","構造になっているのが運用しやすい。",[55,984,986],{"id":985},"辞書toml手書き52500エントリprで直せる","辞書——TOML手書き、52,500エントリ、PRで直せる",[14,988,989,990,992],{},"辞書は約52,500エントリ（0.1.0時点）。内訳は単漢字42,318・熟語7,949・文脈分岐の ",[100,991,230],{}," ブロック1,139・異体字435・外来語168など。",[14,994,995,1000],{},[30,996,999],{"href":997,"target":33,"rel":998},"https://ryuuneko1107.github.io/ja-furigana-dict/",[35,36],"→ 登録語句検索ページ（GitHub Pages）","で辞書の中身をブラウザから検索できる。手元の語が登録済みかどうか、PRを出す前にここで確認できるのは親切。",[14,1002,1003,1004,1006,1007,1010,1011,1014,1015,1018,1019,1022],{},"辞書の更新経路も5通り用意されていて、個人運用なら ",[100,1005,495],{}," + 再起動か ",[100,1008,1009],{},"--auto-pull","、無停止運用なら ",[100,1012,1013],{},"[auto_update]"," の定期polling（",[100,1016,1017],{},"RwLock\u003CArc\u003CFurigana>>"," のswapでダウンタイムなし）、外部からは ",[100,1020,1021],{},"POST /admin/reload","（admin token必須）が使える。",[55,1024,1026],{"id":1025},"弱点と二段構え運用","弱点と「二段構え」運用",[14,1028,1029,1030,1033],{},"開発者自身がブログで明記しているとおり、52,500エントリはまだ小さく、",[18,1031,1032],{},"人名・地名・新語・超高精度な文脈読み分けは苦手","。手元でも「辛いラーメン→つらい」のような取りこぼしがあった。",[14,1035,1036,1037,1040],{},"そこで現実解としては、",[18,1038,1039],{},"前にやったAivisSpeechのユーザー辞書登録自動化と組み合わせる二段構え","が良さそうだと思っている:",[924,1042,1043,1049],{},[26,1044,1045,1048],{},[18,1046,1047],{},"大半をja-furiganaで正規化",": 一般語・数字・日付・助数詞・踊り字など、辞書とルールで機械的に決まるものはここで確定",[26,1050,1051,1054],{},[18,1052,1053],{},"残りをTTS側のユーザー辞書で補完",": 自分のドメイン固有語（会計用語など）や、ja-furiganaがまだ外す語は、AivisSpeech / VOICEVOX側の辞書登録でピンポイントに潰す",[14,1056,1057],{},"ja-furigana側で直せるものは辞書PRを出せば全ユーザーに還元される、という出口があるのもOSSとして良い循環。",[55,1059,1060],{"id":1060},"バージョンと開発ペース",[23,1062,1063,1066,1073],{},[26,1064,1065],{},"0.1.0 stable: 2026-05-12リリース。以降、公開API・TOMLスキーマ・CLI引数・HTTPレスポンス形式の互換性を維持（0.1.xはadditive only）",[26,1067,1068,1069,1072],{},"その後の開発ペースが速く、",[18,1070,1071],{},"2026-06-11時点でcrates.io上の最新は0.1.9","。0.1.4で「腹+空く」の文脈補正と波ダッシュ誤読の修正、0.1.5で辞書lookupの約200倍高速化（38ms→0.19ms）、0.1.8で数詞慣用語句（二十歳=はたち、明後日=あさって）の対応、とほぼ毎日改善が入っている",[26,1074,1075,1076,1079],{},"0.2.0ではUniDicベースのpitch accentデータを使ったイントネーション機能（VOICEVOX ",[100,1077,1078],{},"AccentPhrase[]"," 互換出力など）が予定されている",[14,1081,1082,1083,1085],{},"TTSパイプラインを組むなら、まず ",[100,1084,506],{}," を立ててcurlで自分の文章を流してみるのがおすすめ。誤読を見つけたら検索ページで辞書を確認して、直せそうならPR、ドメイン固有ならTTS側の辞書へ、という流れが綺麗に回る。",[1087,1088,1089],"style",{},"html pre.shiki code .senZ8, html code.shiki .senZ8{--shiki-default:#59873A;--shiki-dark:#59873A}html pre.shiki code .sdGka, html code.shiki .sdGka{--shiki-default:#B56959;--shiki-dark:#B56959}html pre.shiki code .sxvE3, html code.shiki .sxvE3{--shiki-default:#A0ADA0;--shiki-dark:#A0ADA0}html pre.shiki code .sz8Xr, html code.shiki .sz8Xr{--shiki-default:#998418;--shiki-dark:#998418}html pre.shiki code .sMJiu, html code.shiki .sMJiu{--shiki-default:#B5695977;--shiki-dark:#B5695977}html pre.shiki code .stQ0i, html code.shiki .stQ0i{--shiki-default:#AB5959;--shiki-dark:#AB5959}html pre.shiki code .snbK4, html code.shiki .snbK4{--shiki-default:#A65E2B;--shiki-dark:#A65E2B}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .s4oTP, html code.shiki .s4oTP{--shiki-default:#B07D48;--shiki-dark:#B07D48}html pre.shiki code .shFtX, html code.shiki .shFtX{--shiki-default:#999999;--shiki-dark:#999999}html pre.shiki code .sHkkW, html code.shiki .sHkkW{--shiki-default:#1E754F;--shiki-dark:#1E754F}html pre.shiki code .sSkh3, html code.shiki .sSkh3{--shiki-default:#2E8F82;--shiki-dark:#2E8F82}",{"title":246,"searchDepth":267,"depth":267,"links":1091},[1092,1093,1094,1099,1103,1104,1105,1106,1107],{"id":57,"depth":267,"text":57},{"id":132,"depth":267,"text":132},{"id":234,"depth":267,"text":234,"children":1095},[1096,1097,1098],{"id":238,"depth":274,"text":239},{"id":318,"depth":274,"text":319},{"id":489,"depth":274,"text":489},{"id":499,"depth":267,"text":500,"children":1100},[1101,1102],{"id":565,"depth":274,"text":565},{"id":671,"depth":274,"text":671},{"id":824,"depth":267,"text":825},{"id":918,"depth":267,"text":919},{"id":985,"depth":267,"text":986},{"id":1025,"depth":267,"text":1026},{"id":1060,"depth":267,"text":1060},"dev","「一日署長」をいちにちしょちょう、「明日」をあしたと読み分けるふりがな変換エンジン ja-furigana の紹介。HTTPサーバー機能でClaude CodeやCodexからPOSTすれば正規化済みの読みがJSONで返る。曖昧な語に候補と重みを付けて返すaccent/analyzeモード、Smart engine + 6 providerの仕組み、TOML辞書への貢献方法、AivisSpeech辞書登録との二段構え運用まで。","md",{},"/ja-furigana-tts-reading","mdx-playground",false,"2026-06-12T00:00:00.000Z",{"title":5,"description":1109},"2026-06/2026-06-12/ja-furigana-tts-reading",[1119,1120,1121,1122,20,1123,1124],"TTS","Rust","OSS","日本語処理","VOICEVOX","AivisSpeech",null,"S_POU-2QfcHMWtbkx8HGlBOmkvaVmbqmcvRA3HUhpDA",[1128,1139,1148,1158,1165],{"title":1129,"description":1130,"path":1131,"tags":1132,"publishedAt":1138,"updatedAt":1125},"Fish Audio v2/v3とElevenLabsで教材ナレーション音声を一括生成した記録","Fish Audio v2で33件、v3で68件のナレーション音声を生成。ダブルクォーテーション除去や読み間違い対策などテキスト整備、Python製TTS音声バリデーターの開発、R2アップロードからCDNキャッシュ問題の発覚まで。","/fish-audio-tts-narration-generation",[1133,1119,1134,1135,1123,1136,1137],"Fish Audio","音声合成","ElevenLabs","Python","Cloudflare R2","2026-03-18T00:00:00.000Z",{"title":1140,"description":1141,"path":1142,"tags":1143,"publishedAt":1147,"updatedAt":1125},"ElevenLabs v3で日本語TTS - 2026年3月時点の音声合成サービス比較と本番生成","日本語TTS 4サービス（OpenAI TTS, Google Cloud TTS, ElevenLabs v3, VOICEVOX）を比較調査。ElevenLabs v3を選定し、Audio Tags感情制御テスト、6ボイス聞き比べページ構築、Chapter 04全59行の本番音声生成までの記録。","/elevenlabs-tts-comparison",[1135,1119,1134,1123,1144,1145,1146],"Google Cloud TTS","Audio Tags","日本語TTS","2026-03-16T00:00:00.000Z",{"title":1149,"description":1150,"path":1151,"tags":1152,"publishedAt":1157,"updatedAt":1125},"2026年5月16日の開発日記 - 投資判断クイズ75問の音声化とマイクロン決算チャートの作り込み","Part 2 投資判断クイズ75問のVOICEVOX音声化を本番デプロイまで完走し、午後はマイクロン（MU）の決算チャートを11回のフィードバックで作り直した1日。","/2026-05-16-diary",[1153,1123,1134,1154,1155,1156],"日記","SVG","Vue 3","決算分析","2026-05-16T00:00:00.000Z",{"title":1159,"description":1160,"path":1161,"tags":1162,"publishedAt":1157,"updatedAt":1125},"投資判断クイズ75問をVOICEVOXで音声化：WAV合成→MP3→Cloudflare R2まで一気通貫の自動化ログ","Part 2 投資判断クイズ75問の問題文・選択肢・解説・誤答パターンをVOICEVOXで音声合成し、MP3変換からCloudflare R2へのアップロード、Nuxtページへの組み込み、本番デプロイまでをClaude Codeに順次実行させた。PowerShellの罠やprefix typo、narrationConfig未渡しといった躓きも含めて記録","/quiz-narration-pipeline",[1123,1134,1137,1163,1164],"Nuxt 3","音声化パイプライン",{"title":1166,"description":1167,"path":1168,"tags":1169,"publishedAt":1174,"updatedAt":1125},"「ALL Software をエージェントネイティブに」を疑う：CLI-Anything を開けて読んでみた","HKUDS/CLI-Anything が掲げる『あらゆるソフトウェアをエージェント対応に』の文言を真に受けず、READMEと中身を読み解いて実態を整理する。誇大な見出しに釣られないための、リポジトリの開き方のメモ。","/cli-anything-doubt",[1170,1121,1171,1172,1173],"AI","GitHub","情報リテラシー","Claude Code","2026-05-15T00:00:00.000Z",[],"https://log.eurekapu.com/og/blog/ja-furigana-tts-reading.png?v=2026-06-12T00%3A00%3A00.000Z&title=ja-furigana%E2%80%94%E2%80%94%E6%96%87%E8%84%88%E3%82%92%E8%A6%8B%E3%81%A6%E3%80%8C%E6%AD%A3%E3%81%97%E3%81%84%E8%AA%AD%E3%81%BF%E3%80%8D%E3%82%92%E5%BD%93%E3%81%A6%E3%82%8BRust%E8%A3%BDOSS%E3%81%8CTTS%E3%81%AE%E8%AA%AD%E3%81%BF%E9%96%93%E9%81%95%E3%81%84%E5%AF%BE%E7%AD%96%E3%81%AB%E5%8A%B9%E3%81%8F&author=Kei%20Komatsu&sig=17e61c56ac5041d0",1781333884299]