音声合成の話題は英語圏のモデルに偏りがちですが、日本語だけを狙い撃ちにしたモデルが個人の手から出てきて、しかも MIT ライセンスで配られています。それが Irodori-TTS です。

名前を聞いたことはあっても、「結局のところ何が新しいのか」「業務で使ってよいものなのか」までは追えていない方が多いと思います。この記事では、公開されているモデルカードやリポジトリの一次情報を追いながら、実際に GPU を借りて動かした実測値とあわせて整理します。

FIXITFIXIT

絵文字で感情を指定できる音声合成って聞いたけど、それって飛び道具なだけじゃないの?

TsumikiTsumiki

実際に聴くと、笑いも吐息も絵文字を置いた位置にそのまま乗ります。設定はしていません。

FIXITFIXIT

えっ、個人が作ったモデルなんだよね?仕事で使って大丈夫なの?

TsumikiTsumiki

コードも重みも MIT です。参照元が非商用縛りなので、そこを外した作りが効いています。

FIXITFIXIT

じゃあ動かすのは大変?GPU がないと無理とか?

TsumikiTsumiki

手元では RTX 4090 を 1 時間借りて全部試しました。実費は 60 円くらいです。

Irodori-TTS とは何か——4 系統の入力で声を作る

Irodori-TTS は、Aratako 氏 (Chihiro Arata 名義) が個人で開発している日本語特化のテキスト音声合成モデルです。学習・推論コードは GitHub に、学習済みの重みは Hugging Face に、どちらも MIT ライセンスで公開されています。

最新版の Irodori-TTS-v4.1-Small は 2026 年 8 月 11 日公開で、パラメータ数は約 7.7 億 (766,052,385) です。GitHub リポジトリは 2026 年 8 月 22 日時点で 1,203 スター、149 フォークを集めています。

このモデルの性格をひとことで言うと、「声そのものを設計させる」タイプの音声合成です。既製の話者ボイスは同梱されておらず、代わりに次の 4 系統の入力を組み合わせて、話者と話し方をその場で作り出します。

入力役割
テキスト読み上げる内容本日はお越しいただき、誠にありがとうございます。
参照音声話者の同一性同じ人物の短いクリップを合計 30 秒ほど
キャプション声質・感情・話し方落ち着いた大人の男性。フォーマルな場で深く響く声で丁寧に話している。
絵文字発話スタイルと効果音👂 囁き、🤧 咳、😮‍💨 吐息、📖 ナレーション

裏を返すと、何も指定しないと生成のたびに性別も年齢も変わります。手軽さを求めて触ると面食らう部分ですが、これは欠点というより設計思想の表れです。

仕組み——離散トークンをやめて連続潜在を生成する

Irodori-TTS のアーキテクチャは Rectified Flow Diffusion Transformer (RF-DiT) と呼ばれるものです。設計と学習方法は、Jordan Darefsky 氏の Echo-TTS をおおむね踏襲しています。

近年の音声合成には大きく 2 つの流れがあります。ひとつは音声をコーデックで離散トークンに変換し、言語モデルと同じ要領で次のトークンを予測していく方式です。もうひとつが、音声を連続値の潜在表現に落とし、拡散モデルやフローマッチングでその潜在表現そのものを生成する方式です。Irodori-TTS は後者にあたります。

Echo-TTS の作者は、前作にあたる Parakeet が離散トークン空間の自己回帰生成で一貫性を保てなかったと振り返り、連続潜在への移行を選んだと説明しています。Irodori-TTS はこの判断をそのまま引き継いでいます。

推論時の流れは次のようになります。

flowchart LR
  T[入力テキスト] --> E[共有エンコーダ<br/>ModernBERT-ja]
  C[キャプション] --> E
  R[参照音声] --> RE[参照潜在エンコーダ]
  E --> P[条件プロジェクタ]
  P --> D[Diffusion Transformer<br/>RF-DiT]
  RE --> D
  P --> DP[Duration Predictor]
  DP --> D
  D --> L[DACVAE 潜在系列]
  L --> V[コーデックでデコード<br/>48kHz 波形]
  V --> W[SilentCipher 透かし]

構成要素として押さえておきたいのは次の 3 つです。

