TTS

Qwen3-TTS CustomVoice: озвучка текста готовыми голосами на Windows 11

Qwen3-TTS CustomVoice: озвучка текста готовыми голосами на Windows 11
Mikhail
Автор
Mikhail
Опубликовано 07.02.2026
0,0
Views 38

В этом гайде мы настроите локальную озвучку текста из TXT на Windows 11 с помощью Qwen3-TTS CustomVoice. Используем предустановленные голоса (speaker). На выходе получите файл WAV с озвучкой.

Подходит, если нужно быстро запустить TTS без подготовки референсного аудио.

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

  • Windows 11
  • NVIDIA RTX 3060 Ti, 8 GB VRAM
  • 32 GB RAM
  • Python 3.12
  • venv
  • PyTorch CUDA 12.4
  • SoX установлен и доступен системе

Важно про качество русской речи

В нашей версии CustomVoice доступны спикеры: aiden, dylan, eric, ono_anna, ryan, serena, sohee, uncle_fu, vivian. Это англоязычные голоса. Русский текст они озвучивают, но возможен акцент.

Если нужна озвучка вашим голосом или максимально естественная русская речь, используйте сценарий voice cloning с референсом. Отдельный гайд: https://aisferaic.ru/blog/tutorials/152/.

Структура папки проекта - шаг 1

Создайте папку проекта, например D:\voice, и положите туда входной текст.

Структура:

\voice\
├── .venv\
├── tts_ru_preset.py
├── article_ru.txt

Где:

  • article_ru.txt: текст для озвучки в UTF-8
  • tts_ru_preset.py: скрипт озвучки

Результат:

  • out_ru.wav: итоговый файл WAV

Установка окружения (venv, PyTorch, зависимости) - шаг 2

Откройте PowerShell и выполните последовательно команды в папке вашего проекта:

python -m venv .venv

.\.venv\Scripts\activate

python -m pip install -U pip

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

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

Установите зависимости для Qwen3-TTS:

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

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

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

SoX и PATH - шаг 3

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

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

Добавить 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 выводит версию, все готово.

Код: озвучка текста с помощью CustomVoice и speaker - шаг 4

Создайте файл tts_ru_preset.py рядом с article_ru.txt.

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


# ---- CONFIG ----
SOX_DIR = r"C:\Program Files (x86)\sox-14-4-2"
ARTICLE_PATH = Path("article_ru.txt")
OUT_PATH = Path("out_ru.wav")

# Модель для предустановленных голосов
MODEL_ID = "Qwen/Qwen3-TTS-12Hz-0.6B-CustomVoice"

# Поддерживаемые значения в вашей версии:
# aiden, dylan, eric, ono_anna, ryan, serena, sohee, uncle_fu, vivian
SPEAKER = "serena"

MAX_CHARS = 600
SILENCE_MS = 120

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


def _ts() -> str:
    return time.strftime("%H:%M:%S")


def _log(msg: str) -> None:
    print(f"[{_ts()}] {msg}", flush=True)


def _ensure_env():
    # На случай, если скрипт запускается из IDE с другим PATH
    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()
    _log(f"SoX OK: {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():
    t_start = time.time()
    _log("Start")
    _ensure_env()

    _log("Step 0: проверка SoX")
    _check_sox()

    # На Windows FP32 обычно надежнее, FP16 иногда падает с CUDA assert
    torch.backends.cuda.matmul.allow_tf32 = True
    torch.set_float32_matmul_precision("high")

    _log("Step 1: чтение входного текста")
    if not ARTICLE_PATH.exists():
        raise FileNotFoundError(f"Не найден файл: {ARTICLE_PATH.resolve()}")

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

    _log(f"Текст разбит на чанки: {len(chunks)} (MAX_CHARS={MAX_CHARS})")
    _log(f"Speaker: {SPEAKER}")
    _log(f"Model: {MODEL_ID}")

    _log("Step 2: загрузка модели (первый запуск может включать скачивание)")
    _log("Если видите прогресс Fetching files, идет скачивание с Hugging Face")
    t0 = time.time()

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

    _log(f"Step 2: модель готова за {time.time() - t0:.1f}s")

    _log(f"Step 3: генерация аудио ({len(chunks)} чанков)")
    all_wavs = []
    sr_final = None

    for i, chunk in enumerate(chunks, 1):
        _log(f"Chunk {i}/{len(chunks)}: start")
        tg0 = time.time()

        wavs, sr = model.generate_custom_voice(
            text=chunk,
            speaker=SPEAKER,
            language="Russian",
        )

        wav = wavs[0]
        all_wavs.append(wav)
        sr_final = sr

        dur = len(wav) / sr
        _log(f"Chunk {i}/{len(chunks)}: ok, audio={dur:.2f}s, gen_time={time.time() - tg0:.1f}s")

    _log("Step 4: склейка и сохранение WAV")
    audio = concat_wavs(all_wavs, sr_final, SILENCE_MS)
    sf.write(str(OUT_PATH), audio, sr_final)

    _log(f"Done. Saved: {OUT_PATH.resolve()}")
    _log(f"Total time: {time.time() - t_start:.1f}s")


if __name__ == "__main__":
    main()

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

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

python tts_ru_preset.py

Результат: out_ru.wav.

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

Как выбрать голос (speaker)

Поддерживаемые значения в нашей версии:

  • aiden
  • dylan
  • eric
  • ono_anna
  • ryan
  • serena
  • sohee
  • uncle_fu
  • vivian

Поменяйте переменную SPEAKER в коде и запустите снова. Это самый простой способ перебора.

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

SoX could not be found

Симптом: ошибка SoX could not be found.

Проверка:

where.exe sox

sox --version

Решение:

  • Добавьте папку SoX в PATH пользователя: C:\Program Files (x86)\sox-14-4-2
  • Убедитесь, что в коде SOX_DIR указывает на ту же папку
  • Если запускаете из IDE, попробуйте запуск из PowerShell или оставьте принудительное добавление PATH в _ensure_env

Таймауты при скачивании модели

Симптом: ReadTimeoutError на xethub или cas-bridge.

Решение в PowerShell:

$env:HF_HUB_DOWNLOAD_TIMEOUT="600"

$env:HF_HUB_ETAG_TIMEOUT="120"

python tts_ru_preset.py

Если не помогло, отключите Xet:

$env:HF_HUB_DISABLE_XET="1"

python tts_ru_preset.py

Warning про symlinks

Симптом: предупреждение про symlinks в кэше Hugging Face.

Это не ошибка. Можно игнорировать.

Чтобы убрать:

$env:HF_HUB_DISABLE_SYMLINKS_WARNING="1"

python tts_ru_preset.py

CUDA device-side assert triggered

Симптом: падение CUDA на генерации.

Решение:

  • Используйте FP32. В коде уже стоит dtype=torch.float32

Unsupported speakers

Симптом: ValueError Unsupported speakers.

Решение:

  • Укажите SPEAKER строго одной из строк из списка поддерживаемых

Что дальше

Если вы хотите качественную русскую озвучку без акцента, обычно есть два пути:

  • Озвучка вашим голосом через voice cloning с референсом, ссылка на отдельный гайд
  • Поиск набора preset, где есть русские спикеры, в рамках другой модели или другого набора голосов

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

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

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

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