技術 約11分で読めます

ZONOS2はVRAM 8GBのRTX 4060 Laptopでも日本語音声を生成できた

いけさん目次

Zyphraが2026年6月12日にZONOS2を公開した。
8B総パラメータ、推論時900MアクティブのMoE TTSで、重みはHugging Faceに出ている。
日本語は英語・中国語と並んでTier 1扱い。ただし、公式ブログに並ぶ比較音声のテキストは英語中心で、日本語の生成済み音声をそのまま記事に貼れる形では見つからなかった。

確認できた日本語の見本は、Hugging Face Space multimodalart/ZONOS2 の例文。

私は数秒の音声からどんな声でも再現できます。

これはSpace上で生成するための例文で、事前生成された音声ファイルではない。
2026年6月14日時点では、YouTube検索でもZONOS2の日本語音声デモとして参照しやすい動画は見つからず、旧Zonos v0.1の英語チュートリアルが多く混ざった。

ZONOS2の要点

ZONOS2は、テキストからDACトークンを自己回帰で生成し、44.1kHzの音声に戻すTTSモデル。
公式ブログでは、次の構成として説明されている。

項目内容
モデル規模8B総パラメータ、900Mアクティブ
アーキテクチャスパースMoE
学習音声600万時間超
出力DAC経由の44.1kHz音声
ボイスクローン2048次元の話者埋め込みで条件付け(実装・configはQwen3 voice embedding。公式概要文はECAPA-TDNNと記載で食い違い)
ライセンスモデルカードはApache 2.0
最大生成ブログ上では最長1分の多言語・コードスイッチング音声に対応と説明

Hugging Faceの params.json では、28層、隠れ次元2048、9コードブック、コードブックサイズ1024、最大シーケンス長6144。
MoEは16エキスパート、top-k 1、26層目だけtop-k 2になっている。

モデル本体の model.pth は約15.3GB。
15.3GBの重みとCUDA前提の実装なので、CUDAサーバで回すオープンウェイトTTSとして扱う。

日本語はTier 1

Hugging FaceとGitHubのREADMEでは、対応言語が3段階に分かれている。
Tier 1は英語、中国語、日本語。Tier 2に韓国語、ロシア語、イタリア語、ポルトガル語、フランス語、スペイン語、ベトナム語、ドイツ語、ヘブライ語、オランダ語が入る。

API側にも language パラメータがあり、テキスト正規化の指定として ja が用意されている。

{
  "text": "私は数秒の音声からどんな声でも再現できます。",
  "language": "ja",
  "stream": true
}

ZONOS2で日本語が重く扱われている理由は、旧Zonos v0.1からの変更にある。
Zyphraの説明では、ZONOS2は明示的な音素化に依存せず、生のUTF-8バイトを入力表現として使う。
これにより、音素化辞書や言語ラベルに由来する誤りを減らし、中国語・韓国語・日本語のような非欧州言語の扱いを改善した、と書いている。
さらに、固定の言語トークンに依存しないため、文中の言語切り替えにも対応しやすい。

公式ブログの音声見本は英語中心

Zyphraの公式ブログには、ZONOS2、Fish Audio、Qwen、Cartesia、ElevenLabsなどを並べた比較音声がある。
ページから取得できた音声アセットは33個。表示上の話者・プロンプトは、DwarkeshTrumpBritish FemaleParks and Recreation GuyDavid AttenboroughArlechinoObamaなどで、確認できるテキストは英語だった。

公式ブログは「音声比較ページ」ではあるが、日本語の固定サンプルURLを拾う場所にはならない。
日本語がTier 1という主張は、モデルカード、README、Spaceの例文、または自分で生成した音声で確認する。

Hugging Face Spaceには日本語例文がある

2026年6月14日時点で、Hugging Face上にはZONOS2を使うSpaceが2つ見つかる。