1 つ目は音声の表現方法です。Irodori-TTS は音声を Semantic-DACVAE-Japanese-32dim という 32 次元の連続潜在系列として扱い、48kHz の波形に復元します。このコーデックも同じ作者が Meta の DACVAE をベースに作ったもので、WavLM による意味蒸留を組み込んだうえで日本語音声で追加学習し、潜在次元を 128 から 32 まで圧縮しています。次元を落とすと下流の音声合成モデルの学習が軽くなる一方、UTMOSv2 で測った再構成品質は元の DACVAE を上回っています。

2 つ目はテキストの理解です。v4 でテキストエンコーダが刷新され、ゼロから学習した独自のエンコーダから、SB Intuitions が公開する ModernBERT-ja-310m をファインチューニングしたものに置き換わりました。しかもこのエンコーダは、読み上げるテキストとキャプションの両方で共有されます。日本語の事前学習済み言語モデルを土台にしたことで、難しい漢字の読みが改善したとされています。

3 つ目が出力長の推定です。v3 から Duration Predictor が導入され、テキストと条件から出力の長さを自動で見積もるようになりました。v4.1 での変更はここだけで、本体を凍結した状態で Duration Predictor だけを分離して学習し直しています。出力長を過大に見積もることで起きていた生成崩れを減らすのが狙いです。

半年で 7 世代——どこから生まれたのか

Irodori-TTS を「突然出てきた個人開発モデル」と捉えると、実像を見誤ります。作者の Hugging Face アカウントには 134 のモデルと 68 のデータセットが並んでおり、Irodori-TTS はその積み重ねの上に立っています。

公開日を並べると流れが見えてきます。

時期公開されたもの位置づけ
2024〜2025 年日本語の合成データセット、ロールプレイ用 LLM のファインチューン日本語データを作る側の経験
2025 年 12 月T5Gemma-TTS音声合成への着手
2026 年 1〜2 月MioVocoder / MioCodec / MioTTS自前のボコーダーとコーデック、LLM ベースの音声合成
2026 年 2 月 25 日Irodori-TTS-500M初代。Meta の DACVAE を 128 次元で使用
2026 年 3 月 5〜14 日Semantic-DACVAE-Japanese と 32 次元版日本語向けコーデックを自作
2026 年 3 月 23 日Irodori-TTS-500M-v2コーデックを自作品に差し替え、学習量を 2.5 倍に
2026 年 3 月 30 日v2-VoiceDesignキャプションで声を作る系統を分離
2026 年 5 月 12 日Irodori-TTS-500M-v3可変長学習と Duration Predictor、透かしを統合
2026 年 5 月 31 日600M-v3-VoiceDesign参照音声とキャプションの併用に対応
2026 年 8 月 1 日Irodori-TTS-v4-Small2 系統を単一モデルに統合、ModernBERT-ja を採用
2026 年 8 月 11 日Irodori-TTS-v4.1-SmallDuration Predictor を分離再学習

半年で 7 世代という速度もさることながら、v1 から v2 にかけて音声コーデックそのものを自作品へ差し替えている点が目を引きます。ここは後述するライセンスの話にも直結します。

v4 で何が変わったか

v3 までは「参照音声で声を真似る本体モデル」と「キャプションで声を作る VoiceDesign モデル」が別々のチェックポイントとして配られており、使い分けるには 2 つのモデルをダウンロードする必要がありました。v4 以降はこれが単一のチェックポイントに統合され、参照音声とキャプションを同時に渡せます。v3 時点の解説記事を読むときは、この差を意識しておくと混乱しません。

ライセンスが MIT である意味

日本語のローカル音声合成を業務で検討するとき、性能より先に引っかかるのがライセンスです。ここで Irodori-TTS の設計判断が効いてきます。

この種のモデルでは、音声を潜在表現に変換するコーデックのライセンスが全体を縛ります。設計の参照元である Echo-TTS は Fish Speech の S1-DAC というオートエンコーダを使っており、これが CC BY-NC-SA 4.0、つまり非商用限定です。コーデックが非商用であれば、それを通して音声を作るパイプライン全体も非商用に縛られます。Echo-TTS の作者自身がそう述べています。

Irodori-TTS はこの部分だけ別の道を選びました。初代は Meta の DACVAE をそのまま使い、v2 以降は前述の Semantic-DACVAE-Japanese-32dim に切り替えています。土台の facebook/dacvae-watermarked を含めて MIT で公開されているため、コーデックが非商用に縛られません。アーキテクチャの考え方は参照しつつ、ライセンス上の足かせになる部分は最初から避けたかたちです。

作者は GitHub の Issue で、商用利用について次のように回答しています。

