TTS

Клонирование голоса и озвучка текста бесплатно с Qwen3-TTS (Windows, RTX 3060)

Клонирование голоса и озвучка текста бесплатно с Qwen3-TTS (Windows, RTX 3060)
Mikhail
Автор
Mikhail
Опубликовано 06.02.2026
0,0
Views 51

Этот гайд показывает, как озвучить русский текст из файла TXT вашим голосом локально на ПК. Мы используем Qwen3-TTS и режим voice cloning: вы даете короткий референсный фрагмент своего голоса (ref.wav) и текст, который в нем произнесен (ref_text_ru.txt), а затем модель озвучивает article_ru.txt в похожем тембре.

Ориентировано на конфигурацию:

  • Windows 11
  • NVIDIA RTX 3060 Ti, 8 GB VRAM
  • 32 GB RAM
  • Python 3.12
  • venv
  • PyTorch CUDA 12.4

Важно про железо
На 8 GB VRAM начинайте с модели 0.6B. Модель 1.7B можно пробовать позже, но это уже режим экспериментов: выше риск нехватки VRAM и ниже предсказуемость.

Почему в гайде FP32, а не FP16

На Windows вы можете столкнуться с падением CUDA вида device-side assert triggered при FP16. Поэтому в инструкции сразу используем dtype=torch.float32. Это медленнее, но стабильнее.

Подготовьте папку проекта - шаг 1

Рекомендуемая структура:

\voice\
├── .venv\
├── tts_ru_clone.py
├── article_ru.txt
├── ref.wav
└── ref_text_ru.txt

Файлы:

  • article_ru.txt: текст статьи в UTF-8
  • ref.wav: ваш голос, референс
  • ref_text_ru.txt: точная расшифровка того, что сказано в ref.wav

Требования к ref.wav

  • WAV, mono, 16 kHz
  • Минимум 3 секунды, но лучше 15-30 секунд чистой речи
  • Без музыки, без эха, без шумодава, без пережатия мессенджерами
  • ref_text_ru.txt должен совпадать со словами в ref.wav. Если не совпадает, качество клона ухудшается

Установите SoX и добавьте в PATH - шаг 2

Qwen3-TTS пайплайн для аудио на Windows часто ожидает наличие sox.exe. Без него вы получите ошибку SoX could not be found.

