「Qwen3-TTS」を試す
Qwen3-TTSが正式にリリースされました。VoiceDesign、CustomVoice、Baseの全ファミリーをオープンソース化し、高品質をオープンコミュニティにもたらします。
- 5モデル(0.6B & 1.8B)
- 自由形式のボイスデザイン&クローニング
- 10言語対応
- 高圧縮のためのSOTA 12Hzトークナイザー
- 完全なファインチューニングサポート
- SOTAパフォーマンス
私たちは、これがこれまでのオープンソースTTSにおける最も破壊的なリリースであると信じています。さあ、試して壊してみて、クールなものを作ってください。🚀 すべてが今公開されています—重み、コード、論文。楽しんでください。🧵
Github: https://github.com/QwenLM/Qwen3-TTS
Hugging Face: https://huggingface.co/collections/Qwen/qwen3-tts
ModelScope: https://modelscope.cn/collections/Qwen/Qwen3-TTS
ブログ: https://qwen.ai/blog?id=qwen3tts-0115
論文: https://github.com/QwenLM/Qwen3-TTS/blob/main/assets/Qwen3_TTS.pdf
Hugging Faceデモ: https://huggingface.co/spaces/Qwen/Qwen3-TTS
ModelScope デモ: https://modelscope.cn/studios/Qwen/Qwen3-TTS
API: https://www.alibabacloud.com/help/en/model-studio/qwen-tts-voice-design
以前はオープンモデルではなかったので、API経由では試していたが、試したのは「Qwen3-TTS-Flash」というモデル。これは今回のモデルと比較して、どういう位置づけのものなのかな?多分商用向けってことなのだろうと思うけど。
日本語で試した時の当時の印象としては、よくある中国産TTSと同じで
- それなりに読み間違いが多い
- ElevenLabs等の商用には劣る
という感じで、ちょっと厳しいなと感じたが、果たして?
公式ブログ
Dia によるまとめ。
Qwen3-TTSは、ざっくり言うと「めちゃ高性能で細かくコントロールできる音声生成(TTS)ファミリー」だよ。
テキストから声を作るだけじゃなくて、「声のデザイン」「声真似(クローン)」「感情や話し方の細かい指定」まで全部乗せって感じ。
1. Qwen3-TTSって何してくれるモデルなの?
このページで説明されてるQwen3-TTSは、こんなことができるシリーズになってる:
- 声をゼロからデザイン
「イケボの落ち着いた中年男性で」「泣きそうな女子高生っぽく」とか、自然言語(普通の文章)で条件を書くだけで、そういうキャラっぽい声を作れる。- 声をクローン(コピー)
だいたい3秒くらいの音声から、その人の声質(声色・話し方)を真似したTTSを作れる。- 感情や話し方をコントロール
「ゆっくり」「小声で」「めっちゃ怒って」「テンション高めで」みたいな、速度・音量・ピッチ・感情・トーンなどをテキストで細かく指示できる。- 多言語対応
中国語・英語・日本語・韓国語・ドイツ語・フランス語・ロシア語・ポルトガル語・スペイン語・イタリア語 + 各種方言までサポート。しかも、全部オープンソースで、GitHubにもあるし、Qwen API経由でも使えるって書いてある。
2. モデルの種類:1.7Bと0.6B
1.7B系(大きい・高性能)
- Qwen3-TTS-12Hz-1.7B-VoiceDesign
説明文を元に、声そのものをデザインするモデル。
→ 「悲しくてかすれた声」「テンション高くて明るい声」みたいな指示に強い。- Qwen3-TTS-12Hz-1.7B-CustomVoice
あらかじめ用意された9種類の高品質な声(性別・年齢・言語・方言違い)をベースに、指示でスタイルをコントロールするモデル。- Qwen3-TTS-12Hz-1.7B-Base
ベースモデル。
- 3秒の音声から高速に声クローンができる
- 他のカスタムモデルを作るためのファインチューニング元としても使える
0.6B系(軽量・効率重視)
- Qwen3-TTS-12Hz-0.6B-CustomVoice
1.7B-CustomVoiceの小さい版。9種類のティンバー(声質プリセット)に対応。性能と処理効率のバランス重視。- Qwen3-TTS-12Hz-0.6B-Base
軽量版ベースモデル。3秒クローン & ファインチューニング用という役割は1.7Bと同じだけど、小さいぶん軽い。
3. 中身のキモ:Tokenizerとアーキテクチャ
高性能な音声トークナイザー(Qwen3-TTS-Tokenizer-12Hz)
Qwen3-TTSは、Qwen3-TTS-Tokenizer-12Hzっていう独自のトークナイザーで音声を「圧縮して離散トークン」にして扱ってる。
ページに書いてあるポイント:
- 効率的な圧縮+高次元の意味表現
音声をただ圧縮するんじゃなくて、声のニュアンスや環境音までちゃんと持ったトークンにしてる。- パラリンガル情報も保持
感情・話し方・間の取り方みたいな「言葉以外の情報」や背景音も含めて再現できる。- 評価結果(LibriSpeech test-clean)
- PESQ(音質評価)で3.21(ワイドバンド)・3.68(ナローバンド)
- STOI(知覚的な聞き取りやすさ)0.96
- UTMOS 4.16
- 話者類似度 0.95
→ 「ほぼ元の声に近い品質で再構成できる」ってニュアンス。モデル構造(ユニバーサルEnd-to-End+Dual-Track)
- Universal End-to-End Architecture
「離散マルチコードブックLM」という構造で、途中の段階をいろいろ挟む古い構成(LM + DiT)のボトルネックや誤差の蓄積を避けてると書かれてる。
→ つまり、「テキスト→音声」を一気通貫でやることで、万能性・効率・上限性能を上げてる、って主張。- Dual-Trackハイブリッドストリーミング
同じモデルでストリーミングと非ストリーミングの両方を扱える設計。
- 1文字入力しただけで最初の音声パケットを出せる
- 端から端までの合成レイテンシは最小97ms
→ リアルタイムの会話系シナリオでも使えるレベルの低遅延を目指してる。
4. 「賢いテキスト理解+音声制御」
Qwen3-TTSは、単にテキストを読むだけじゃなくて:
- 自然言語の指示に従って
- 声色(timbre)、感情、プロソディ(抑揚・リズム)などを
- 柔軟にコントロールする
っていうコンセプトになってる。
ページの例だと:
- 性別(male/female)
- 年齢感(若め・中年・老年)
- ピッチ(高め・低め・途中で上げるなど)
- 速度(ゆっくり・早口・途中から加速)
- 音量(小声・普通・叫ぶレベル)
- トーン(命令口調・皮肉っぽい・明るい・冷静)
- 性格設定(外向的・権威的・おっとり など)
- 背景設定(職業・年齢・人生観まで含んだキャラプロファイル)
こういう情報を自然言語で長文指定して、それ通りのキャラボイスっぽい喋り方をさせる例が、サンプルとして大量に載ってる。
さらに:
- Age Control(幼い女の子っぽい声など)
- Gradual Control(途中で感情が高ぶっていく喋り)
- Human-likeness(普通の雑談っぽい自然な喋り)
- Background Information(「国家プロジェクトの老科学者」とか「TV局アナウンサー」といったキャラ設定)
みたいに、結構人間ぽい「演技」をさせてる。
5. ティンバー(声質プリセット)と再利用
Qwen3-TTSは、「ティンバー」(声質のプリセット) という形で、9種類の声を公開してる:
- 中国語話者の男女・年齢違い数人
- 英語話者
- 日本語・韓国語話者
- 北京方言・四川方言の話者 など
これらは:
- 単に読み上げるだけじゃなく
- 「同じ声で別の言語を話させる」(単一話者で多言語)
- ティンバーを保存して、マルチターン・マルチキャラの会話を作る
ために使えるイメージ。
ページには、ナレーション役・青年男性・大人の女性みたいな複数キャラを指定して、バーでの会話シーンを長めに喋らせるサンプルも載ってる。
→ 同じキャラが何度も出てくる長尺の対話で、「声の一貫性」を維持できるデモ。
6. Voice Clone(声真似)のデモ
1.7B-Baseモデルを使ったクローン例として:
- 中国語の声クローン
- 英語の声クローン
- クロスリンガルクローン(別言語で同じ声質)
が挙がってて、同じ人の短い元音声(Reference Sample)から、その声質のまま別テキスト(別言語含む)を読ませている。
また、「Text Robustness」の例としては:
- 中英混じり
- pinyin表記
- 記号
- 顔文字 (◍•͈⌔•◍)
- 数式っぽい表現
などを混ぜてもちゃんと読める、というサンプルが載ってる。
7. パフォーマンス(評価)
ページ内のパフォーマンス部分も要点だけまとめると:
- Voice Designタスク
InstructTTS-Evalというベンチマークで
- MiniMax-Voice-Design(クローズドソース)より、指示に従う能力と生成の表現力で優れている
- 他のオープンソースモデルよりも大きくリードと主張。
- Voice Controlタスク
- Qwen3-TTS-Instructが、単一話者で多言語をこなして平均WER 2.34%
- 音色を保ったままスタイル制御ができて、InstructTTS-Evalで75.4%
- 10分間の長尺生成でも中国語WER 2.36%、英語WER 2.81%
- Voice Cloneタスク
- Seed-tts-evalで、MiniMaxとSeedTTSより安定した中国語・英語クローン
- 10言語テストセットで平均WER 1.835%、話者類似度0.789
- MiniMax・ElevenLabsより良いと主張
- クロスリンガルクローンはCosyVoice3より良いという書き方
ただし、全部、「このページの説明の中でそう主張している」というレベルで、外部情報の補足はなし。
8. Tokenizerの復元デモ
最後にQwen-TTS-Tokenizer-12Hz単体の性能として:
- 方言音声
- 歌
- パラランゲージ(咳・笑い・掛け声など)
- 背景音
の「元音声」と「復元音声」が並んでいる。
→ 「ほぼ劣化なく再現できる」ことを見せるデモって位置づけ。
まとめ
このページに基づいて整理すると、Qwen3-TTSは:
- 高性能なトークナイザーで音声をトークン化して
- 離散マルチコードブックLM+エンドツーエンド構造で
- 超低レイテンシのストリーミングもできて
- 声のデザイン・クローン・感情&話し方制御・多言語を全部こなす
- 1.7B(高性能)と0.6B(軽量)の2サイズがあり
- 9種類の公開ティンバーと多数のデモを用意
- ベンチマーク上でSOTA級と主張
っていう、「オープンソースの多機能TTSファミリー」ってイメージだよ。
モデル
Qwen3-TTS-12Hz-1.7B-Baseのモデルカードから、全モデルで記述が共通してる概要部分を抜粋。翻訳はPLaMo翻訳。
Qwen3-TTS
概要
はじめに
referred from https://huggingface.co/Qwen/Qwen3-TTS-12Hz-1.7B-BaseQwen3-TTSは、主要10言語(中国語、英語、日本語、韓国語、ドイツ語、フランス語、ロシア語、ポルトガル語、スペイン語、イタリア語)を網羅するとともに、多様な方言音声プロファイルを提供し、グローバルなアプリケーションニーズに対応しています。さらに、高度な文脈理解能力を備えており、指示内容やテキストの意味内容に基づいて、声調・発話速度・感情表現を柔軟に制御可能で、ノイズの多い入力テキストに対する耐性も大幅に向上しています。主な特徴は以下の通りです:
- 強力な音声表現能力: 独自開発のQwen3-TTS-Tokenizer-12Hzを搭載し、音声信号の効率的な音響圧縮と高次元の意味表現を実現。パラリンガル情報(非言語情報)や音響環境の特徴を完全保持しつつ、軽量なnon-DiTアーキテクチャによって高速かつ高忠実度な音声再構成を可能にしています。
- 汎用的なエンドツーエンドアーキテクチャ: 離散型マルチコードブックLMアーキテクチャを採用することで、完全な情報伝達を実現するエンドツーエンド音声モデリングを実現。従来のLM+DiT方式に見られた情報ボトルネックやカスケードエラーを完全に回避し、モデルの汎用性・生成効率・性能限界を大幅に向上させています。
- 極限的な低遅延ストリーミング生成: 革新的なDual-Trackハイブリッドストリーミング生成アーキテクチャを採用し、単一モデルでストリーミング生成と非ストリーミング生成の両方をサポート。1文字入力直後に最初の音声パケットを出力可能で、エンドツーエンド合成遅延はわずか97msと、リアルタイム対話シナリオの厳しい要求要件を満たしています。
- インテリジェントなテキスト理解と音声制御: 自然言語指示に基づく音声生成をサポートし、音色・感情・韻律など多次元の音響属性を柔軟に制御可能。テキスト意味理解を深層的に統合することで、トーン・リズム・感情表現を適応的に調整し、「想像したものがそのまま聞こえる」というリアルな出力を実現しています。
モデルアーキテクチャ
referred from https://huggingface.co/Qwen/Qwen3-TTS-12Hz-1.7B-Baseリリース済みモデルの概要とダウンロード情報
以下に、既にリリースされているQwen3-TTSモデルの概要とダウンロード情報を提供します。技術レポートで言及されているその他のモデルについては、近日中にリリース予定です。ご自身のニーズに合ったモデルを選択してダウンロードしてください。
トークナイザ名 説明 Qwen3-TTS-Tokenizer-12Hz 入力音声をコード化し、コードから音声に復号可能なQwen3-TTS-Tokenizer-12Hzモデル
モデル 機能 対応言語 ストリーミング 指示制御 Qwen3-TTS-12Hz-1.7B-VoiceDesign ユーザー指定の説明文に基づいて音声デザインを実施 中国語、英語、日本語、韓国語、ドイツ語、フランス語、ロシア語、ポルトガル語、スペイン語、イタリア語 ✅ ✅ Qwen3-TTS-12Hz-1.7B-CustomVoice ユーザー指示による対象音声の音色制御が可能。性別・年齢・言語・方言の様々な組み合わせに対応した9種類のプレミアム音色をサポート 中国語、英語、日本語、韓国語、ドイツ語、フランス語、ロシア語、ポルトガル語、スペイン語、イタリア語 ✅ ✅ Qwen3-TTS-12Hz-1.7B-Base ユーザー提供の音声入力から3秒で高速に音声クローンを生成可能なベースモデル。他モデルのファインチューニング(FT)にも利用可能 中国語、英語、日本語、韓国語、ドイツ語、フランス語、ロシア語、ポルトガル語、スペイン語、イタリア語 ✅ Qwen3-TTS-12Hz-0.6B-CustomVoice 性別・年齢・言語・方言の様々な組み合わせに対応した9種類のプレミアム音色をサポート 中国語、英語、日本語、韓国語、ドイツ語、フランス語、ロシア語、ポルトガル語、スペイン語、イタリア語 ✅ Qwen3-TTS-12Hz-0.6B-Base ユーザー提供の音声入力から3秒で高速に音声クローンを生成可能なベースモデル。他モデルのファインチューニング(FT)にも利用可能 中国語、英語、日本語、韓国語、ドイツ語、フランス語、ロシア語、ポルトガル語、スペイン語、イタリア語 ✅
ざっくり、0.6B / 1.7B の2つのパラメータサイズで、それぞれで以下のバリエーション。
- ベースモデル: 音声クローン、ファインチューニング用
- カスタムボイス: プリセット音声に対してプロンプトで口調などを制御
- ボイスデザイン: 1.7Bのみ。声そのものをプロンプトで制御
あとは、これに加えてトークナイザーモデルがあるという感じ。
ライセンスは全てApache-2.0。
デモで一通り試せるみたいなので、手っ取り早く試すならそれで。
インストール
VRAM要件次第だけど、1.7Bで順に試していくのが良さそう。
- カスタムボイス
- ボイスデザイン
- ベース
の順で試す。環境はColaboratory L4で。
パッケージインストール
pip install -U qwen-tts
Successfully installed coloredlogs-15.0.1 humanfriendly-10.0 onnxruntime-1.23.2 qwen-tts-0.0.4 sox-1.5.0 transformers-4.57.3
Flash Attentionをインストール
pip install -U flash-attn --no-build-isolation
Successfully installed flash-attn-2.8.3
追記
soxがないとモデルロード時にWarningがでる。
ARNING:sox:SoX could not be found!
If you do not have SoX, proceed here:
- - - http://sox.sourceforge.net/ - - -
If you do (or think that you should) have SoX, double-check your
path variables.
なくても一応動いたけどインストールしておいたほうが良さそう。
!apt install -y sox
あとはそれぞれのモデル個別に試す。
カスタムボイス
モデルをロード
import torch
import soundfile as sf
from qwen_tts import Qwen3TTSModel
model = Qwen3TTSModel.from_pretrained(
"Qwen/Qwen3-TTS-12Hz-1.7B-CustomVoice",
device_map="cuda:0",
dtype=torch.bfloat16,
attn_implementation="flash_attention_2",
)
VRAM消費は4.3GBぐらい。
+-----------------------------------------------------------------------------------------+
| NVIDIA-SMI 550.54.15 Driver Version: 550.54.15 CUDA Version: 12.4 |
|-----------------------------------------+------------------------+----------------------+
| GPU Name Persistence-M | Bus-Id Disp.A | Volatile Uncorr. ECC |
| Fan Temp Perf Pwr:Usage/Cap | Memory-Usage | GPU-Util Compute M. |
| | | MIG M. |
|=========================================+========================+======================|
| 0 NVIDIA L4 Off | 00000000:00:03.0 Off | 0 |
| N/A 51C P0 28W / 72W | 4331MiB / 23034MiB | 0% Default |
| | | N/A |
+-----------------------------------------+------------------------+----------------------+
使える話者を確認。
model.get_supported_speakers()
['aiden',
'dylan',
'eric',
'ono_anna',
'ryan',
'serena',
'sohee',
'uncle_fu',
'vivian']
それそれの特徴はモデルカードに以下とある。
Qwen3-TTS-12Hz-1.7B/0.6B-CustomVoiceモデルにおいて、サポートされている話者リストと各話者の音声特性を以下に示します。最高品質の音声を得るには、各話者の母語を使用することをお勧めします。もちろん、すべての話者はモデルがサポートするあらゆる言語で音声を生成可能です。
話者名 音声特性説明 母語 Vivian 明るく、ややエッジの効いた若い女性の声質 Chinese Serena 温かみがあり優しい若い女性の声質 Chinese Uncle_Fu 深みのあるまろやかな声質を持つベテラン男性の声 Chinese Dylan クリアで自然な響きを持つ、若々しい北京語男性の声 Chinese (北京方言) Eric リズミカルで躍動感のある、少しハスキーなトーンの成都語男性の声 Chinese (四川方言) Ryan 力強いリズム感が特徴のダイナミックな男性の声 English Aiden 明るい中音域が特徴の、陽気なアメリカ英語男性の声 English Ono_Anna 軽やかで機敏な響きを持つ、遊び心のある日本語女性の声 Japanese Sohee 豊かな感情表現が特徴の、温かみのある韓国語女性の声 Korean
使える言語を確認。
model.get_supported_languages()
['auto',
'chinese',
'english',
'french',
'german',
'italian',
'japanese',
'korean',
'portuguese',
'russian',
'spanish']
では生成。サンプルコードでは、
- 話者: Vivian(中国語の女性の声)
- 言語: 中国語
- 発話テキスト: (日本語訳)「実は、私は他人の感情を観察するのがとても得意な人間だと気づきました。」
- 指示: (日本語訳)「特に怒りを込めて言う」
という感じ。
from IPython.display import Audio
wavs, sr = model.generate_custom_voice(
text="其实我真的有发现,我是一个特别善于观察别人情绪的人。",
language="Chinese", # 言語を自動で判定させる場合は `Auto`か 省略。言語が事前にわかっている場合は場合は、明示的に指定。
speaker="Vivian",
instruct="用特别愤怒的语气说", # 必要ない場合は省略化。
)
sf.write("output_custom_voice.wav", wavs[0], sr)
display(Audio(wavs[0], rate=sr))
約10秒ほどで生成された。生成されたものは以下。
日本語でもやってみる。
wavs, sr = model.generate_custom_voice(
text="実は、私は他人の感情を観察するのがとても得意な人間だと気づきました。",
language="Japanese",
speaker="Ono_Anna",
instruct="特に怒りを込めて言う",
)
sf.write("output.wav", wavs[0], sr)
display(Audio(wavs[0], rate=sr))
日本語にはなってるけど、指示の効果が薄い感がある。指示を中国語にしてみる。
wavs, sr = model.generate_custom_voice(
text="実は、私は他人の感情を観察するのがとても得意な人間だと気づきました。",
language="Japanese",
speaker="Ono_Anna",
instruct="用特别愤怒的语气说",
)
sf.write("output.wav", wavs[0], sr)
display(Audio(wavs[0], rate=sr))
英語で指示してみる。
wavs, sr = model.generate_custom_voice(
text="実は、私は他人の感情を観察するのがとても得意な人間だと気づきました。",
language="Japanese",
speaker="Ono_Anna",
instruct="extreamly anger",
)
sf.write("output.wav", wavs[0], sr)
display(Audio(wavs[0], rate=sr))
んー、いまいち感情が乗ってる感がない。話者にもよるのかな?
テキストと言語だけ日本語にして、あとは中国語にしてみる。
wavs, sr = model.generate_custom_voice(
text="実は、私は他人の感情を観察するのがとても得意な人間だと気づきました。",
language="Japanese",
speaker="Vivian",
instruct="用特别愤怒的语气说",
)
sf.write("output.wav", wavs[0], sr)
display(Audio(wavs[0], rate=sr))
んー、なんとなく指示は中国語もしくは英語が制御しやすいってところがありそうな気がする。まあいろいろ試してみる必要はありそう。
バッチで実行する場合はすべてリストで渡せば良いみたい。こういうので試行錯誤するのがいいかもね。
# batch inference
wavs, sr = model.generate_custom_voice(
text=[
"其实我真的有发现,我是一个特别善于观察别人情绪的人。",
"She said she would be here by noon."
],
language=["Chinese", "English"],
speaker=["Vivian", "Ryan"],
instruct=["", "Very happy."]
)
sf.write("output_custom_voice_1.wav", wavs[0], sr)
sf.write("output_custom_voice_2.wav", wavs[1], sr)
display(Audio(wavs[0], rate=sr))
display(Audio(wavs[1], rate=sr))
ボイスデザイン
モデルをロード
import torch
import soundfile as sf
from qwen_tts import Qwen3TTSModel
model = Qwen3TTSModel.from_pretrained(
"Qwen/Qwen3-TTS-12Hz-1.7B-VoiceDesign",
device_map="cuda:0",
dtype=torch.bfloat16,
attn_implementation="flash_attention_2",
)
VRAM消費は同じぐらいだったので割愛。
では推論。サンプルコードでは、
- 言語: 中国語
- 発話テキスト: (日本語訳)「お兄さん、お帰り!ずっとずっと待っていたから、抱きしめて!」
- 指示: (日本語訳)「甘えん坊で幼げなロリ声で、音程が高く抑揚がはっきりしており、粘着質でわざとらしく、わざとらしく可愛らしい聴覚的効果を生み出す。」
という感じの設定。
from IPython.display import Audio
wavs, sr = model.generate_voice_design(
text="哥哥,你回来啦,人家等了你好久好久了,要抱抱!",
language="Chinese",
instruct="体现撒娇稚嫩的萝莉女声,音调偏高且起伏明显,营造出黏人、做作又刻意卖萌的听觉效果。",
)
sf.write("output.wav", wavs[0], sr)
display(Audio(wavs[0], rate=sr))
ちなみにもう一度実行すると声が変わる。
日本語でも。指示も一応日本語で。
wavs, sr = model.generate_voice_design(
text="お兄さん、お帰り!ずっとずっと待っていたから、抱きしめて!",
language="Japanese",
instruct="甘えん坊で幼げなロリ声で、音程が高く抑揚がはっきりしており、粘着質でわざとらしく、わざとらしく可愛らしい聴覚的効果を生み出す。",
)
sf.write("output.wav", wavs[0], sr)
display(Audio(wavs[0], rate=sr))
一応効いてはいる様子。必ずしも中国語・英語である必要はないのかもしれないが、どういう学習をされているかにもよるよね。
あと、ちょっと発音というか読み間違えてる。ゼロにはならないにしても、どれぐらいの頻度で起きるか次第だなぁ。
カスタムボイス同様、バッチ推論もできる。
wavs, sr = model.generate_voice_design(
text=[
"哥哥,你回来啦,人家等了你好久好久了,要抱抱!",
"It's in the top drawer... wait, it's empty? No way, that's impossible! I'm sure I put it there!"
],
language=["Chinese", "English"],
instruct=[
"体现撒娇稚嫩的萝莉女声,音调偏高且起伏明显,营造出黏人、做作又刻意卖萌的听觉效果。",
"Speak in an incredulous tone, but with a hint of panic beginning to creep into your voice."
]
)
sf.write("output_voice_design_1.wav", wavs[0], sr)
sf.write("output_voice_design_2.wav", wavs[1], sr)
display(Audio(wavs[0], rate=sr))
display(Audio(wavs[1], rate=sr))
音声クローン(ベースモデル)
モデルをロード
import torch
import soundfile as sf
from qwen_tts import Qwen3TTSModel
model = Qwen3TTSModel.from_pretrained(
"Qwen/Qwen3-TTS-12Hz-1.7B-Base",
device_map="cuda:0",
dtype=torch.bfloat16,
attn_implementation="flash_attention_2",
)
VRAM消費は同じぐらいなので割愛。
発話させたいテキストに、リファレンスとなる音声とその文字起こしも追加して、推論。また、以下の例では、数式や顔文字が含まれている。
ref_audio = "https://qianwen-res.oss-cn-beijing.aliyuncs.com/Qwen3-TTS-Repo/clone.wav"
ref_text = "Okay. Yeah. I resent you. I love you. I respect you. But you know what? You blew it! And thanks to you."
wavs, sr = model.generate_voice_clone(
text="I am solving the equation: x = [-b ± √(b²-4ac)] / 2a? Nobody can — it's a disaster (◍•͈⌔•͈◍), very sad!",
language="English",
ref_audio=ref_audio,
ref_text=ref_text,
)
sf.write("output_voice_clone.wav", wavs[0], sr)
のだが、リファレンス音声が403になる。
---------------------------------------------------------------------------
HTTPError Traceback (most recent call last)
/tmp/ipython-input-196458161.py in <cell line: 0>()
4 ref_text = "Okay. Yeah. I resent you. I love you. I respect you. But you know what? You blew it! And thanks to you."
5
----> 6 wavs, sr = model.generate_voice_clone(
7 text="I am solving the equation: x = [-b ± √(b²-4ac)] / 2a? Nobody can — it's a disaster (◍•͈⌔•͈◍), very sad!",
8 language="English",
11 frames
/usr/lib/python3.12/urllib/request.py in http_error_default(self, req, fp, code, msg, hdrs)
637 class HTTPDefaultErrorHandler(BaseHandler):
638 def http_error_default(self, req, fp, code, msg, hdrs):
--> 639 raise HTTPError(req.full_url, code, msg, hdrs, fp)
640
641 class HTTPRedirectHandler(BaseHandler):
HTTPError: HTTP Error 403: Forbidden
OpenAI TTSで生成した、以下の音声でやってみる。
from IPython.display import Audio
ref_audio = "alloy-friendly-en.wav"
ref_text = "Good morning. The weather is really nice today. On a day like this, I feel like going to the racetrack."
wavs, sr = model.generate_voice_clone(
text="I am solving the equation: x = [-b ± √(b²-4ac)] / 2a? Nobody can — it's a disaster (◍•͈⌔•͈◍), very sad!",
language="English",
ref_audio=ref_audio,
ref_text=ref_text,
)
sf.write("output.wav", wavs[0], sr)
display(Audio(ref_audio)) # 比較用にリファレンス音声も再生
display(Audio(wavs[0], rate=sr))
ちょっとここまでとは違って30秒強と生成は長めだったが、リファレンス音声と同じ声で数式を読み上げているのがわかる(数式の読み方が正しいのかわからないけど)。顔文字はなんか発話されなかったな・・・
日本語でも。日本語のリファレンス音声。
from IPython.display import Audio
ref_audio = "alloy-friendly.wav"
ref_text = "おはようございます。今日はとてもいいお天気ですね。こんな日は競馬場に行きたいですね。"
wavs, sr = model.generate_voice_clone(
text="この方程式を解いています:x = [-b ± √(b²-4ac)] / 2a? 誰も解けない――大惨事です (◍•͈⌔•͈◍)、本当に悲しい!",
language="Japanese",
ref_audio=ref_audio,
ref_text=ref_text,
)
sf.write("output.wav", wavs[0], sr)
display(Audio(ref_audio))
display(Audio(wavs[0], rate=sr))
うーん、日本語だと数式や顔文字のところでちょっとおかしくなってしまっている。まあ数式とか結構難しいことやってると思うし、顔文字も国で異なるところがあると思うので、しょうがないかも。前半部分は普通に読めているので、ごくごく普通の文章で使うほうが良さそう。
なお、ここでは試していないが、リファレンス音声: 英語、生成音声: 日本語、みたいなクロスリンガルも一応できた。ただ言語は合わせたほうが良さそう。
リファレンス音声を使い回す場合は以下のようにすれば再計算が不要となる。推論が速くなるのかな?
%%time
# create_voice_clone_prompt でリファレンスを構築
prompt_items = model.create_voice_clone_prompt(
ref_audio=ref_audio,
ref_text=ref_text,
x_vector_only_mode=False,
)
wavs, sr = model.generate_voice_clone(
text=["こんばんは。今夜は月が綺麗ですね。", "こんにちは。今日も寒い日が続きますね。"],
language=["Japanese", "Japanese"],
# voice_clone_promptに構築したリファレンスを渡す
voice_clone_prompt=prompt_items,
)
sf.write("output_voice_clone_1.wav", wavs[0], sr)
sf.write("output_voice_clone_2.wav", wavs[1], sr)
display(Audio(wavs[0], rate=sr))
display(Audio(wavs[1], rate=sr))
CPU times: user 8.46 s, sys: 2.68 ms, total: 8.47 s
Wall time: 8.41 s
普通にバッチでそれぞれリファレンスを指定した場合。
%%time
wavs, sr = model.generate_voice_clone(
text=["こんばんは。今夜は月が綺麗ですね。", "こんにちは。今日も寒い日が続きますね。"],
language=["Japanese", "Japanese"],
ref_audio=[ref_audio, ref_audio],
ref_text=[ref_text, ref_text]
)
sf.write("output1.wav", wavs[0], sr)
sf.write("output2.wav", wavs[1], sr)
display(Audio(wavs[0], rate=sr))
display(Audio(wavs[1], rate=sr))
CPU times: user 8.25 s, sys: 4.97 ms, total: 8.26 s
Wall time: 8.16 s
あんまり変わらないな。でもまあ冗長に書かなくて済むし、もっと生成数が多ければ差が出てくるのかもしれない。
モデルカードには、ボイスデザインで音声を作成、それをクローンで使って音声を生成する、という例も載っているので参考までに。
トークナイザー
トークナイザーをロード
import soundfile as sf
from qwen_tts import Qwen3TTSTokenizer
tokenizer = Qwen3TTSTokenizer.from_pretrained(
"Qwen/Qwen3-TTS-Tokenizer-12Hz",
device_map="cuda:0",
)
音声をエンコードして音声トークンに変換する。上で使用したOpenAI TTS Alloyの日本語音声を使う。
# 音声をエンコードして音声トークン化
enc = tokenizer.encode("alloy-friendly.wav")
print(enc)
Qwen3TTSTokenizerV2EncoderOutput(audio_codes=[tensor([[ 932, 814, 901, ..., 616, 439, 1484],
[ 641, 518, 703, ..., 2025, 79, 100],
[2029, 1707, 1526, ..., 398, 1449, 1741],
...,
[ 338, 1008, 297, ..., 381, 518, 880],
[ 759, 1644, 1402, ..., 1531, 76, 956],
[ 58, 1647, 1286, ..., 1785, 988, 139]], device='cuda:0')])
音声トークンをデコードして音声に戻す。
from IPython.display import Audio
# エンコードされた音声トークンをデコードして音声に戻す
wavs, sr = tokenizer.decode(enc)
sf.write("output.wav", wavs[0], sr)
# エンコード前の音声と比較
display(Audio("alloy-friendly.wav"))
display(Audio(wavs[0], rate=sr))
違いがほとんどわからない。符号化しても音声の特徴が維持されているということだよね。
まとめ
もう少し試行回数を増やさないとわからないし、個人の印象だけだけども、以前アリババクラウドのAPIでQwen3-TTS-Flashを試したときより、日本語についてはいい感じになってるのではないか?という気がして、これなら・・・という期待感がある。
あと、軽量なのと、Apache-2.0ライセンスで公開されているのは、いろいろ使いやすくて嬉しいところ。
とはいえ、実際に使う場合、
- 数式とか顔文字、あと指示なんかについては、日本語よりも中国語・英語のほうが精度が良さそう。
- もっと試行回数を増やせば、読み間違いもそこそこ出て来そうな気がする。
- リアルタイムのユースケースで耐えれるほどの生成速度があるか?は不明(GPU環境にもよるし、0.6Bだと多少速くなるかも?)
あたり、商用トップクラスのTTSと比較すると(比較すること自体が間違いなのかもしれないが)、使いこなすための工夫は多少なりとも必要にはなるのではないかな?という気がしている。
その他
- Web UIもある
- vLLMでの推論も可能
Ubuntu-22.04(RTX4090)で、カスタムボイスのサンプルコードを元に、生成部分(model.generate_custom_voiceのところ)の時間をざっくり計測してみたけど、
- 1.7B: 3.8秒前後
- 0.6B: 4.5秒前後
という感じ。0.6Bのほうが遅いという不思議。
サンプルコードのテキストはそんなに長いものでもないので、やっぱりリアルタイムには足りないかも。
商用APIには入出力ストリーミングに対応したrealtimeモデルがあるので、そこと棲み分けてる感じかなぁ。
vLLMでストリーミングをサポート中、あと25Hz対応のトークナイザーが出てくるってことか。
Qwen3-TTSに関するたくさんの質問をいただいています—こちらが簡単なアップデートです! 🎙️
1️⃣ ストリーミングサポートは?
@vllm_project と協力してストリーミング推論を有効にする作業中です—vLLMチームに大感謝! 近日中にスムーズなリアルタイム体験をお楽しみに。2️⃣ 一貫した声のトーンは?
Voice Designを使ってお気に入りの声をピックアップし、次にBaseモデルのクローンフィーチャーを活用してそれを参照として固定してください。これで安定した一貫した出力が確保されます。3️⃣ BaseモデルはInstructスタイルの制御(例: 感情、スタイル)をサポートできますか?
はい—これは近日公開予定のオープンソース25Hzモデルリリースで対応します!