As long as you comply with the model's license and Ethical Restrictions, there are no further restrictions. Please feel free to use it, including for commercial purposes.

ただし、ライセンスとは別に 4 つの倫理的制約がモデルカードに明記されています。

  1. 声優・著名人・公人を含め、本人の明確な同意なく個人の声をクローンしないこと
  2. 誤解を招くディープフェイクや虚偽情報を目的とした音声を生成しないこと
  3. 参照音声を使わずに生成した声が偶然実在の人物に似る可能性があること
  4. 誤用に対して開発者は責任を負わず、法令順守は利用者の責任であること

3 番目は見落とされがちです。参照音声を渡していないから安全、とは言い切れません。潜在空間のなかで確率的に似てしまう可能性があると、作者自身が述べています。

生成音声にはソニーの SilentCipher による電子透かしが自動で埋め込まれます。ここも作者の説明が明快で、生成後に後付けする方式なので技術的には外せるものの、なりすまし防止のために外す方法は案内しない、外すことを推奨もしない、という立場を取っています。禁止条項ではないと明言しながら推奨しないと言い切る書き方は、実務で判断する側から見て参考になります。

MIT だから何でもよい、ではありません

ライセンスが許すことと、声の権利者が許すことは別の話です。参照音声を使うなら、その声の持ち主から用途を含めた同意を取り、記録を残してください。社内の人物の声であっても同じです。ここを曖昧にしたまま制作物を納品すると、後から差し替えが効きません。

実際に動かす——RTX 4090 を 1 時間借りて測る

ここからは手を動かした結果です。手元の Mac には NVIDIA の GPU がないため、RunPod で RTX 4090 (24GB) を時間借りして検証しました。実費は Pod の立て直しを含めて約 60 円です。

セットアップ

必要なのは Git と uv の 2 つです。Python 3.10 は uv が自動で用意します。

git clone https://github.com/Aratako/Irodori-TTS.git
cd Irodori-TTS
uv sync --extra cu128

末尾の --extra で PyTorch のバックエンドを選びます。NVIDIA の CUDA 12.8 なら cu128、AMD なら rocm、Intel なら xpu、CPU のみや macOS なら cpu です。

所要時間は環境によって大きく変わりました。同じ手順を 2 つの環境で実行した結果は次のとおりです。

項目Secure CloudCommunity Cloud
uv のインストールと git clone3 秒3 秒
uv sync --extra cu12846 秒581 秒
合計49 秒584 秒

依存関係をすべて展開した .venv は 7.8GB になりました。ここにモデル本体のダウンロードが加わります。初回の推論では v4.1 本体 (3.06GB) に加えてコーデック、ModernBERT、SilentCipher が取得され、Hugging Face のキャッシュは量子化版も含めて 5.0GB まで膨らみました。実測の合計は約 13GB なので、モデルの入れ替えや量子化版の取得を見込んでも 20GB あれば足ります。

生成そのものは 1 行です。

uv run --no-sync python infer.py \
  --hf-checkpoint Aratako/Irodori-TTS-v4.1-Small \
  --text "本日はお越しいただき、誠にありがとうございます。どうぞごゆっくりお過ごしください。" \
  --no-ref \
  --output-wav outputs/sample.wav

ブラウザから触りたい場合は Gradio の Web UI が用意されています。

uv run --no-sync python gradio_app.py --server-name 0.0.0.0 --server-port 7860

生成レイテンシと VRAM の実測

先ほどのコマンドで読み上げた 40 字の文 (出力音声 7.80 秒) を基準に、条件を変えて測った結果です。wall はプロセスの起動から終了までの実時間、gen は infer.py が出力するモデルロード後の純粋な生成時間です。条件によって出力音声の長さは多少前後します。

条件wallgenVRAM ピーク
初回 (モデルのダウンロード込み)54.27 秒1.396 秒5,512 MiB
参照なし / 40 ステップ (既定)17.34 秒1.066 秒5,512 MiB
参照なし / 16 ステップ17.88 秒0.657 秒5,512 MiB
参照なし / 6 ステップ + Sway Sampling17.72 秒0.454 秒5,512 MiB
キャプション指定18.65 秒1.230 秒5,496 MiB
参照音声あり18.93 秒1.492 秒5,648 MiB
参照音声 + キャプション18.26 秒1.340 秒5,632 MiB
絵文字入りテキスト17.79 秒1.146 秒5,676 MiB
bf1618.22 秒1.372 秒4,876 MiB
int8 量子化27.63 秒1.363 秒3,312 MiB
int4 量子化24.06 秒1.395 秒3,234 MiB

