OmniVoice Real-Time TTS dla Polskiego
Porównanie OmniVoice z Chatterbox na RTX 5090 — opóźnienia, streaming, klonowanie głosu i jakość audio.
Modele
OmniVoice
autor: k2-fsa · Apache-2.0 · arXiv:2604.00688
Najnowocześniejszy wielojęzyczny model TTS zero-shot obsługujący ponad 600 języków — najszersza obsługa językowa wśród modeli TTS zero-shot. Wykorzystuje architekturę dyfuzyjnego modelu językowego z 8-warstwowym hierarchicznym koderem audio.
- Architektura: backbone Qwen3-0.6B (~600M parametrów), iteracyjne dekodowanie dyfuzyjne z maskowaniem
- Klonowanie głosu: zero-shot na podstawie nagrania referencyjnego + transkrypcji
- Projektowanie głosu: kontrola płci, wieku, wysokości, akcentu, dialektu, szeptu przez instrukcje tekstowe
- Paralingwistyka:
[laughter],[breath]oraz korekcja wymowy - Szybkość: RTF nawet 0.025 (40x szybciej niż w czasie rzeczywistym)
- Dostępny na: HuggingFace, CLI (
omnivoice-infer), demo Gradio
Chatterbox
autor: Resemble AI · Licencja MIT
Rodzina trzech modeli TTS open-source (Chatterbox, Chatterbox-Multilingual, Chatterbox-Turbo) zaprojektowanych do generowania naturalnej mowy z klonowaniem głosu. Wbudowany znak wodny Perth do wykrywania audio generowanego przez AI.
- Architektura: autoregresywny tokenizer mowy + dekoder mel-spektralny, 350M–500M parametrów
- Klonowanie głosu: zero-shot na podstawie nagrania referencyjnego
- Wariant Turbo: 350M parametrów, destylowany do 1-krokowego dekodowania dla agentów głosowych
- Paralingwistyka: natywne tagi
[laugh],[cough],[chuckle] - Języki: 23+ (angielski, hiszpański, francuski, niemiecki, polski, chiński, japoński, arabski, hindi itd.)
- Znak wodny: Perth — przetrwa kompresję MP3, ~100% skuteczności wykrywania
- Dostępny na:
pip install chatterbox-tts, HuggingFace
Przegląd architektury
| Chatterbox | OmniVoice | |
|---|---|---|
| Typ modelu | Autoregresywny (token po tokenie) | Dyfuzja z maskowaniem (iteracyjne odmaskowanie) |
| Backbone | Własny dekoder T3 | Qwen3-0.6B LLM (~600M parametrów) |
| Kodek audio | Pojedynczy strumień kodowy | 8-warstwowy hierarchiczny (8×1025 tokenów) |
| Streaming | Prawdziwy streaming token-po-tokenie | Brak natywnego streamingu — pełna sekwencja na wywołanie |
| Klonowanie głosu | Warunkowanie embeddingami | Tokenizacja audio referencyjnego + prefiks |
| Języki | Polski + podstawowy wielojęzyczny | 600+ języków natywnie |
Kluczowa różnica architektoniczna
Chatterbox działa w czasie rzeczywistym, ponieważ streamuje token po tokenie – dekoder autoregresywny emituje tokeny sekwencyjnie, każdy może być natychmiast dekodowany do audio i wysłany. TTFA = czas do wygenerowania pierwszych kilku tokenów.
OmniVoice wykorzystuje dyfuzję z maskowaniem – wszystkie tokeny audio zaczynają jako [MASK] i są iteracyjnie odmaskowane w N krokach. Każdy krok uruchamia pełne przejście przez cały model. Tokeny są ujawniane wg wyniku pewności, nie pozycji. Częściowe audio nie może być dekodowane w trakcie generowania.
Jednak surowa szybkość inferencji OmniVoice jest na tyle duża (RTF 0.01–0.04), że chunking na poziomie tekstu osiąga porównywalne lub lepsze TTFA niż streaming tokenowy Chatterboxa.
Test 1: Bazowa latencja
Pełne generowanie, klonowany głos, bez chunkingu. Całkowity czas od wywołania generate() do zwrócenia tensora.
| Tekst | Znaki | Audio | 32 kroki | 16 kroków | 8 kroków |
|---|---|---|---|---|---|
| mini | 12 | 1.2–1.5s | 269ms (RTF 0.222) | 136ms (RTF 0.094) | 72ms (RTF 0.054) |
| krótki | 66 | 4.3s | 298ms (RTF 0.069) | 151ms (RTF 0.035) | 80ms (RTF 0.019) |
| średni | 196 | 12.6s | 503ms (RTF 0.040) | 255ms (RTF 0.020) | 137ms (RTF 0.011) |
| długi | 488 | 28.5–28.9s | 849ms (RTF 0.030) | 446ms (RTF 0.015) | 255ms (RTF 0.009) |
- RTF poprawia się przy dłuższym tekście (stały narzut amortyzowany na więcej audio).
- 16 kroków to optimum: ~2x szybciej niż 32, degradacja jakości jest minimalna.
- Przy 8 krokach RTF spada do 0.009–0.054 – 18–110x szybciej niż w czasie rzeczywistym.
Test 2: Streaming chunkowany (pomiar TTFA)
Symulacja streamingu: podział tekstu na granicach zdań, niezależne generowanie każdego chunka, pomiar czasu do pierwszego gotowego chunka.
Tekst średni (196 znaków, 2 chunki)
| Kroki | TTFA (chunk 0) | Audio chunk 0 | Gen chunk 1 | Audio chunk 1 | Łącznie |
|---|---|---|---|---|---|
| 32 | 335ms | 7.00s | 327ms | 5.80s | 662ms |
| 16 | 169ms | 7.00s | 165ms | 5.80s | 333ms |
| 8 | 88ms | 7.00s | 86ms | 5.80s | 173ms |
Tekst długi (488 znaków, 5 chunków)
| Kroki | TTFA (chunk 0) | Chunki | Gen łącznie | Audio łącznie | RTF |
|---|---|---|---|---|---|
| 32 | 331ms | 5 | 1605ms | 29.6s | 0.054 |
| 16 | 168ms | 5 | 813ms | 29.6s | 0.027 |
| 8 | 87ms | 5 | 423ms | 29.6s | 0.014 |
Rozkład po chunkach (tekst długi, 16 kroków):
| Chunk | Czas gen. | Audio | Treść |
|---|---|---|---|
| 0 | 168ms | 7.00s | "Poważny błąd w obiegu dokumentów..." |
| 1 | 165ms | 5.80s | "Przez pomyłkę dokumentacja..." |
| 2 | 150ms | 4.08s | "Incydent został zgłoszony..." |
| 3 | 171ms | 7.44s | "Linia lotnicza przeprosiła..." |
| 4 | 159ms | 5.32s | "Związki zawodowe domagają się..." |
- Przy 16 krokach TTFA wynosi 169ms – 32% szybciej niż typowe 250ms Chatterboxa.
- Każdy chunk generuje ~4–7s audio w ~150–170ms. Bufor odtwarzania jest ogromny.
- Narzut chunkingu jest minimalny: całkowity czas generowania ~30% wyższy niż single-shot, ale korzyści ze streamingu zdecydowanie to rekompensują.
Test 3: Cache promptu klonowania głosu
create_voice_clone_prompt() wstępnie koduje audio referencyjne do wielokrotnego użycia.
| Tryb | Czas generowania |
|---|---|
| Surowa ścieżka ref_audio (kodowanie przy każdym wywołaniu) | 264ms |
| Wstępnie zcachowany VoiceClonePrompt | 255ms |
| Koszt utworzenia promptu | 37ms (jednorazowo) |
| Oszczędność na wywołanie | 9ms (3%) |
Kodowanie promptu jest już szybkie (37ms). Cache jest nadal warty implementacji na serwerze, aby uniknąć redundantnego kodowania.
Test 4: Współbieżna inferencja
Ten sam tekst, 3 zapytania
| Tryb | Czas całkowity | Na zapytanie | Przyspieszenie |
|---|---|---|---|
| Sekwencyjnie | 767ms | 255ms każde | 1.0x |
| 3x równolegle (pula wątków + strumienie CUDA) | 462ms | 436–460ms każde | 1.66x |
Różne długości tekstu, 3 równolegle
| Zapytanie | Tekst | Latencja | Audio |
|---|---|---|---|
| 0 | mini (12 znaków) | 408ms | 1.51s |
| 1 | średni (196 znaków) | 502ms | 12.58s |
| 2 | długi (488 znaków) | 555ms | 28.61s |
| Czas całkowity | 558ms |
- GIL + współdzielone wagi modelu ograniczają prawdziwy paralelizm do ~1.66x przyspieszenia dla 3 wątków.
- Latencja pojedynczego zapytania wzrasta ~1.8x pod obciążeniem.
- Wzorzec
InferenceSlot+SlotPoolz Chatterboxa poprawiłby to dalej.
Test 5: Rozkład pipeline’u
Szczegółowa instrumentacja każdego etapu, średnia z 5 uruchomień na konfigurację. RTX 5090, float16, klonowany głos.
Gdzie idą milisekundy
Pipeline OmniVoice ma 7 etapów. Etapy 1–4 (preprocessing) są pomijalne. Etap 5 (iteracyjne dekodowanie) dominuje – 87–97% całkowitego czasu.
| Etap | Krótki (66 zn., 4.4s audio) | Średni (196 zn., 12.6s audio) | ||||
|---|---|---|---|---|---|---|
| 32 kroki | 16 kr. | 8 kr. | 32 kroki | 16 kr. | 8 kr. | |
| 1. Preprocess/resolve | 0.0ms | 0.0ms | 0.0ms | 0.0ms | 0.0ms | 0.0ms |
| 2. Estymacja czasu trwania | 0.0ms | 0.0ms | 0.0ms | 0.0ms | 0.0ms | 0.0ms |
| 3. Tokenizacja tekstu + wejścia | 0.4ms | 0.4ms | 0.4ms | 0.5ms | 0.6ms | 0.5ms |
| 4. Konstrukcja batcha (CFG) | 0.2ms | 0.2ms | 0.2ms | 0.2ms | 0.2ms | 0.2ms |
| 5. Iteracyjne dekodowanie | 357ms | 182ms | 88ms | 521ms | 264ms | 130ms |
| 5a. Forward pass LLM | 330ms | 166ms | 82ms | 491ms | 246ms | 122ms |
| 5b. CFG + wybór tokenów | 27ms | 16ms | 7ms | 30ms | 17ms | 7ms |
| 6. Dekodowanie audio (wokoder) | 5.5ms | 3.7ms | 3.6ms | 12.3ms | 8.6ms | 8.3ms |
| 7. Post-processing | 3.3ms | 3.2ms | 3.1ms | 9.9ms | 9.8ms | 9.7ms |
| ŁĄCZNIE | 367ms | 190ms | 96ms | 544ms | 283ms | 148ms |
Tekst długi (488 zn., 28.5s audio, 950 tokenów)
| Etap | 32 kroki | % całkowitego |
|---|---|---|
| 5a. Forward pass LLM | 818ms | 90.5% |
| 5b. CFG + wybór tokenów | 40ms | 4.5% |
| 6. Dekodowanie audio (wokoder) | 21ms | 2.3% |
| 7. Post-processing | 24ms | 2.6% |
| ŁĄCZNIE | 905ms | 100% |
Koszt per krok
Każdy krok dyfuzji uruchamia pełny forward pass Qwen3-0.6B na całej sekwencji. Koszt skaluje się z długością sekwencji:
| Tekst | Długość sekwencji | Koszt per krok |
|---|---|---|
| Krótki (66 zn.) | 220 tokenów | ~11ms |
| Średni (196 zn.) | 465 tokenów | ~16ms |
| Długi (488 zn.) | 950 tokenów | ~27ms |
Wszystkie kroki mają jednakowy koszt – żaden nie jest istotnie droższy. Zmniejszenie liczby kroków o połowę zmniejsza czas LLM prawie dokładnie o połowę.
Kluczowe wnioski
- Forward pass LLM = 87–91% całkowitego czasu. Reszta to szum pomiarowy.
- Tokenizacja tekstu: <1ms. Pomijalna nawet dla długiego tekstu.
- Estymacja czasu trwania: <0.1ms. Reguły, bez sieci neuronowej.
- CFG + wybór tokenów: 5–8%. Matematyka classifier-free guidance, próbkowanie Gumbela, top-k.
- Dekodowanie audio (wokoder): 4–21ms. HiggsAudioV2 na GPU. Skaluje się z czasem trwania audio.
- Post-processing: 3–24ms. Usuwanie ciszy przez pydub (CPU). Liniowo z długością audio.
- Cel optymalizacji: Zmniejszenie kosztu forward pass (kwantyzacja, flash attention, KV caching) dałoby prawie liniowe przyspieszenie.
Test 6: Streaming zoptymalizowany pod pierwszy chunk
Najlepsza strategia: podział na pierwszym zdaniu, generowanie krótkiego pierwszego chunka dla minimalnego TTFA, reszta generuje się podczas odtwarzania pierwszego chunka.
| Kroki | TTFA | Pierwszy chunk gra | Czas gen. reszty | Przerwa? |
|---|---|---|---|---|
| 32 | 335ms | 7.00s | 700ms | Nie — reszta gotowa 6.3s wcześniej |
| 16 | 169ms | 7.00s | 357ms | Nie — reszta gotowa 6.6s wcześniej |
| 8 | 87ms | 7.00s | 185ms | Nie — reszta gotowa 6.8s wcześniej |
Nawet dla najdłuższego tekstu (488 znaków, 29s audio) nie ma żadnej przerwy w odtwarzaniu przy żadnej liczbie kroków. Pierwszy chunk generuje 7s audio, zapewniając ogromne okno buforowania. Margines wynosi 6–7 sekund – wystarczająco na jitter sieciowy, kodowanie i buforowanie po stronie klienta.
Test 7: Profil pamięci GPU
| Scenariusz | Szczytowy VRAM |
|---|---|
| Model załadowany (idle) | 5.41 GB |
| 1 inferencja | 5.61 GB |
| 3 równoległe inferencje | 5.87 GB |
| Zapas na 32 GB | 26.1 GB wolne |
| Szacowane max równoległych | ~5 |
Przyrostowy koszt na równoległą inferencję to ~150 MB. Duży zapas na dodatkowe instancje modelu lub równoległe zapytania.
OmniVoice vs Chatterbox
| Metryka | Chatterbox | OmniVoice (16 kroków) | Zwycięzca |
|---|---|---|---|
| TTFA | ~250ms | 169ms | OmniVoice |
| RTF (tekst średni) | 0.05–0.10 | 0.020 | OmniVoice |
| Typ streamingu | Prawdziwy token-po-tokenie | Na poziomie chunków | Chatterbox |
| Przerwy w odtwarzaniu | Brak | Brak (bufor 7s) | Remis |
| Jakość głosu | Dobra | Doskonała | OmniVoice |
| Klonowanie głosu | Warunkowanie embeddingami | Audio ref. + tekst | OmniVoice |
| Języki | Polski + ograniczone | 600+ | OmniVoice |
| Zużycie VRAM | 4–6 GB | 5.6 GB | Remis |
| Równoległych użytkowników | 3–4 z pulą slotów | 3–5 na jednym GPU | Remis |
Chatterbox vs OmniVoice – odsłuch (głos weronika)
Ten sam tekst, ten sam głos (weronika), ten sam GPU. Chatterbox wygenerowany przez serwer produkcyjny. OmniVoice przy 16 krokach (rekomendowane) i 32 krokach (najlepsza jakość).
Mini – “Dzień dobry.”
Chatterbox
OmniVoice 16 kroków
Krótki – zdanie informacyjne (66 znaków)
Chatterbox
OmniVoice 16 kroków
Średni – incydent PLL LOT (196 znaków)
Chatterbox
OmniVoice 16 kroków
Chatterbox (ten sam)
OmniVoice 32 kroki
Długi – pełna wiadomość (488 znaków)
Chatterbox
OmniVoice 16 kroków
Chatterbox (ten sam)
OmniVoice 32 kroki
Porównania wewnętrzne OmniVoice
Kompromisy między liczbą kroków a chunkingiem.
32 vs 16 kroków (tekst średni)
32 kroki (referencyjna jakość)
16 kroków (rekomendowane)
Bazowy vs Chunkowany (tekst średni, 16 kroków)
Bazowy (pojedyncze generowanie)
Chunkowany (2 chunki, symulacja streamingu)
Dolna granica jakości – 8 kroków (tekst średni)
32 kroki (najlepsza jakość)
8 kroków (najszybsze, 87ms TTFA)
Zoptymalizowany streaming vs Bazowy (tekst długi)
Bazowy 16 kroków (single shot)
Zoptymalizowany 16 kroków (chunked stream)
Paralingwistyka: tagi dźwięków niewerbalnych
OmniVoice obsługuje ekspresyjne tagi niewerbalne osadzone bezpośrednio w tekście. Wszystkie próbki: polski, głos klonowany (weronika), 16 kroków.
Obsługiwane tagi: [laughter], [sigh], [confirmation-en], [question-ah], [question-oh], [question-ei], [question-yi], [surprise-ah], [surprise-oh], [surprise-wa], [surprise-yo], [dissatisfaction-hnn]
| Tag | Tekst | Gen. | Audio |
|---|---|---|---|
[laughter] | "...to się stało [laughter] naprawdę nie mogę." | 156ms | 3.91s |
[sigh] | "No cóż [sigh] trzeba było to przewidzieć." | 150ms | 2.41s |
[confirmation-en] | "[confirmation-en] tak, dokładnie o to mi chodziło." | 152ms | 2.77s |
[question-ah] | "Naprawdę tak uważasz [question-ah] bo ja mam wątpliwości." | 153ms | 3.68s |
[question-oh] | "[question-oh] a to ciekawe, kiedy to się stało?" | 151ms | 2.74s |
[question-ei] | "Mówisz poważnie [question-ei] nie żartujesz?" | 147ms | 2.71s |
[surprise-ah] | "[surprise-ah] nie spodziewałam się tego!" | 146ms | 2.61s |
[surprise-oh] | "[surprise-oh] to niesamowite co się wydarzyło." | 151ms | 2.76s |
[surprise-wa] | "[surprise-wa] ale rewelacja, nie do wiary!" | 150ms | 2.30s |
[surprise-yo] | "Wygraliśmy konkurs [surprise-yo] fantastycznie!" | 148ms | 3.08s |
[dissatisfaction-hnn] | "[dissatisfaction-hnn] no nie wiem, to mnie nie przekonuje." | 155ms | 3.38s |
| Mix (4 tagi) | "...co się stało [question-ah] ...wygrali [surprise-oh] ...stracili [sigh] ...[dissatisfaction-hnn] trzeba było..." | 247ms | 10.44s |
| Bez tagów (kontrolna) | "Nie mogę uwierzyć, że to się stało, naprawdę nie mogę." | 153ms | 3.40s |
[laughter] naprawdę nie mogę."[sigh] trzeba było to przewidzieć."[confirmation-en] tak, dokładnie o to mi chodziło."[dissatisfaction-hnn] no nie wiem, to mnie nie przekonuje."[question-ah] bo ja mam wątpliwości."[question-oh] a to ciekawe, kiedy to się stało?"[question-ei] nie żartujesz?"[surprise-ah] nie spodziewałam się tego!"[surprise-oh] to niesamowite co się wydarzyło."[surprise-wa] ale rewelacja, nie do wiary!"[surprise-yo] fantastycznie!"[question-ah] okazuje się że wygrali [surprise-oh] a potem wszystko stracili [sigh] no i co tu dużo mówić [dissatisfaction-hnn] trzeba było lepiej planować."Wszystkie tagi generują wyraźne dźwięki niewerbalne w oznaczonych miejscach. Próbka mieszana (4 tagi, 10.44s) demonstruje naturalny przepływ między mową a emocjami. Czas generowania pozostaje stały (~150ms) niezależnie od liczby tagów; próbka mieszana jest dłuższa (247ms) tylko dlatego, że sam tekst jest dłuższy.
Wnioski
OmniVoice jest gotowy do użycia w streamingu TTS w czasie rzeczywistym i przewyższa Chatterbox pod względem surowych metryk szybkości. Architektura dyfuzji z maskowaniem uniemożliwia prawdziwy streaming na poziomie tokenów, ale chunking na poziomie zdań osiąga TTFA 169ms przy 16 krokach z zerowymi przerwami w odtwarzaniu. W połączeniu z doskonałą jakością głosu, obsługą 600+ języków i niskim zużyciem VRAM, OmniVoice jest mocnym kandydatem do produkcyjnego wdrożenia TTS.
W sprawie konsultacji dotyczących integracji TTS w czasie rzeczywistym, architektury streamingu lub inżynierii AI/ML, skontaktuj się z Folx.