2.1 Скачать и установить
SoX можно скачать со страницы проекта на SourceForge (https://sourceforge.net/projects/sox/) и установить как обычную программу.

2.2 Добавить SoX в PATH
У вас SoX может лежать здесь: C:\Program Files (x86)\sox-14-4-2\sox.exe

Добавляем в PATH именно папку:
C:\Program Files (x86)\sox-14-4-2

Шаги:

  1. Нажмите Win и введите: Изменение переменных среды (environment variables)
  2. Откройте: Изменение переменных среды для вашей учетной записи (Edit environment variables for your account)
  3. В блоке Переменные пользователя (User variables) найдите Path и нажмите Изменить (Edit)
  4. Нажмите Создать (New)
  5. Вставьте: C:\Program Files (x86)\sox-14-4-2 или ваш путь
  6. Нажмите ОК во всех окнах (OK)
  7. Закройте все окна PowerShell и откройте новый PowerShell

2.3 Проверка в PowerShell

where.exe sox
sox --version

Если команда sox --version выводит версию, все готово.

Создайте venv и установите зависимости - шаг 3

Откройте PowerShell в папке проекта. Создайте виртуальное окружение и активируйте его:

python -m venv .venv

.\.venv\Scripts\activate

Обновите pip:

python -m pip install -U pip

Установите PyTorch под CUDA 12.4:

pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu124

Установите qwen-tts и утилиты:

pip install -U qwen-tts soundfile numpy "huggingface_hub[hf_xet]" hf_xet

Проверьте, что PyTorch видит GPU:

python -c "import torch; print(torch.__version__); print(torch.cuda.is_available()); print(torch.version.cuda); print(torch.cuda.get_device_name(0) if torch.cuda.is_available() else None)"

Клон голоса + озвучка TXT + склейка WAV - шаг 4

Создайте файл tts_ru_clone.py в папке проекта:

import os
import re
import time
import subprocess
from pathlib import Path

import numpy as np
import soundfile as sf
import torch

from qwen_tts import Qwen3TTSModel


SOX_DIR = r"C:\Program Files (x86)\sox-14-4-2"  # папка с sox.exe
ARTICLE_PATH = Path("article_ru.txt")
REF_AUDIO_PATH = Path("ref.wav")
REF_TEXT_PATH = Path("ref_text_ru.txt")
OUT_PATH = Path("out_ru.wav")

MODEL_ID = "Qwen/Qwen3-TTS-12Hz-0.6B-Base"
MAX_CHARS = 600
SILENCE_MS = 120

HF_DOWNLOAD_TIMEOUT = "600"
HF_ETAG_TIMEOUT = "120"
HF_DISABLE_XET = ""  # если будут таймауты на xethub, поставьте "1"


def _ensure_env():
    os.environ["PATH"] = SOX_DIR + ";" + os.environ.get("PATH", "")

    os.environ.setdefault("HF_HUB_DOWNLOAD_TIMEOUT", HF_DOWNLOAD_TIMEOUT)
    os.environ.setdefault("HF_HUB_ETAG_TIMEOUT", HF_ETAG_TIMEOUT)
    os.environ.setdefault("HF_HUB_DISABLE_SYMLINKS_WARNING", "1")
    if HF_DISABLE_XET.strip():
        os.environ["HF_HUB_DISABLE_XET"] = HF_DISABLE_XET.strip()


def _check_sox():
    out = subprocess.check_output(["sox", "--version"], text=True).strip()
    print(f"[env] {out}")


def split_text_ru(text: str, max_chars: int) -> list[str]:
    text = re.sub(r"\s+", " ", text).strip()
    if not text:
        return []
    parts = re.split(r"(?<=[\.\!\?…])\s+", text)

    chunks, buf = [], ""
    for p in parts:
        p = p.strip()
        if not p:
            continue
        if not buf:
            buf = p
            continue
        if len(buf) + 1 + len(p) <= max_chars:
            buf = buf + " " + p
        else:
            chunks.append(buf)
            buf = p
    if buf:
        chunks.append(buf)
    return chunks


def concat_wavs(wavs: list[np.ndarray], sr: int, silence_ms: int) -> np.ndarray:
    silence = np.zeros(int(sr * (silence_ms / 1000.0)), dtype=np.float32)
    out = []
    for w in wavs:
        out.append(np.asarray(w, dtype=np.float32).reshape(-1))
        out.append(silence)
    return np.concatenate(out, axis=0) if out else np.zeros((0,), dtype=np.float32)


def main():
    _ensure_env()
    _check_sox()

    # На Windows FP16 иногда падает с CUDA assert, поэтому фиксируем FP32.
    torch.backends.cuda.matmul.allow_tf32 = True
    torch.set_float32_matmul_precision("high")

    print("1) reading inputs...")
    text = ARTICLE_PATH.read_text(encoding="utf-8")
    chunks = split_text_ru(text, MAX_CHARS)
    if not chunks:
        raise SystemExit("Пустой article_ru.txt")

    ref_text = REF_TEXT_PATH.read_text(encoding="utf-8").strip()
    if not ref_text:
        raise SystemExit("Пустой ref_text_ru.txt")

    print(f"   chunks: {len(chunks)} (MAX_CHARS={MAX_CHARS})")
    print("2) loading model (first run can be slow)...")
    t0 = time.time()

    model = Qwen3TTSModel.from_pretrained(
        MODEL_ID,
        device_map="cuda:0",
        dtype=torch.float32,
    )

    print(f"3) model loaded in {time.time() - t0:.1f}s")
    print("4) building voice clone prompt...")
    t1 = time.time()

    voice_prompt = model.create_voice_clone_prompt(
        ref_audio=str(REF_AUDIO_PATH),
        ref_text=ref_text,
        x_vector_only_mode=False,
    )

    print(f"5) voice prompt ready in {time.time() - t1:.1f}s")
    print(f"6) generating audio for {len(chunks)} chunks...")

    all_wavs = []
    sr_final = None

    for i, chunk in enumerate(chunks, 1):
        tg0 = time.time()
        wavs, sr = model.generate_voice_clone(
            text=chunk,
            language="Russian",
            voice_clone_prompt=voice_prompt,
        )
        wav = wavs[0]
        all_wavs.append(wav)
        sr_final = sr
        print(f"   [{i}/{len(chunks)}] ok: {len(wav)/sr:.2f}s, gen_time={time.time() - tg0:.1f}s")

    print("7) saving wav...")
    audio = concat_wavs(all_wavs, sr_final, SILENCE_MS)
    sf.write(str(OUT_PATH), audio, sr_final)
    print(f"Done. Saved: {OUT_PATH.resolve()}")


if __name__ == "__main__":
    main()

Запуск клонирования голоса и озвучки текста - шаг 5

Убедитесь, что venv активирован. Запустите скрипт:

python tts_ru_clone.py

Результат: out_ru.wav в той же папке.

Первый запуск может быть долгим. При первом запуске модель скачивается и загружается. Это нормально. Следующие запуски обычно заметно быстрее.

Частые проблемы и решения

SoX could not be found

Симптом: скрипт ругается, что SoX не найден.
Проверка:

where.exe sox

sox --version

Решение:

  • Добавьте папку SoX в PATH как в шаге 2.
  • Если запускаете из IDE, PATH может отличаться. В скрипте SOX_DIR принудительно добавляет путь для процесса Python, убедитесь, что SOX_DIR указывает на: C:\Program Files (x86)\sox-14-4-2

ReadTimeout при скачивании модели с Hugging Face

Симптом: таймауты на xethub или cas-bridge.
Решение 1: увеличить таймауты в PowerShell перед запуском

$env:HF_HUB_DOWNLOAD_TIMEOUT="600"

$env:HF_HUB_ETAG_TIMEOUT="120"

python tts_ru_clone.py

Решение 2: отключить Xet, если сеть нестабильна

$env:HF_HUB_DISABLE_XET="1"

python tts_ru_clone.py

Warning про symlinks на Windows

Симптом: предупреждение, что кэш Hugging Face не может использовать symlinks. Это не ломает работу, но кэш может занимать больше места.
Решения:

  • Игнорировать
  • Включить Developer Mode в Windows
  • Или убрать предупреждение:
$env:HF_HUB_DISABLE_SYMLINKS_WARNING="1"

python tts_ru_clone.py

CUDA error: device-side assert triggered

Симптом: падение на генерации, часто после установки pad_token_id.
Решение:

  • Используйте FP32 на Windows. В этом гайде уже стоит dtype=torch.float32.

CUDA out of memory

Симптом: нехватка видеопамяти.
Решения:

  • Уменьшите MAX_CHARS до 300-400
  • Закройте приложения, которые держат VRAM
  • Оставайтесь на 0.6B

Как попробовать 1.7B на 8 GB VRAM

Сначала добейтесь стабильной работы 0.6B.
Если хотите тест 1.7B:

  • Поменяйте MODEL_ID на 1.7B Base
  • Поставьте MAX_CHARS 300
  • Запустите и следите за nvidia-smi Если получите OOM или станет слишком медленно, возвращайтесь на 0.6B.

Примечание про нормализацию громкости
Если нужно выровнять громкость, это обычно делают постобработкой (например ffmpeg loudnorm или sox gain). В этом туториале я намеренно не добавляю нормализацию в код, чтобы оставить минимально надежный путь.

Авторизуйтесь, чтобы оставить комментарий.

Комментариев: 0

Нет комментариев.