既定設定での RTF (生成時間 ÷ 音声長) は 0.137、つまり実時間の約 7 倍速で音声が出てきます。ステップ数を 16 に落とすと 0.084、実験的な Sway Sampling で 6 ステップまで削ると 0.058 まで下がりました。なお初回だけ gen が 1.396 秒と既定より 3 割ほど遅いのは、CUDA カーネルのウォームアップが含まれるためです。2 回目以降は 1.066 秒に落ち着きます。

ステップ数を削ると音質がどうなるかは、聴き比べるのが確実です。

ステップ数を 40 から 6 まで削る

  • 40 ステップ (既定)

    生成時間 1.066 秒

  • 6 ステップ + Sway Sampling

    生成時間 0.454 秒

同じ文・同じシード・同じ参照音声で、サンプリングのステップ数だけを変えています。生成時間は 1.066 秒から 0.454 秒に縮みます。

読み取れることが 2 つあります。

ひとつは、VRAM が 5.4GB 前後で収まる点です。24GB の GPU は必要なく、8GB クラスでも動く水準に見えます。int8 の重み量子化を使えば 3.2GB まで下がるため、より小さい GPU も射程に入ります。ただし量子化と引き換えに速くはなりません。既定 (fp32) の 1.066 秒に対し、int8 は 1.363 秒、int4 は 1.395 秒と 3 割ほど遅くなりました。量子化は速度ではなく、VRAM を切り詰めるための選択肢だと考えるのが妥当です。

もうひとつは、wall と gen の差です。生成が 1 秒で終わっているのに、プロセス全体では 17 秒前後かかっています。差の 16 秒はモデルのロードです。コマンドを都度叩く使い方では待ち時間の 9 割以上がロードということになります。

何に時間がかかっているのか

infer.py は処理段階ごとの内訳を出力します。参照なし・40 ステップの場合は次のとおりです。

段階時間
tokenize_text1.7 ms
prepare_reference0.2 ms
predict_duration131.2 ms
sample_rf773.9 ms
decode_latent84.0 ms
silentcipher_watermark74.5 ms
合計1.066 秒

7 割強を占めるのが sample_rf、つまり Rectified Flow のサンプリングです。ステップ数を削ると速くなるのはこの部分だからで、逆に言えばここ以外を削っても効果は薄いことがわかります。

参照音声を渡すと prepare_reference が 0.2 ミリ秒から 445.3 ミリ秒に跳ね上がり、合計は 1.492 秒になりました。同じ声を繰り返し使うなら、参照音声を毎回エンコードするのではなく、事前に潜在表現へ変換して渡すか、話者埋め込みを学習しておくほうが効率的です。Irodori-TTS には Speaker Inversion という仕組みがあり、本体を凍結したまま話者の埋め込みだけを学習して、小さなファイルとして使い回せます。

電子透かしの付与に 74.5 ミリ秒かかっている点も、内訳を見て初めて気づける部分でした。生成時間の約 7% が透かしに使われている計算になります。

30 秒の壁

入力を長くしながら出力音声の長さを測ると、明確な上限が見えました。

入力テキスト文字数出力音声長
短文約 40 字7.80 秒
中文約 100 字18.04 秒
長文約 210 字30.00 秒

約 210 字を入れたときの出力はちょうど 30.00 秒で、後半が失われていました。学習時の最大長が 25 fps 換算で 750 フレーム、つまり 30 秒に設定されているためです。1 回の生成は 150 字前後までに抑え、それ以上は分割する前提で設計します。

つまずいたところ

最初に借りた Community Cloud の個体では、nvidia-smi は正常に GPU を表示するのに torch.cuda.is_available() が False を返し、CUDA の初期化に失敗しました。Pod を再起動しても直らず、Secure Cloud で立て直したところ問題なく動きました。時間貸しの GPU では、こうした個体差に当たることがあります。本番の作業に入る前に torch.cuda.is_available() を確認しておくと、無駄な待ち時間を防げます。

なお、CUDA が使えないまま CPU にフォールバックした状態でも生成自体は完走しました。ただし短文 1 本に、モデルのダウンロード込みで 176 秒かかりました。これは 152 vCPU のサーバー CPU での値なので、ノート PC ではさらに時間がかかると見ておくべきでしょう。

声をどう作るか

まず自分の声を 1 本作るところから始まる

