TTS

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

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

Этот гайд показывает, как озвучить русский текст из файла 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

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

Тут может быть ваша реклама

Пишите info@aisferaic.ru

Похожие туториалы