Qwen3-TTSの日本語ボイスクローンをMacで動かす【Python】
Text to Speechのモデル「Qwen3-TTS」が登場したので試してみました。このモデル、自分の声を数秒の音声で複製(ボイスクローン)できるというのが特徴です。今回は、ボイスクローンを実際にPythonコードでやってみましたので、サンプルコードを紹介します。
Qwen3-TTSとは、
Qwen3-TTSは、Alibaba CloudのQwenが公開したオープンソースのText to Speech(Text2Speech)モデルです(2026年1月22日公開)
このブログではTTSモデルをいくつか紹介してきましたが、このモデルは、①商用利用可能、②自身の音声を複製(ボイスクローン)できることが大きな特徴です。
対応言語に「日本語」も含まれているため、早速日本語でのボイスクローンに挑戦してみました。
この記事では、MacOS環境でPythonから利用する方法を紹介します。自分でプログラミングして使いたい方の参考になれば幸いです。
このブログのコードは以下にあります
https://github.com/aruaru0/Qwen3-TTS-test
インストール
最初にインストールを行います。Python環境にuvを使っている場合は、以下のコマンドで仮想環境を作っておきます。uvのインストール方法は以下のブログ記事にあります。

仮想環境を作りたいフォルダで、以下のコマンドを実行します。
uv venv初期化が完了すると .venv フォルダが作成されます。以下のコマンドで仮想環境を有効化し、qwen-ttsをインストールします。
source .venv/bin/activate
uv pip install qwen-tts 
qwen3-ttsではsoxを必要としますので、もしインストールしていない場合はhomebrewでインストールしておきます。homebrewのインストール方法は以下の記事を参考にしてください。