最初に戸惑うのがここです。Irodori-TTS には既製の話者ボイスが 1 つも同梱されていません。VOICEVOX のように「選ぶだけで使える声」を期待して触ると、生成のたびに別人が出てきて面食らいます。

モデルのリポジトリには音声ファイルが 11 本ありますが、これはモデルカードに貼るデモ用の素材です。素性の説明がないので、業務で使う参照音声にするのは避けたほうがよいでしょう。API サーバーの voices/ ディレクトリも空で、自分の音源を置く場所として用意されているだけです。

声を手に入れる道は 3 つあります。キャプションで作って気に入った 1 本を保存する方法、同意の取れた人の録音を使う方法、そして Speaker Inversion で話者埋め込みとして固定する方法です。この記事のサンプルはすべて 1 つ目の方法で作りました。

キャプションで声を作るのは、当たりが出るまで引き直す作業になります。最初に「落ち着いた大人の女性。自然で聞き取りやすい、標準的な読み上げの話し方。」と指示したところ、想定よりかなり年上の声が出てきました。指示文とシードを変えて 8 本作り、そのうちの 1 本を以降のサンプルの参照音声に採用しています。

この記事のサンプルで使う参照音声

  • キャプション「若い女性の声。アニメのヒロインのように、高めで澄んだ、明るく可愛らしい話し方。」

    こんにちは。この声で、記事のサンプル音声を作ります。

参照音声なしでキャプションだけを渡して生成しました。以降のサンプルはすべてこの音声を参照に固定しています。

一度こうして声が決まれば、あとはそれを参照音声として渡すだけで、別の文章も同じ声で読み上げられます。

ゼロショット音声クローン

  • 参照音声を渡して別の文を生成

    初めて読む文章でも、参照音声と同じ声で読み上げられます。

上の参照音声を渡して、学習を挟まずに別の文章を読み上げさせたものです。

参照音声は「短いクリップを複数」

v4-Small は参照音声を合計 120 秒まで受け付けます。ただしここには注意点があり、学習時に「同じ話者の短い発話をランダムに連結したデータ」で訓練されているため、1 本の長い録音を渡す形式は評価されていないと明記されています。推奨は同じ話者のクリーンな短いクリップを複数渡す方法です。

参照の長さと話者類似度については、作者が JVS の 100 話者で測った結果を公開しています。

モデル / 参照CAM++ コサイン類似度top-1 正解率
v3 VoiceDesign / 1 クリップ0.678288.92%
v4-Small / 1 クリップ0.661084.60%
v4-Small / 約 30 秒0.752198.56%
v4-Small / 約 60 秒0.764699.56%
v4-Small / 120 秒0.775399.76%

短いクリップ 1 本だけなら v3 のほうが良いという結果になっています。長い参照に対応するため学習方法を変えた副作用だと作者は説明しており、改善が一様ではないことを自分から明示している点は信頼できます。実務上は、30 秒集めた時点で改善のほとんどが得られます。そこから 120 秒まで伸ばしても差はわずかなので、まずは 30 秒を目標にするとよいでしょう。

キャプションは日本語の文章で書く

キャプションは声質・感情・話し方を日本語の文章で指定する機能です。モデルカードのサンプルには、次のように書かれています。

落ち着いた大人の男性。フォーマルな場で、深く響く声で丁寧かつ歓迎の意を込めて話している。
若く元気な女性の声。カフェの店員のように、明るくハキハキとした少し高めのトーンで話している。
深く傷つき、今にも泣き出しそうな様子。声が震えており、悲痛なトーンで弱々しく話す。

年齢層・性別・場面・トーン・距離感を短い文で重ねる書き方です。

同じ文・同じシード・同じ参照音声で、キャプションだけを変えると次のようになります。

キャプションで話し方を変える

  • キャプションなし

    指定なし

  • 悲しみ

    深く傷つき、今にも泣き出しそうな様子。声が震えており、悲痛なトーンで弱々しく話す。

  • 怒り

    激しい怒りを感じており、声を荒らげている。相手を責め立てるような強い口調で、感情的なトーン。

読み上げるテキストもシードも参照音声も同一で、キャプションだけを差し替えています。声の主は変わらないまま、感情だけが乗り替わります。

参照音声と併用するときは、声の同一性を参照音声に任せ、キャプションでは感情や状況だけを指定するのがコツだとされています。両方で声質を指定すると条件が衝突し、音質が不安定になったり片方が無視されたりすると明記されています。

