Голос как вектор: почему 1024 измерения меняют всё
Представьте, что голос человека можно превратить в математический объект. Не в файл WAV, не в спектрограмму, а в чистый вектор из 1024 чисел. Это именно то, что делает Qwen3-TTS 1.7B - последняя версия на февраль 2026 года. В отличие от старых систем, где голос "зашивался" в веса модели, здесь он становится отдельной сущностью, с которой можно работать как с обычными данными.
Что умеют эти векторы (и чего не умеют)
Голосовой эмбеддинг Qwen3 - не волшебная палочка. Он не сохраняет акцент, не копирует манеру речи и уж точно не воспроизводит эмоции из исходной записи. Зато он делает три вещи блестяще:
- Клонирует тембр - даёт синтезатору понять, "как звучать"
- Смешивается с другими эмбеддингами - можно создать гибридный голос
- Интерполируется - плавный переход от одного голоса к другому
Почему именно 1024 измерения? В более ранних версиях (до Qwen3-TTS 1.5B) использовалось 2048. Разработчики Alibaba нашли, что 1024 достаточно для качественного представления, но требует меньше вычислений. На практике разницу в качестве не слышно, а скорость выросла на 15-20%.
Сравнение с альтернативами: почему Qwen3 выигрывает у конкурентов
| Инструмент | Размерность эмбеддинга | Требует обучения? | Качество на русском |
|---|---|---|---|
| Qwen3-TTS 1.7B | 1024 | Нет (zero-shot) | Отличное |
| XTTS v2 | Непублично | Нет | Хорошее |
| Bark | Нет эмбеддингов | Да (fine-tuning) | Среднее |
| VALL-E X | 768 | Нет | Хорошее |
Главное преимущество Qwen3 - открытость. В отличие от XTTS, где эмбеддинги скрыты внутри модели, здесь вектор доступен как обычный numpy-массив. Можно сохранить его в JSON, передать по API, даже визуализировать в 2D через t-SNE.
Практика: от аудио до вектора за 4 строки кода
1 Установка и загрузка модели
На февраль 2026 года актуальная версия - Qwen3-TTS-1.7B. Не берите старые 1.5B или 0.5B - в них другой размер эмбеддингов (2048 и 512 соответственно).
pip install transformers torch soundfile
from transformers import Qwen3TTSForConditionalGeneration, AutoProcessor
import torch
model = Qwen3TTSForConditionalGeneration.from_pretrained(
"Qwen/Qwen3-TTS-1.7B",
torch_dtype=torch.float16,
device_map="auto"
)
processor = AutoProcessor.from_pretrained("Qwen/Qwen3-TTS-1.7B")
2 Извлечение эмбеддинга из голоса
Здесь важный нюанс: модель ожидает аудио длиной 5-30 секунд. Короче - недостаточно данных. Длиннее - обрежется. Идеально - 10-15 секунд чистой речи без фонового шума.
import soundfile as sf
audio, sr = sf.read("образец_голоса.wav")
inputs = processor(
text="", # Пустой текст - нам нужен только эмбеддинг
audio=audio,
sampling_rate=sr,
return_tensors="pt"
).to(model.device)
# Извлекаем эмбеддинг голоса
with torch.no_grad():
speaker_embedding = model.extract_speaker_embedding(**inputs)
# speaker_embedding.shape: torch.Size([1, 1024])
# Сохраняем для будущего использования
import numpy as np
np.save("мой_голос.npy", speaker_embedding.cpu().numpy())
Не пытайтесь извлекать эмбеддинг из музыки или шума. Модель выдаст вектор, но синтез будет звучать как случайный голос. Нужна именно речь, желательно на том языке, который планируете использовать для синтеза.
Математические операции с голосами: создаём то, чего не существует
Вот где начинается магия. Поскольку голос - это просто вектор в 1024-мерном пространстве, с ним работают все линейные операции.
Смешивание двух голосов
Хотите голос, который на 70% похож на диктора А и на 30% на диктора Б?
embedding_a = np.load("голос_а.npy") # [1, 1024]
embedding_b = np.load("голос_б.npy") # [1, 1024]
# Линейная интерполяция
hybrid = 0.7 * embedding_a + 0.3 * embedding_b
# Нормализуем, чтобы не выйти за пределы распределения
hybrid = hybrid / np.linalg.norm(hybrid) * np.linalg.norm(embedding_a)
Создание "среднего" голоса из нескольких образцов
Полезно для создания универсального корпоративного голоса из записей нескольких сотрудников.
embeddings = []
for voice_file in ["сотрудник1.npy", "сотрудник2.npy", "сотрудник3.npy"]:
emb = np.load(voice_file)
embeddings.append(emb)
# Среднее арифметическое
corporate_voice = np.mean(embeddings, axis=0)
Поиск похожих голосов
Если у вас база из сотен эмбеддингов, можно искать голоса, похожие на целевой:
from sklearn.metrics.pairwise import cosine_similarity
target_embedding = np.load("целевой_голос.npy")
all_embeddings = np.load("база_голосов.npy") # [N, 1024]
similarities = cosine_similarity(target_embedding, all_embeddings)
most_similar_idx = np.argmax(similarities)
Синтез речи с модифицированным эмбеддингом
После всех математических манипуляций нужно вернуть вектор обратно в аудио:
# Загружаем или создаём модифицированный эмбеддинг
custom_embedding = np.load("гибридный_голос.npy")
custom_embedding = torch.from_numpy(custom_embedding).to(model.device)
# Текст для синтеза
text = "Это синтезированная речь с использованием модифицированного голосового эмбеддинга."
inputs = processor(
text=text,
return_tensors="pt",
sampling_rate=24000
).to(model.device)
# Подменяем стандартный эмбеддинг на наш
inputs["speaker_embedding"] = custom_embedding
# Синтез
with torch.no_grad():
output = model.generate(**inputs)
audio = output.audio.cpu().numpy().squeeze()
sf.write("результат.wav", audio, 24000)
Оптимизация для продакшена: vLLM-omni и ONNX
Базовая модель на 1.7B параметров требует около 4GB VRAM. Для продакшена это многовато. Вот два способа оптимизации:
vLLM-omni форк
Специальный форк vLLM для TTS-моделей. Ускоряет инференс в 2-3 раза за счёт оптимизированной реализации attention-механизмов для последовательностей разной длины (текст и аудио).
# Установка специального форка
pip install git+https://github.com/vllm-project/vllm-omni.git
# Загрузка модели через vLLM
from vllm_omni import LLM, SamplingParams
llm = LLM(
model="Qwen/Qwen3-TTS-1.7B",
quantization="fp16",
max_model_len=4096,
gpu_memory_utilization=0.8
)
ONNX-версия для веба
На Hugging Face появилась официальная ONNX-версия модели, которая работает в 4 раза быстрее на CPU и идеально подходит для веб-приложений. Размер эмбеддинга сохраняется - те же 1024 измерения.
from optimum.onnxruntime import ORTModelForSpeechSeq2Seq
# Загрузка ONNX-версии
model = ORTModelForSpeechSeq2Seq.from_pretrained(
"Qwen/Qwen3-TTS-1.7B-ONNX",
provider="CPUExecutionProvider" # или CUDAExecutionProvider
)
Если нужна максимальная скорость на CPU, посмотрите статью про Qwen3-TTS.cpp - там ускорение в 4 раза без потери качества.
Кому это нужно (а кому - нет)
Беритесь за Qwen3 эмбеддинги, если:
- Делаете систему озвучки с выбором голоса
- Нужно создать семейство похожих голосов для бренда
- Работаете над инструментом анонимизации голоса (совместите с speech-to-speech конверсией)
- Исследуете acoustics пространство для научных целей
Не тратьте время, если:
- Нужно клонировать голос с одной фразы (берите Kanade Tokenizer)
- Работаете только с английским (XTTS v2 проще)
- Нужен реальный time синтез с задержкой <200ms
- Хотите сохранить эмоции и интонации оригинала
Ограничения и подводные камни
Самая частая ошибка - ожидать, что смешивание голосов даст предсказуемый результат. Нет, голос (мать + отец) / 2 не будет звучать как их ребёнок. Это математическая абстракция, а не генетика.
Второй момент: эмбеддинги чувствительны к качеству входного аудио. Шум, эхо, компрессия MP3 - всё это добавляет "шум" в вектор. Результат будет работать, но качество синтеза снизится на 10-15%.
Третье: размерность 1024 - это компромисс. Для научных исследований иногда нужно больше (2048 в старых версиях давали чуть лучшее разделение похожих голосов). Для продакшена - даже многовато, 512 хватило бы.
Что будет дальше с голосовыми эмбеддингами
На февраль 2026 года вижу три тренда:
- Уменьшение размерности - Google уже экспериментирует с 256-мерными эмбеддингами для мобильных устройств
- Мультимодальность - один эмбеддинг для голоса, лица и стиля письма (пока фантастика, но в research papers уже есть)
- Стандартизация - попытки создать единый формат голосовых эмбеддингов, как JPEG для изображений
Мой прогноз: через год мы будем передавать голосовые профили как QR-коды. Отсканировал - и твой ассистент заговорил голосом друга. Звучит как антиутопия? Возможно. Но технически это уже почти реализуемо.
А пока - сохраняйте свои эмбеддинги в надёжном месте. Через пять лет, когда появится квантовая версия Qwen7-TTS, вам будет что в неё загрузить.