インストール後は、以下のコマンドでインストールできます。
brew install sox任意のフォルダを作成後、以下のコマンドを実行
uv venv
source .venv/bin/activate
uv pip install qwen-tts
基本的な使い方
英語音声
PythonからQwen3-TTSを使うのは非常に簡単です。
このプログラムを実行すると、test01.wav として音声ファイルが生成されます。
import torch
import soundfile as sf
from qwen_tts import Qwen3TTSModel
model = Qwen3TTSModel.from_pretrained(
"Qwen/Qwen3-TTS-12Hz-1.7B-CustomVoice",
device_map="mps",
dtype=torch.bfloat16,
)
wavs, sr = model.generate_custom_voice(
text="Hello, how are you?",
language="English",
speaker="Ryan",
)
sf.write("test01.wav", wavs[0], sr)用意された声を使う場合、Qwen/Qwen3-TTS-12Hz-1.7B-CustomVoiceをモデルとして設定します。Macの場合、device_map="mps"にします。
modelのインスタンスを作成したら、あとは、generate_custom_voiceで喋らせたいテキストを指定します。
この例では、言語を英語にしています。公式にありますが、英語の発話モデルの話者はRyanという名前みたいです。
このプログラムを実行すると、test00.wavとして音声ファイルができます。
日本語音声
日本語音声の場合のプログラムも先ほどとほぼ同じです。
import torch
import soundfile as sf
from qwen_tts import Qwen3TTSModel
model = Qwen3TTSModel.from_pretrained(
"Qwen/Qwen3-TTS-12Hz-1.7B-CustomVoice",
device_map="mps",
dtype=torch.bfloat16,
)
wavs, sr = model.generate_custom_voice(
text="こんにちは、私になにか御用ですか?",
language="Japanese",
speaker="Ono_Anna",
)
sf.write("test02.wav", wavs[0], sr)違いは、language="Japanese" を指定する点です。日本語話者は Ono_Anna が用意されています。
再生して聞いてみた感じ、なんかアクセントが少し変です・・・・
ボイスクローン
ここからメインのボイスクローンの方法を説明します。
ボイスクローンでは、録音したmp3, wavファイルが必要です。今回は、「あみたろの音声素材工房」の音声を使わせていただきました。
あみたろの音声素材工房: https://amitaro.net
ボイスクローン①
ボイスクローンを行うには、「参照する音声ファイル」と「音声ファイルの話している内容を書いたテキストファイル」の2つが必要です。秒数は60秒までと書かれていましたが、数秒あればそれなりに似たボイスを作れるようです。
import torch
import soundfile as sf
from qwen_tts import Qwen3TTSModel
model = Qwen3TTSModel.from_pretrained(
"Qwen/Qwen3-TTS-12Hz-1.7B-Base",
device_map="mps",
dtype=torch.bfloat16,
)
ref_audio = "https://amitaro.net/download/voice/111_ganbaru/anmarimuzukashiku_01.wav"
ref_text = "あんまりむずかしく考えすぎるといろいろ大変だしね、しっかり反省したらぱぱっと行こう!"
wavs, sr = model.generate_voice_clone(
text="大丈夫だよ、これから何度だって挑戦すればいいんだから",
language="Japanese",
ref_audio=ref_audio,
ref_text=ref_text,
instruct="As the news anchor says"
)
sf.write("test03.wav", wavs[0], sr)
ボイスクローンを行う場合、モデルはQwen/Qwen3-TTS-12Hz-1.7B-Baseになります。
ref_audioは、ローカルにあるファイルだけでなく、URL指定もできました。
モデルのインスタンス作成後、generate_voice_clone関数を呼び出すことで音声を生成できます。
instruct引数は、いろいろな指示が与えられるようです(日本語もOK)。ここでは、アナウンサーのような喋り方を指定しましたが、うまく機能しているかよくわかりませんでした。
ボイスクローン②
ボイスクローンをする2つめの方法です。
あらかじめ音声をしておき、その後クローンを作るという方法です。繰り返しテキストを渡して音声を作る場合などは、こちらの方法が推奨されています。
import torch
import soundfile as sf
from qwen_tts import Qwen3TTSModel
model = Qwen3TTSModel.from_pretrained(
"Qwen/Qwen3-TTS-12Hz-1.7B-Base",
device_map="mps",
dtype=torch.bfloat16,
)
ref_audio = "https://amitaro.net/download/voice/111_ganbaru/anmarimuzukashiku_01.wav"
ref_text = "あんまりむずかしく考えすぎるといろいろ大変だしね、しっかり反省したらぱぱっと行こう!"
voice_clone_prompt = model.create_voice_clone_prompt(
ref_audio=ref_audio,
ref_text=ref_text,
)
wavs, sr = model.generate_voice_clone(
text="""
本日の天気は、全国的に概ね晴れとなる見込みです。
しかし、午後は大気の状態が不安定になるため、急な雨や雷にご注意ください。
お出かけの際は、折りたたみ傘を持っていくと安心でしょう。
以上、気象情報をお伝えしました。
""",
language="Japanese",
voice_clone_prompt=voice_clone_prompt,
instruct="女性。標準的な日本語のアクセントで、落ち着いて発音。ゆっくり話す。",
)
sf.write("test04.wav", wavs[0], sr)
先ほどと異なるのは、create_voice_clone_promptであらかじめ、参照する音声とテキストを登録していることです。
今回は少し長めのテキストを話させてみました。instructも細かく指定してみましたが、なんとなく機能しているようにも聞こえます。
ただ、「雷」がおかしかったり、読み方を間違うパターンもあるみたいです。この場合はひらがなにすれば良さそうです。
処理時間の計測
①と②の手法で速度が異なるか時間計測してみました。測定につかったMacは以下のスペックです。
MacBook Pro : M4Max 128GB
以下は計測に使用したプログラムです。
import torch
import soundfile as sf
from qwen_tts import Qwen3TTSModel
import time
from functools import wraps
def timer(func):
@wraps(func) # 元の関数のメタデータを保持
def wrapper(*args, **kwargs):
start = time.perf_counter() # 計測開始
result = func(*args, **kwargs)
end = time.perf_counter() # 計測終了
print(f"実行時間 ({func.__name__}): {end - start:.4f} 秒")
return result
return wrapper
model = Qwen3TTSModel.from_pretrained(
"Qwen/Qwen3-TTS-12Hz-1.7B-Base",
device_map="mps",
dtype=torch.bfloat16,
)
ref_audio = "https://amitaro.net/download/voice/111_ganbaru/anmarimuzukashiku_01.wav"
ref_text = "あんまりむずかしく考えすぎるといろいろ大変だしね、しっかり反省したらぱぱっと行こう!"
@timer
def method1():
wavs, sr = model.generate_voice_clone(
text="大丈夫だよ、これから何度だって挑戦すればいいんだから",
language="Japanese",
ref_audio=ref_audio,
ref_text=ref_text,
)
@timer
def method2_1():
voice_clone_prompt = model.create_voice_clone_prompt(
ref_audio=ref_audio,
ref_text=ref_text,
)
return voice_clone_prompt
@timer
def method2_2():
global voice_clone_prompt
wavs, sr = model.generate_voice_clone(
text="大丈夫だよ、これから何度だって挑戦すればいいんだから",
language="Japanese",
voice_clone_prompt=voice_clone_prompt,
)
for _ in range(10):
method1()
voice_clone_prompt = method2_1()
for _ in range(10):
method2_2()計測結果を見ると、②の方が若干速度が上がっている気はします。
Fetching 4 files: 100%|████████████████████████████████████████████████████████████████████████████████████████████| 4/4 [00:00<00:00, 21760.33it/s]
Setting `pad_token_id` to `eos_token_id`:2150 for open-end generation.
実行時間 (method1): 12.5603 秒
Setting `pad_token_id` to `eos_token_id`:2150 for open-end generation.
実行時間 (method1): 10.2508 秒
Setting `pad_token_id` to `eos_token_id`:2150 for open-end generation.
実行時間 (method1): 9.3695 秒
Setting `pad_token_id` to `eos_token_id`:2150 for open-end generation.
実行時間 (method1): 10.6178 秒
Setting `pad_token_id` to `eos_token_id`:2150 for open-end generation.
実行時間 (method1): 10.7287 秒
Setting `pad_token_id` to `eos_token_id`:2150 for open-end generation.
実行時間 (method1): 10.1432 秒
Setting `pad_token_id` to `eos_token_id`:2150 for open-end generation.
実行時間 (method1): 10.3042 秒
Setting `pad_token_id` to `eos_token_id`:2150 for open-end generation.
実行時間 (method1): 12.3442 秒
Setting `pad_token_id` to `eos_token_id`:2150 for open-end generation.
実行時間 (method1): 10.0701 秒
Setting `pad_token_id` to `eos_token_id`:2150 for open-end generation.
実行時間 (method1): 11.3259 秒
実行時間 (method2_1): 0.6746 秒
Setting `pad_token_id` to `eos_token_id`:2150 for open-end generation.
実行時間 (method2_2): 10.4085 秒
Setting `pad_token_id` to `eos_token_id`:2150 for open-end generation.
実行時間 (method2_2): 8.5917 秒
Setting `pad_token_id` to `eos_token_id`:2150 for open-end generation.
実行時間 (method2_2): 8.2806 秒
Setting `pad_token_id` to `eos_token_id`:2150 for open-end generation.
実行時間 (method2_2): 11.3703 秒
Setting `pad_token_id` to `eos_token_id`:2150 for open-end generation.
実行時間 (method2_2): 9.2123 秒
Setting `pad_token_id` to `eos_token_id`:2150 for open-end generation.
実行時間 (method2_2): 10.2720 秒
Setting `pad_token_id` to `eos_token_id`:2150 for open-end generation.
実行時間 (method2_2): 9.1840 秒
Setting `pad_token_id` to `eos_token_id`:2150 for open-end generation.
実行時間 (method2_2): 10.0569 秒
Setting `pad_token_id` to `eos_token_id`:2150 for open-end generation.
実行時間 (method2_2): 9.5072 秒
Setting `pad_token_id` to `eos_token_id`:2150 for open-end generation.
実行時間 (method2_2): 9.2455 秒
| 方式 | 平均実行時間 |
| 方式① | 平均10.77秒 |
| 方式② | 平均9.61秒 |

メモリ使用量は6GB〜7GBくらいだと思います。実行中のメモリを見るとPythonで使っていました。
その他気になる点
モデルの特性上しょうがないですが、実行するたびに音声が変化します(かなり変化します)。気に入ったパターンになるまで何度も実行する必要がありそうです。

LLMの制御と同じtemperatureなどのパラメータで制御できますが、思った発話を狙うのは難しそう
まとめ
Qwen3-TTSをMacOSのPythonから利用する方法について解説しました。ボイスクローンが割といい感じです。オープンソースでここまでできるとすごいとしか言いようがありません。