キャプションの追従性については、作者が Coco-Nut の公開音声記述 2,890 件を使い、生成音声を LLM に 1〜5 で採点させた結果を公開しています。v3 VoiceDesign の平均 4.2096 に対し v4-Small が 4.2339 と、わずかな改善にとどまりました。この評価について作者自身が「単一の自動判定を使った軽量な内部比較であり、研究水準のベンチマークとして扱うものではない」と断っています。

絵文字は 45 種類

対応する絵文字は 45 種類あり、ドキュメントに一覧化されています。一部を挙げると次のようなものです。

絵文字効果絵文字効果
👂囁き、耳元の音😮‍💨吐息、溜息
🤭くすくす笑い😭嗚咽、泣き声
🤧咳き込み、くしゃみ😰慌てて、動揺
早口🐢ゆっくりと
📖ナレーション、独白📞電話越しの音
⏸️間、沈黙🎵鼻歌

同じ絵文字を繰り返すと効果を強められます。この機能は Respair 氏の着想を取り入れたものだと謝辞に記されています。

効き目は聴くのが早いので、同じ文・同じシード・同じ参照音声で、絵文字だけを足し引きしたものを並べます。

絵文字を足すと何が変わるか

  • 絵文字なし

    あははっ、それ本当に言ってるの?…まぁ、君らしいけどね。

  • 絵文字あり (🤭 と 😮‍💨)

    あははっ🤭、それ本当に言ってるの?…😮‍💨まぁ、君らしいけどね。

読み上げるテキストの中身もシードも参照音声も同一で、差は絵文字 2 つだけです。抑揚の設定やパラメータの調整はしていません。

含み笑いと吐息が、絵文字を置いた位置にそのまま乗ります。テキストに 2 文字足しただけでこれが出てくるのは、耳で確かめると素直に驚きます。

出力の長さにも表れていて、絵文字なしが 7.32 秒だったのに対し、絵文字ありは 8.35 秒になりました。非言語の発声が挿入されるぶん、1 秒ほど伸びています。30 秒の上限を考えるときは、絵文字の追加分も見込んでおく必要があります。

ただしモデルカードの注意書きどおり、効きは文脈に左右されます。うまくいったのは 1 つのシードでの 1 例にすぎず、いつでもこの精度で乗るとは言えません。納品物に使うなら、当たりを引くまで作り直す前提の工程を組んでおくのが安全です。

業務システムへの組み込み方

先ほどの 16 秒のモデルロードが、そのまま構成の分かれ目になります。業務で使うならサーバーを常駐させるのが現実的です。

作者は Irodori-TTS-Server という OpenAI Text-to-Speech API 互換のサーバーを別リポジトリで公開しています。既存のコードで OpenAI の音声合成を呼んでいるなら、接続先を差し替えるだけで移行できます。

from openai import OpenAI
 
client = OpenAI(base_url="http://localhost:8088/v1", api_key="not-used")
 
with client.audio.speech.with_streaming_response.create(
    model="irodori-tts",
    voice="sample",
    input="こんにちは。これは Irodori-TTS の API テストです。",
    response_format="wav",
) as response:
    response.stream_to_file("speech.wav")

キャプションのような Irodori-TTS 固有の指定は、リクエストに irodori キーを足して渡します。

{
  "model": "irodori-tts",
  "input": "本日はお越しいただき、ありがとうございます。",
  "voice": "none",
  "response_format": "wav",
  "irodori": {
    "caption": "落ち着いた低めの女性の声。丁寧で穏やかな話し方。"
  }
}

長文は既定で自動的にチャンク分割され、順番に合成されたうえで 1 本の音声に連結されます。分割は「一定の文字数に達したうえで句読点か改行に当たった位置」で行われ、しきい値はリクエストごとに調整できます。30 秒の制約をアプリケーション側で意識しなくて済むのは大きな利点です。

出力形式は wav / mp3 / flac / opus / aac / pcm に対応し、リクエストごとの LoRA アダプタ切り替えやベアラートークン認証も備えています。既定では同時に走る合成は 1 件で、それ以上は待ち行列に入ります。同時アクセスが見込まれるなら、この上限とタイムアウトの設定を先に詰めておくべきです。

このほか、コミュニティ側でも WebGPU によるブラウザ内推論、ComfyUI 用のノード、独自の量子化で VRAM 1GB 前後を狙う実装、Google Colab 用のノートブックなど、派生プロジェクトが複数生まれています。VRAM 1GB という値は、公式の int4 版を手元で測った約 3.2GB とは別の実装によるものです。用途に近いものが既にあるか、一度探してみる価値はあります。

