VibeVoice
Microsoft VibeVoice es un modelo de síntesis de voz de formato largo y múltiples hablantes para inglés y chino. A diferencia del TTS de enunciados cortos, está diseñado para generar diálogos de duración de podcast, narración de audiolibros y escenas multi-hablante en una sola pasada — hasta 90 minutos con hasta 4 voces distintas y una identidad consistente en toda la salida. Se distribuyen dos variantes: Realtime-0.5B para streaming de baja latencia y 1.5B para calidad insignia de formato largo.
Qué es
- Formato largo en una pasada — hasta 90 minutos de audio con voces consistentes en toda la salida; sin entregas por frase
- Diálogo multi-hablante — 4 hablantes distintos a la vez, cada uno condicionado por su propio voice cache
- Inglés + chino — los datos de entrenamiento de audio son solo EN/ZH; otros idiomas no son compatibles (el tokenizador los acepta pero la salida es ininteligible)
- Salida mono a 24 kHz — PCM Float32, listo para
AudioCommon.WAVWriteryStreamingAudioPlayer - Licencia MIT — los pesos del modelo y nuestro port a Swift son MIT; se permiten derivados cuantizados a INT4
Arquitectura
Cuatro componentes colaboran para producir audio un latente de 7.5 Hz a la vez:
| Componente | Descripción |
|---|---|
| Split Qwen2 backbone | 24-layer Qwen2.5 decoder (896 hidden, GQA 14/2 for Realtime-0.5B). The model is split: the lower 4 layers form a text LM, the upper 20 layers run as the TTS LM. Text windows (5 tokens at a time) flow through both; generated speech latents flow only through the TTS LM. |
| σ-VAE acoustic tokenizer | Streaming conv stack that encodes 24 kHz audio to a 64-dim latent at 7.5 Hz (3200× temporal downsample) and decodes latents back to waveform. Used for both voice-cache creation and final audio decode. |
| Diffusion head | Small 4-layer DDPM head with adaLN modulation. Samples each speech latent via 20-step DPM-Solver with classifier-free guidance (cfg = 1.3 default for Realtime-0.5B, 1.5 for 1.5B). |
| EOS classifier | Per-step binary classifier on the TTS LM's last hidden state. When sigmoid probability exceeds 0.5, generation stops. |
Clonación de voz mediante voice-cache
La identidad del hablante no proviene de una forma de onda de referencia en el momento de la generación. En su lugar, cada voz se distribuye como un voice cache precalculado en .safetensors que contiene las cachés KV de condicionamiento y los estados ocultos para un hablante específico, producidos al ejecutar el audio de referencia por la ruta del codificador de forma offline. Cargar un voice cache es instantáneo en tiempo de ejecución; una instancia del modelo puede cambiar de voz a bajo coste entre generaciones.
Voice caches de ejemplo (licencia MIT): mzbac/vibevoice.swift/voice_cache — 7 voces en inglés que incluyen Carter, Davis, Emma, Frank, Grace, Mike y Samuel con acento indio.
Modelo
| Bundle | Cuantización | Tamaño | HuggingFace |
|---|---|---|---|
| Realtime-0.5B | BF16 (source) | ~1 GB | microsoft/VibeVoice-Realtime-0.5B |
| Realtime-0.5B INT4 | Qwen2 INT4, tokenizer + diffusion FP16 | ~350 MB | aufklarer/VibeVoice-Realtime-0.5B-MLX-INT4 |
| Realtime-0.5B INT8 | Qwen2 INT8 | ~570 MB | aufklarer/VibeVoice-Realtime-0.5B-MLX-INT8 |
| 1.5B long-form | BF16 (source) | ~3 GB | microsoft/VibeVoice-1.5B |
| 1.5B INT4 | Qwen2 INT4 | ~1 GB | aufklarer/VibeVoice-1.5B-MLX-INT4 |
La cuantización la produce models/vibevoice/export/convert.py usando cuantización afín por grupos de MLX (grupo 32). Los embeddings, normalizaciones, convoluciones del acoustic-tokenizer y el clasificador EOS conservan su dtype original.
Inicio rápido
import VibeVoiceTTS
let tts = try await VibeVoiceTTSModel.fromPretrained()
try tts.loadVoice(from: "/path/to/voice_cache/en-Mike_man.safetensors")
let pcm = try await tts.generate(text: "Hello world.")
// pcm: [Float] at 24 kHz mono
Preset 1.5B de formato largo
let config = VibeVoiceTTSModel.Configuration.longForm1_5B
let tts = try await VibeVoiceTTSModel.fromPretrained(configuration: config)
try tts.loadVoice(from: "voices/narrator.safetensors")
let pcm = try await tts.generate(text: longTranscript) // up to ~90 min
El preset longForm1_5B sube maxSpeechTokens a 4000 y cfgScale a 1.5 para una salida de formato largo de mayor fidelidad.
Intercambiar voces entre generaciones
try tts.loadVoice(from: "en-Mike_man.safetensors")
let a = try await tts.generate(text: "First speaker line.")
try tts.loadVoice(from: "en-Emma_woman.safetensors")
let b = try await tts.generate(text: "Second speaker line.")
CLI
audio vibevoice "Hello world." \
--voice-cache voice_cache/en-Mike_man.safetensors \
--output hello.wav
# Formato largo 1.5B
audio vibevoice "Long paragraph ..." \
--voice-cache voices/narrator.safetensors \
--long-form \
--max-tokens 4000 \
--output episode.wav
Flags: --steps (pasos del DPM-Solver), --cfg (guía), --model / --tokenizer para sobrescribir los IDs de HuggingFace, --long-form para cambiar al preset 1.5B, --verbose para tiempos.
Elegir entre los módulos TTS de speech-swift
| Kokoro-82M | Qwen3-TTS | CosyVoice3 | VibeVoice Realtime | VibeVoice 1.5B | |
|---|---|---|---|---|---|
| Parámetros | 82M | 7B | 7B | 500M | 1.5B |
| Backend | CoreML (ANE) | MLX | MLX | MLX | MLX |
| Idiomas | 8 | 10+ | 10+ | EN/ZH | EN/ZH |
| Clonación de voz | Presets fijos | Referencia ICL | Referencia zero-shot | Voice cache | Voice cache |
| Formato largo | Corto/medio | Streaming | Streaming | Streaming | Hasta 90 min / 4 hablantes |
…necesites salida de formato largo, multi-hablante o podcast/audiolibro en inglés o chino, con identidad vocal consistente a lo largo de minutos de audio. Para TTS multilingüe de formato corto, Qwen3-TTS o CosyVoice3 encajan mejor. Para enunciados cortos nativos en iOS, Kokoro es la opción más pequeña.