Space状態日本語の手がかり
multimodalart/ZONOS2Running on Zero言語ドロップダウンに Japanese、例文に日本語あり
Mike0021/zonos2ZeroGPU言語ドロップダウンに ja、例文は英語とフランス語

multimodalart/ZONOS2app.py には、言語マップとして "Japanese": "ja" があり、例文欄に次の行が入っている。

["私は数秒の音声からどんな声でも再現できます。", "Japanese"]

2026年6月14日時点で見つけた日本語例文はこの行だった。
ただし、SpaceのUIで実行して音声を生成するタイプなので、公式ブログのように固定URLの音声ファイルを記事へ直貼りする形ではない。

ローカル実行はLinuxとCUDA前提

READMEの Quick Start には、対応環境としてLinux x86_64のみ、NVIDIA GPUとCUDA Toolkitが必要と書かれている。
Apple SiliconでGGUFを落として試すタイプのローカルLLMとは違う。

GitHub READMEの起動例は次の形。

git clone https://github.com/Zyphra/Zonos2.git
cd Zonos2
uv sync
uv run python -m zonos2 --model-path Zyphra/ZONOS2 --tts-default-voices-dir ./default_voices/

サーバはデフォルトで http://localhost:1919 に立つ。
日本語を投げるなら、languageja を入れる。

curl -X POST http://localhost:1919/tts/generate \
  -H "Content-Type: application/json" \
  -d '{"text":"私は数秒の音声からどんな声でも再現できます。","language":"ja","stream":true}' \
  --output zonos2-ja.pcm

レスポンスはfloat32 PCM、44.1kHz、モノラル。WAVにするには次の変換を挟む。

ffmpeg -f f32le -ar 44100 -ac 1 -i zonos2-ja.pcm zonos2-ja.wav

Hugging Faceのモデルカードでは起動コマンドが python -m minisgl になっており、GitHub READMEでは python -m zonos2 になっている。
2026年6月14日時点では表記が揺れているので、実行時はGitHubの最新READMEとSpace実装の両方を確認する。

8GBノートのRTX 4060 Laptopで実際に動かしてみた

「Linux x86_64 + CUDA前提」とだけ書かれていると、VRAM 8GBのノートでは無理に見える。
実際にWindows 11 + WSL2のRTX 4060 Laptop(VRAM 8GB)で動かしたら、素直には2回詰まったが、最終的に日本語音声の生成まで通った。

検証環境は次のとおり。

  • Windows 11 + WSL2(Ubuntu 22.04)
  • NVIDIA GeForce RTX 4060 Laptop GPU(専用VRAM 8GB)
  • ホストRAM 31.7GB(WSLには既定で約15.8GB割り当て)
  • torch 2.9.1+cu128、モデルはbf16

素直にロードするとKVキャッシュで停止する

TTSLLM(model_path="Zyphra/ZONOS2") でそのままロードすると、bf16の重みが約14.3GiBあり、8GBの物理VRAMには収まらない。
それでもクラッシュしないのは、WSL2のNVIDIAドライバに「システムメモリフォールバック」があるため。VRAMを超えた分は共有GPUメモリ(=ホストのメインRAM)へ自動退避され、cudaMalloc は8GBを超えても成功する。

指標
PyTorchがGPUに要求した量14.287 GiB
物理VRAM使用7.95GB(8GB上限に張り付き、空き0)
共有GPUメモリへの溢れ(Windows実測ピーク)7.12GB
CPU側ロード時のWSL RAMピーク約15.4GB(15.8GB中)

torch.load(map_location="cpu") で15.3GBのチェックポイントを一度システムRAMに展開してからGPUへ移す実装なので、ロード中はWSL側のRAMもほぼ使い切る。

ただしここで止まる。エラーはOOMクラッシュではなく、次のアサーション。

AssertionError: Not enough memory for KV cache, try reducing --num-tokens