サーバーレスで動かす

常駐させる以上、使っていない時間も課金されます。生成が 1 日に数回しかないなら、リクエストが来たときだけコンテナを起動する構成のほうが割に合うかもしれません。

そこで RunPod Serverless に載せてみました。時間貸しの Pod とは別のプロダクトで、呼ばれたときだけワーカー (コンテナを載せる実行単位) が起動し、アイドルが続くと落ちます。つまずいたところを順に見ていきます。

モデルはイメージに焼き込む

ネットワークボリュームに置く手もありますが、存在するだけで容量課金が続くうえ、コールドスタートのたびに読み出しが挟まります。チェックポイント 3.06GB とコーデック 0.43GB の計 3.5GB なら、イメージに含めてしまうほうが無理がありません。

もうひとつ、1 リクエストで複数のセリフをまとめて受け取る作りにしています。モデルのロードに 16 秒かかる以上、セリフごとにリクエストを投げると待ち時間が支配的になるためです。ワーカーの起動時に一度だけ載せ、以降は使い回します。

CUDA のバージョン要求でコンテナが起動しない

最初に nvidia/cuda:12.8.1-cudnn-runtime-ubuntu22.04 を base にしたところ、ワーカーは立ち上がるのにコンテナが起動しませんでした。

nvidia-container-cli: requirement error:
unsatisfied condition: cuda>=12.8, please update your driver to a newer version,
or use an earlier cuda container

CUDA のイメージには NVIDIA_REQUIRE_CUDA という環境変数が設定されていて、nvidia-container-cli がこれを読み、ホストのドライバが条件を満たさないと起動を拒否します。サーバーレスでは割り当て先のホストを選べないので、新しすぎるバージョンを要求すると外れを引きます。

ベースイメージを 12.4.1 に下げて解決しました。PyTorch は cu128 のホイールのままです。CUDA 12 系にはマイナーバージョン互換があり、新しいマイナー版で追加された API を使わないかぎり、12.4 のドライバでも cu128 のビルドが動きます。

GPU プールを絞りすぎると空きが無い

次は、ワーカーが throttled のまま動かなくなりました。ホスト側が満杯という意味です。

VRAM は 5.4GB しか要らないので 24GB クラスで十分だと考えて ADA_24 だけを指定していたのですが、埋まっていると待つしかありません。プールを 5 つに広げたところ、すぐに割り当てられました。載る GPU を絞るのは主に単価のためなので、時間のほうが惜しい場面では広げておくのが無難です。

:latest は取り直されない

これがいちばん時間を使いました。コードを直してイメージを push し直しても、まったく同じエラーが出続けます。

エンドポイントの image をコミットの SHA を含むタグに切り替えたところ、取得が走りました。稼働中のワーカーは、タグが :latest のまま変わらないので手元のイメージを使い続けていた、と見られます。

CI でイメージを焼く構成にするなら、SHA のタグも一緒に push して、エンドポイントはそちらを指すのが確実です。

バッチは「同じセリフを N 本」だけ

セリフをまとめて投げる構成を考えるなら、ここは先に知っておくと設計が変わります。

num_candidates というパラメータがあり、名前から「複数の文をまとめて生成できる」と読めます。実際は違いました。実装を追うと、生成の入口は SamplingRequest を 1 つだけ受け取る形になっていて、内部ではこう書かれています。

self.tokenizer.batch_encode([normalized_text] * num_candidates, ...)

同じ文を候補の数だけ複製しているだけです。バッチの次元は候補に使われていて、異なるセリフには使えません。decode_mode"batch" も、候補のデコードをまとめる指定です。

つまり複数のセリフは 1 本ずつ順に回すことになります。ただしプロセスを跨がなければモデルのロードは一度きりなので、実用上の痛手は小さいはずです。

むしろ num_candidates は別の使いどころがあります。作者自身がモデルカードで「効果は文脈によって変わり、常に一貫するとはかぎらない」と書いているとおり、狙った表現を出すにはシードを変えて数回生成し、良いものを選ぶ工程が要ります。num_candidates はそれを 1 回の推論でまとめて行う仕組みです。選別を機械的にできる指標を持っているなら、そのまま自動化に載せられます。

ベンチマークをどう読むか

