🎙️ VibeVoice — Polskie głosy TTS: Agnes i Marek
Dwa polskie głosy TTS wytrenowane na bazie modelu VibeVoice-Realtime-0.5B.
🔗 Model bazowy: microsoft/VibeVoice-Realtime-0.5B
🎤 Głosy
| Głos | Plik | Typ | Opis |
|---|---|---|---|
| Agnes | pl-Agnes_woman.pt |
Kobieta | Naturalny, ciepły głos kobiecy |
| Marek | pl-Marek_man.pt |
Mężczyzna | Wyraźny, spokojny głos męski |
🚀 Szybki start
1. Instalacja zależności
# Klonuj repo VibeVoice
git clone https://github.com/microsoft/VibeVoice.git
cd VibeVoice
# Utwórz środowisko wirtualne
python3 -m venv venv
source venv/bin/activate
# Zainstaluj zależności
pip install -e .
pip install soundfile
2. Pobierz polskie głosy
from huggingface_hub import hf_hub_download
# Pobierz głos Agnes
agnes_path = hf_hub_download(
repo_id="Sticzu/vibevoice-polish-voices",
filename="pl-Agnes_woman.pt",
local_dir="./demo/voices/streaming_model/"
)
# Pobierz głos Marka
marek_path = hf_hub_download(
repo_id="Sticzu/vibevoice-polish-voices",
filename="pl-Marek_man.pt",
local_dir="./demo/voices/streaming_model/"
)
print(f"Agnes: {agnes_path}")
print(f"Marek: {marek_path}")
3. Generowanie mowy
import os, sys, torch, copy
from pathlib import Path
# Konfiguracja
VV_DIR = Path("./") # katalog VibeVoice
DEVICE = "cuda:0" # lub "cpu" jeśli brak GPU
MODEL_ID = "microsoft/VibeVoice-Realtime-0.5B"
# Ścieżki do głosów
VOICE_AGNES = VV_DIR / "demo/voices/streaming_model/pl-Agnes_woman.pt"
VOICE_MAREK = VV_DIR / "demo/voices/streaming_model/pl-Marek_man.pt"
# Importy modelu
sys.path.insert(0, str(VV_DIR))
from vibevoice.modular.modeling_vibevoice_streaming_inference import (
VibeVoiceStreamingForConditionalGenerationInference)
from vibevoice.processor.vibevoice_streaming_processor import VibeVoiceStreamingProcessor
# Załaduj model
model = VibeVoiceStreamingForConditionalGenerationInference.from_pretrained(
MODEL_ID,
torch_dtype=torch.bfloat16,
attn_implementation="sdpa",
)
model = model.to(DEVICE)
model.eval()
# Załaduj processor
processor = VibeVoiceStreamingProcessor.from_pretrained(MODEL_ID)
# Optymalizacja DDPM (6 kroków = szybko, 10+ = lepsza jakość)
DDPM_STEPS = 6
model.set_ddpm_inference_steps(DDPM_STEPS)
model.model.noise_scheduler.set_timesteps(DDPM_STEPS)
ns = model.model.noise_scheduler
ns.timesteps = ns.timesteps.to(DEVICE)
# Funkcja do ładowania głosu na GPU
def load_voice(path, device):
v = torch.load(str(path), map_location=device, weights_only=False)
def to_dev(obj):
if isinstance(obj, torch.Tensor):
return obj.to(device).to(torch.bfloat16) if obj.is_floating_point() else obj.to(device)
elif isinstance(obj, dict):
return {k: to_dev(vv) for k, vv in obj.items()}
elif isinstance(obj, list):
return [to_dev(i) for i in obj]
elif isinstance(obj, tuple):
return tuple(to_dev(i) for i in obj)
elif hasattr(obj, 'key_cache') and hasattr(obj, 'value_cache'):
obj.key_cache = [t.to(device).to(torch.bfloat16) if t.is_floating_point() else t.to(device) for t in obj.key_cache]
obj.value_cache = [t.to(device).to(torch.bfloat16) if t.is_floating_point() else t.to(device) for t in obj.value_cache]
return obj
return obj
return to_dev(v)
# Załaduj polskie głosy
voices = {
"agnes": load_voice(VOICE_AGNES, DEVICE),
"marek": load_voice(VOICE_MAREK, DEVICE),
}
# === GENEROWANIE MOWY ===
def synthesize(text, voice_name="agnes", output_path="output.wav"):
"""Generuje mowę z tekstu przy użyciu wybranego głosu."""
inputs = processor.process_input_with_cached_prompt(
text=text,
cached_prompt=copy.deepcopy(voices[voice_name]),
padding=True,
return_tensors="pt",
return_attention_mask=True,
)
for k, v in inputs.items():
if torch.is_tensor(v): inputs[k] = v.to(DEVICE)
with torch.inference_mode():
outputs = model.generate(
**inputs,
max_new_tokens=None,
cfg_scale=3.0,
tokenizer=processor.tokenizer,
generation_config={"do_sample": False},
verbose=False,
all_prefilled_outputs=copy.deepcopy(voices[voice_name]),
)
if outputs.speech_outputs and outputs.speech_outputs[0] is not None:
audio = outputs.speech_outputs[0]
processor.save_audio(audio, output_path=output_path)
duration = audio.shape[-1] / 24000
print(f"✅ Zapisano: {output_path} ({duration:.1f}s)")
return output_path
else:
print("❌ Brak wyjścia audio!")
return None
# Przykłady użycia
synthesize(
"Cześć! Jestem Agnes — polski głos VibeVoice.",
voice_name="agnes",
output_path="agnes_test.wav"
)
synthesize(
"Witaj! Mówi Marek. To jest test polskiego głosu.",
voice_name="marek",
output_path="marek_test.wav"
)
⚙️ Parametry
| Parametr | Wartość | Opis |
|---|---|---|
DDPM_STEPS |
6 | Kroki dyfuzji (6=szybko, 10+=lepsza jakość) |
cfg_scale |
3.0 | Skala Classifier-Free Guidance |
torch_dtype |
bfloat16 | Precyzja (oszczędza VRAM) |
sample_rate |
24000 Hz | Częstotliwość próbkowania wyjścia |
💻 Wymagania sprzętowe
| Komponent | Minimalne | Zalecane |
|---|---|---|
| GPU VRAM | 6 GB | 8 GB+ |
| RAM | 8 GB | 16 GB |
| GPU | RTX 3060 | RTX 4060/4090 |
| CUDA | 12.x | 12.4+ |
💡 Model działa też na CPU, ale jest wolniejszy (RTF > 1).
📊 Wydajność
Testowane na RTX 3060 (6GB VRAM), DDPM_STEPS=6:
| Głos | Tekst | Czas gen. | Audio | RTF |
|---|---|---|---|---|
| Agnes | 15 słów | ~15s | 4s | ~3.7 |
| Marek | 15 słów | ~13s | 4s | ~3.2 |
RTF < 1 = szybciej niż czas rzeczywisty (wymaga mocniejszego GPU)
🎧 Próbki audio
W folderze samples/ dostępne są przykładowe nagrania:
samples/agnes_sample.wav— Agnessamples/marek_sample.wav— Marek
📋 Szczegóły treningu
| Parametr | Wartość |
|---|---|
| Model bazowy | VibeVoice-Realtime-0.5B |
| Metoda fine-tuningu | LoRA (ac_conn + pred_head) |
| GPU treningowe | 2× NVIDIA (RTX 4060 + RTX 3060) |
| Dataset Agnes | ~750 próbek (2–6s każda) |
| Dataset Marek | ~500 próbek (trenowanych kroków: 205 500) |
| Język | Polski (pl) |
📄 Licencja
MIT — zgodna z oryginalnym modelem VibeVoice.