KVキャッシュ(テキスト生成中に各トークンのkey/valueを保持しておく作業領域)が大きすぎたわけではない。
重みが先に物理VRAMを8GB使い切り、KV用の物理VRAMが0になったため、エンジンが「1ページも割り当てられない」と判断して停止した。

KVキャッシュのページ数を手動指定して迂回する

engine/config.py を読むと、KVキャッシュのページ数には上書き用のパラメータがある。

num_page_override: int | None = None  # if not None, will override the number of pages

自動計算は「ロード前の空きメモリ − 重みのサイズ」でページ数を出すため、重みのほうが大きいと負になってアサートで死ぬ。
num_page_override を明示すれば、この計算を丸ごと飛ばせる。

tts = TTSLLM(model_path="Zyphra/ZONOS2", dtype=torch.bfloat16,
             num_page_override=4096, max_running_req=1)

これでKVキャッシュ(4096ページ=0.22GiB)も共有メモリ側に確保され、アサートは通過した。
次に当たったのは別の壁。

RuntimeError: Could not find CUDA installation. Please set CUDA_HOME environment variable.

ZONOS2は埋め込み処理などでカスタムCUDAカーネルを実行時にJITコンパイルする。
これにはCUDAツールキット(nvcc)が要る。WSLにはドライバとtorch同梱のランタイムしかなく、nvccが無いため、CUDAグラフ捕捉中のJITで止まった。

CUDAツールキットを入れると生成まで到達する

CUDA 12.8のツールキットをWSLに入れ、CUDA_HOME を通す。

wget https://developer.download.nvidia.com/compute/cuda/repos/wsl-ubuntu/x86_64/cuda-keyring_1.1-1_all.deb
sudo dpkg -i cuda-keyring_1.1-1_all.deb
sudo apt-get update
sudo apt-get install -y cuda-minimal-build-12-8
export CUDA_HOME=/usr/local/cuda-12.8
export PATH="$CUDA_HOME/bin:$PATH"

これでJITが通り、CUDAグラフ捕捉から生成まで進んだ。

generate OK in 105.3s
frames=398 eos=390 sr=44100
max_alloc_after_gen=15.508 GiB

実際に生成された音声がこれ。8GBノートでローカル生成した出力を、そのままMP3に変換したもの。

「私は数秒の音声からどんな声でも再現できます。」の生成結果は、44.1kHz・モノラル・約4.5秒のWAV。
生成スループットは約4.6 frames/s で、4.5秒の音声を出すのに105秒かかった。実時間のおよそ1/20で、リアルタイムには程遠い。
重みの約半分がメインRAM側にあり、推論のたびにPCIe越しに読む。この往復が速度を落としている。

なぜ8GBに載ったのか

専用VRAMは8GBしかないが、Windowsの共有GPUメモリはホストRAMの約半分まで使える。
今回は専用8GB + 共有約15.8GB = 約24GBがGPU側の予算で、ピーク15.5GiBはこの中に収まった。サイズだけ見れば最初から載る計算で、実際に載った。

ただし「動く」と「実用」は別。

  • KVキャッシュのページ数をコード側で手動指定する必要がある(公式の標準手順ではない)
  • CUDAツールキットの追加インストールが要る
  • 速度は実時間の約1/20

素直に使うなら、重み14.3GiBを物理VRAMに載せきれる16GBクラス以上のGPUが下限。
8GBで回すのは、フォールバック前提の力技になる。

flowchart TD
    A[8GB VRAMで素直にロード] --> B{重み14.3GiB が物理8GBを超過}
    B --> C[フォールバックで<br/>共有メモリへ約7GB退避]
    C --> D{KV用の<br/>物理VRAMが0}
    D -->|停止| E[Not enough memory<br/>for KV cache]
    E --> F[num_page_overrideで<br/>ページ数を手動指定]
    F --> G{カスタムカーネルの<br/>JITコンパイル}
    G -->|停止| H[CUDA_HOMEが無い<br/>nvcc不在]
    H --> I[CUDA 12.8ツールキット導入]
    I --> J[生成成功<br/>4.5秒の音声を105秒で出力]