作者は評価結果もモデルカードで公開しています。読み方に注意が要る部分があるので、あわせて整理します。

日本語の読みの正確さは、SB Intuitions が公開する Joyo Kanji Yomi Benchmark と JSUT BASIC5000 で測っています。どちらも学習データには含まれていないと作者が明記しています。いずれの数字も読み誤り率なので、低いほど良い値です。

モデルJoyo Kanji Kana-CER ↓JSUT Sentence Kana-CER ↓
Irodori-TTS-600M-v3-VoiceDesign8.49%3.62%
Irodori-TTS-v4-Small7.43%3.49%
Irodori-TTS-v4.1-Small7.29%3.43%
T5Gemma-TTS (論文値)13.81%2.80%
Sarashina2.2-TTS Stage 2 (論文値)7.83%2.91%

この表を横並びの優劣として読むことはできません。作者自身が注記しているとおり、論文値のモデルは非公開の固定参照音声とその書き起こしを使っているのに対し、Irodori-TTS は参照音声もキャプションも使わずに生成した結果です。アーキテクチャも推論設定も違います。

その前提を踏まえたうえで見ると、常用漢字の読みでは、約 36 万時間の音声で学習された Sarashina2.2-TTS の数字を上回っています (時間数は Sarashina2.2-TTS の論文による)。一方で JSUT の文レベルでは下回っており、得意不得意が分かれます。

もうひとつ押さえておきたいのが、大規模な主観評価を実施していないという点です。自然さ・プロンプト追従・話者類似度のいずれについても人手の MOS 評価は行っておらず、自動評価のスコアが人間の知覚をそのまま代表するわけではないと作者が明記しています。数字だけで採否を決めず、自社の用途のテキストで実際に生成して耳で確かめる工程は省けません。

使いどころと、向かないところ

一次情報と実測を踏まえると、判断の分かれ目は次のように整理できます。

向いている向いていない
日本語だけを扱う多言語が必要
原稿を外部に送りたくない手軽さを最優先したい
生成量が多く従量課金を避けたいGPU を用意できない
感情や話し方を細かく作り込みたい決まった声をすぐ使いたい
短めのセリフを大量に作る長尺のナレーションを一括生成したい

対応言語が日本語のみである点は、そのまま適用範囲の線引きになります。モデルカードにも「日本語のテキスト入力のみに対応する」と明記されているため、多言語が必要な用途では別の選択肢を探すことになります。

FIXITFIXIT

結局、仕事で使うなら何から手をつければいいの?

TsumikiTsumiki

まず公式のデモ Space を触るのが早いです。環境構築なしで質感がわかります。

FIXITFIXIT

それで良さそうなら、次は?

TsumikiTsumiki

使いたい声の参照音声を 30 秒集めます。ここが揃わないと比較になりません。

FIXITFIXIT

GPU を買うのは、その後でいいってこと?

TsumikiTsumiki

はい。時間貸しで先に自社の原稿を通してから決めると、判断を間違えにくいです。

まとめ

Irodori-TTS は、絵文字で感情を指定できるという分かりやすい特徴の裏に、地に足のついた設計判断が積み重なっているモデルでした。

一次情報と実測から見えたのは、設計判断とライセンスが噛み合っているという一点です。

テキスト・参照音声・キャプション・絵文字という 4 系統の入力を単一のモデルで扱えるようになったのが v4 の到達点です。参照元の Echo-TTS が非商用のコーデックに縛られているのに対し、コーデックを自作して置き換えることで MIT を通しています。RTX 4090 では 7.8 秒の音声が 1.07 秒で生成でき、VRAM は 5.5GB、int8 量子化なら 3.3GB まで落ちます。一方で 1 回の生成は 30 秒が上限で、プロセス起動ごとに 16 秒のモデルロードが乗るため、業務利用では API サーバーを常駐させ、長文はチャンク分割する構成が前提になります。

弱点を作者自身がモデルカードに書き出しているのは、採否を判断する側からするとありがたい姿勢です。短い参照 1 本では v3 に劣ること、絵文字の効きが一貫しないこと、人手による主観評価を行っていないこと。こうした情報が揃っているからこそ、自社の用途に照らして冷静に判断できます。

FIXIT では、こうした新しいツールやモデルを実際に動かしたうえで、プロダクト開発のどこに組み込めるかを検証しています。音声を扱うプロダクトの設計や、ローカルモデルの業務導入でお困りのことがあれば、お問い合わせからご相談ください。

参考リンク