Google ColabでQwen3-TTSの音声クローニングを試す
はじめに
Qwen3-TTS を使って、Google Colab 上で音声クローニングを試したメモです。
今回のポイントは次の3つです。
- 1セルにまとめて実行できる
- MP4 / WAV / MP3 / M4A に対応
- 生成音声をZIPでまとめてダウンロードできる
参照ファイルが MP4(動画)でも、コード内で音声を取り出して WAV 化してから使えるようにしています。
注意
本記事の手順は、自分の声または本人の明確な同意を得た音声のみを対象にしてください。なりすまし用途は避けてください。
この記事でできること
- ColabでQwen3-TTSをセットアップ
- MP4から音声を抽出(ffmpeg)
- 参照音声 +
ref_textを使って音声クローニング - 生成したWAVをZIPで一括ダウンロード
- メタ情報(JSON)も一緒に保存
事前に用意するもの
- Google Colab
- 参照ファイル(MP4 / WAV / MP3 / M4A など)
- 参照音声で実際に話している文字列(
ref_text) - GPU(Colabのランタイム設定で有効化)
実行の流れ(先に全体像)
- ColabでGPUを有効化
- 下の「1セット実行コード」を1セルに貼って実行
- 参照ファイルをアップロード(MP4でもOK)
-
ref_textを入力(実際に話した内容をそのまま) - 音声生成結果を再生して確認
- ZIPをダウンロード
1セット実行コード(MP4対応)
以下を Colab の1セルにそのまま貼って実行します。
test_textsは読み上げたい文章なので、必要に応じて書き換えてください。
# ============================================================
# Google Colab用(1セット実行版)
# Qwen3-TTS 音声クローニング(MP4 / WAV / MP3 / M4A 対応)
# ※ 本人の声、または本人の明確な同意がある音声のみ使用してください
# ============================================================
# ---------- 0) インストール ----------
!apt-get -qq update
!apt-get -qq install -y ffmpeg sox libsox-fmt-all
%pip -q install -U qwen-tts soundfile pydub librosa
# ---------- 1) import ----------
import os
import json
import zipfile
import subprocess
import torch
import soundfile as sf
import librosa
from IPython.display import Audio, display
from google.colab import files
from qwen_tts import Qwen3TTSModel
print("CUDA available:", torch.cuda.is_available())
if torch.cuda.is_available():
print("GPU:", torch.cuda.get_device_name(0))
# ---------- 2) 参照ファイルをWAV化する関数(MP4対応) ----------
def convert_to_wav_if_needed(path: str, sample_rate: int = 24000) -> str:
ext = os.path.splitext(path)[1].lower()
# すでにWAV
if ext in [".wav", ".wave"]:
print("WAVそのまま使用:", path)
return path
# 音声ファイル(librosaで変換)
if ext in [".mp3", ".m4a", ".flac", ".mpeg", ".mpga", ".ogg"]:
print(f"{ext} をWAVに変換中(librosa)...")
y, sr = librosa.load(path, sr=sample_rate, mono=True)
out_wav = path.rsplit(".", 1)[0] + "_converted.wav"
sf.write(out_wav, y, sample_rate)
print("変換完了:", out_wav)
return out_wav
# 動画ファイル(ffmpegで音声抽出)
if ext in [".mp4", ".mov", ".mkv", ".webm", ".avi"]:
print(f"{ext} から音声を抽出してWAV化中(ffmpeg)...")
out_wav = path.rsplit(".", 1)[0] + "_audio.wav"
cmd = [
"ffmpeg", "-y",
"-i", path,
"-vn", # 動画を無視
"-ac", "1", # mono
"-ar", str(sample_rate),
out_wav
]
subprocess.run(cmd, check=True)
print("抽出完了:", out_wav)
return out_wav
print("未確認形式。元ファイルのまま試行:", path)
return path
# ---------- 3) モデルロード(声クローニング用 Base) ----------
# Colabでは float16 のほうが安定しやすいことが多い
dtype = torch.float16 if torch.cuda.is_available() else torch.float32
print("Baseモデルをロード中...")
clone_model = Qwen3TTSModel.from_pretrained(
"Qwen/Qwen3-TTS-12Hz-1.7B-Base",
device_map="cuda:0" if torch.cuda.is_available() else "cpu",
dtype=dtype,
)
print("Baseモデルのロード完了")
# ---------- 4) 参照ファイルをアップロード(MP4でもOK) ----------
print("\n参照ファイルをアップロードしてください(MP4/WAV/MP3/M4Aなど)")
uploaded = files.upload()
ref_input_path = list(uploaded.keys())[0]
print("アップロードされたファイル:", ref_input_path)
ref_audio_path = convert_to_wav_if_needed(ref_input_path, sample_rate=24000)
print("使用する参照音声:", ref_audio_path)
# 再生確認(任意)
print("\n参照音声の確認(再生)")
display(Audio(ref_audio_path))
# ---------- 5) ref_text入力(実際に話している内容をそのまま) ----------
print("\n参照音声で実際に話している内容を、できるだけ正確に入力してください")
ref_text = input("ref_text: ").strip()
print("ref_text =", ref_text)
# ---------- 6) 読み上げたいテキストを設定 ----------
# 必要に応じてここを書き換えてください
test_texts = [
"おはようございます。",
"今日はQwen3-TTSの音声クローニングを試しています。",
"これは参照音声を使って生成した音声です。"
]
# ---------- 7) 音声クローニング実行 ----------
generated_files = []
meta = {
"model": "Qwen/Qwen3-TTS-12Hz-1.7B-Base",
"dtype": str(dtype),
"ref_input_path": ref_input_path,
"ref_audio_path": ref_audio_path,
"ref_text": ref_text,
"language": "Japanese",
"generated_texts": test_texts,
}
for i, text in enumerate(test_texts, 1):
print(f"\n生成中 {i}: {text}")
wavs, sr = clone_model.generate_voice_clone(
text=text,
language="Japanese",
ref_audio=ref_audio_path,
ref_text=ref_text,
)
out_path = f"cloned_{i}.wav"
sf.write(out_path, wavs[0], sr)
generated_files.append(out_path)
print("保存:", out_path)
display(Audio(wavs[0], rate=sr))
# メタデータ保存
with open("generation_meta.json", "w", encoding="utf-8") as f:
json.dump(meta, f, ensure_ascii=False, indent=2)
print("\nメタデータ保存: generation_meta.json")
# ---------- 8) ZIPでまとめてダウンロード(任意) ----------
zip_name = "qwen_tts_outputs.zip"
with zipfile.ZipFile(zip_name, "w") as zf:
for f in generated_files:
zf.write(f)
zf.write("generation_meta.json")
print("ZIP作成完了:", zip_name)
files.download(zip_name)
使い方のコツ(精度を上げるポイント)
音声クローニングの出来は、ref_text の入力でかなり変わります。
1. ref_text は実音声と一致させる
アップロードした参照音声で話している内容を、できるだけそのまま入力します。
句読点も入れておくと自然になりやすいです。
2. 参照音声は「1人で」「雑音少なめ」
- BGMが大きい
- 複数人が重なる
- 無音が長い
このあたりは品質が落ちやすいです。
3. MP4のときは「声がはっきり入っている区間」を使う
長い動画なら、あとで ffmpeg で一部だけ切り出して使うと安定しやすいです。
よくあるエラーと対処
NameError: name 'torch' is not defined
セルを分けて実行していると起きやすいです。
この記事のコードは1セル完結なので、そのまま実行すれば回避しやすいです。
ModuleNotFoundError: No module named 'qwen_tts'
インストールが入っていない状態です。
ランタイム再起動後にも起きやすいので、先頭からもう一度実行します。
CUDA out of memory
1.7Bモデルが重いと出ることがあります。
いったんランタイム再起動して、他のセルを減らしてから再実行します。
bfloat16 関連のエラー
本コードでは最初から float16 を使っているので、Colabで通りやすい構成にしてあります。
出力ファイル
実行後に次のファイルが生成されます。
cloned_1.wavcloned_2.wavcloned_3.wavgeneration_meta.jsonqwen_tts_outputs.zip
generation_meta.json を残しておくと、あとで「どの参照音声・どの文章で試したか」を追いやすいです。
注意点(再掲)
- 本人の同意がない音声は使わない
- 公開する場合は個人情報が含まれないか確認する
- 用途と範囲を明確にして使う
まとめ
Qwen3-TTS の音声クローニングは、Colabでもかなり試しやすいです。
今回のコードでは、MP4入力対応・1セット実行・ZIP保存までまとめて扱えるようにしました。
まずは短い参照音声で動作確認して、ref_text を丁寧に合わせるところから始めると、結果の差が分かりやすいです。
# ==========================================
# 参照音声をGoogle Driveに保存して再利用する(Colab用・最小版)
# ==========================================
# 1) Driveをマウント
from google.colab import drive
drive.mount('/content/drive')
import os
import shutil
# 2) 保存先フォルダを作成
SAVE_DIR = "/content/drive/MyDrive/qwen_tts_refs"
os.makedirs(SAVE_DIR, exist_ok=True)
# 3) Colab内にある参照音声ファイル名を指定
# 例: "xxx_audio.wav" や "ref_converted.wav"
ref_audio_path = "xxx_audio.wav" # ←自分の参照音声ファイル名に変更
# 4) Driveへコピー保存
dst_path = os.path.join(SAVE_DIR, os.path.basename(ref_audio_path))
shutil.copy(ref_audio_path, dst_path)
print("保存完了:", dst_path)
# ==========================================
# 次回使うとき
# ==========================================
# Driveに保存した音声を参照音声として指定する
ref_audio_path = dst_path
print("再利用する参照音声:", ref_audio_path)
Discussion