日本語の固有名詞アクセントを表記で矯正する

8GBノートでローカル生成できるようになったので、ついでにこのブログのキャラ「かなちゃん」に喋らせてみた。
セリフは「こんちわ~、かなだよ。今何してるのかな?」。

ここで日本語TTSらしい問題が出た。名前の「かな」が、一般名詞の「仮名」と同じアクセントで読まれる。
語尾のピッチが上がってしまい、人名に聞こえない。

原因は構造的なもの。ZONOS2は音素化を挟まず生のUTF-8バイトを入力に使うため、アクセント辞書も「これは固有名詞」という手がかりも持たない。
「かな」が人名か一般名詞かを判断する材料がなく、学習データ上で多いであろう「仮名」側のアクセントで読む。
Spaceのテキスト正規化を通しても、あれは数字や記号の整形であってアクセントは直らない。

直接アクセントを指定する手段は無いので、表記でヒントを与えて回避する。
テキストの「かな」の書き方だけ変え、声・シードは固定して聞き比べた。

ひらがな「かな」。名前が「仮名」のアクセントになり、語尾が上がる。

カタカナ「カナ」。人名のアクセントで素直に聞き取れる。

「かなちゃん」。ちゃん付けでも人名読みに矯正される。

カタカナ表記か「〜ちゃん」付けで、人名アクセントに寄った。
日本語で人名・固有名詞を喋らせるなら、ひらがなのまま投げず、カタカナや愛称の形にしておくと安定する。

もう1点、サンプリング温度も影響する。
温度を1.3まで上げると発音自体が崩れ、名前以前に語が潰れた。今回の聞き比べは温度0.7〜0.8で、これくらいに下げると明瞭さが戻る。声を一定に保ちたいなら温度は低めがいい。

他のローカルTTSとの違い

このブログでは以前、Qwen3-TTSLuxTTS、それに日本語特化でよく使われているIrodori-TTSも見た。
ZONOS2はこれらとは立ち位置が違う。

モデル主な強み日本語実行の重さ
ZONOS2高忠実度ボイスクローン、MoE、44.1kHzTier 115GB級、CUDA前提
Irodori-TTS日本語特化、絵文字でスタイル・感情を制御、ゼロショットクローン日本語特化500M級、軽い(CPUでも可)
Qwen3-TTSセットアップの軽さ、日本語含む10言語、3秒クローン対応0.6B/1.7B系
LuxTTS軽量、1GB VRAM、速度日本語向けではない軽い

日本語だけが目的なら、日本語特化で軽いIrodori-TTSや、セットアップの軽いQwen3-TTSのほうが手順は少ない。
ZONOS2は重い代わりに、高忠実度クローンと44.1kHzの音質、それに多言語・コードスイッチングが要るときに選ぶ。

今わかること

ZONOS2は日本語をTier 1に入れている。
APIにも ja があり、Hugging Face Spaceにも日本語例文がある。
公式ブログの比較音声からは日本語の生成済みサンプルを拾えなかったが、今回はVRAM 8GBのRTX 4060 Laptopでローカル生成し、日本語音声を自分で用意できた。

日本語音声を出す手段を、現時点の候補としてまとめておく。

用途現時点の候補
公式仕様の確認Hugging Faceモデルカード、GitHub README
日本語例文の提示multimodalart/ZONOS2 Spaceの例文欄
手軽に日本語音声を出すHugging Face Space(ZeroGPU)かZyphra Cloud
ローカルで日本語音声を出す16GBクラス以上のGPUが素直。8GBでもフォールバック前提の力技なら可(実時間の約1/20)

日本語の出力は実際に聞けて、デフォルト声でも短文ならそのまま使えた。
ただし人名「かな」が「仮名」アクセントになるなど、固有名詞の読みは表記で寄せる必要がある。

参考リンク