Clonagem de voz
Clone qualquer voz a partir de uma amostra curta de audio de referencia. Tanto Qwen3-TTS quanto CosyVoice3 suportam clonagem de voz com codificadores de falante diferentes — ECAPA-TDNN (1024 dim) e CAM++ (192 dim) respectivamente.
Como funciona
- Grave ou forneca uma amostra de audio de referencia da voz alvo
- Extracao do embedding de falante — um codificador de falante processa o audio de referencia em um vetor de embedding de dimensao fixa
- Injecao do embedding — o embedding de falante condiciona o modelo TTS durante a sintese
- Sintese de fala — o modelo TTS gera fala que corresponde as caracteristicas vocais da amostra de referencia
Engines
A clonagem de voz esta disponivel em ambos os engines TTS. Cada um usa um codificador de falante diferente:
| Engine | Codificador de falante | Embedding | Backend |
|---|---|---|---|
| Qwen3-TTS | ECAPA-TDNN | x-vector de 1024 dim | MLX (GPU) |
| CosyVoice3 | CAM++ | 192 dim | CoreML (Neural Engine) |
CosyVoice3 + CAM++
CosyVoice3 usa o codificador de falante CAM++ (Context-Aware Masking++) do projeto 3D-Speaker da Alibaba. O embedding de 192 dim condiciona o modelo de flow DiT via uma camada de projecao afim (192 → 80) que foi treinada em conjunto com o CosyVoice3.
Arquitetura CAM++
| Estagio | Descricao |
|---|---|
| FCM | Modulo convolucional front-end (Conv2d + 2 ResBlocks, 32 canais) |
| TDNN | Time Delay Neural Network (320 para 128 canais, kernel size 5) |
| Blocos D-TDNN | 3 blocos densamente conectados (12/24/16 camadas) com mascaramento context-aware |
| Stats Pool | Pooling de media + desvio padrao (estatisticas globais) |
| Dense | Projecao linear para embedding de 192 dim |
O modelo CoreML (~14 MB, FP16) roda no Neural Engine. E baixado automaticamente de aufklarer/CamPlusPlus-Speaker-CoreML no primeiro uso.
Clonagem de voz com Qwen3-TTS
Qwen3-TTS suporta dois modos de clonagem de voz:
Modo ICL (recomendado)
O modo In-Context Learning codifica o audio de referencia em tokens de codec via o codificador tokenizer de fala Mimi e os prepende com a transcricao de referencia. Isso da ao modelo contexto acustico completo — maior qualidade e EOS confiavel (corrige problemas com textos curtos e idiomas nao-ingles).
let (model, encoder) = try await Qwen3TTSModel.fromPretrainedWithEncoder()
let audio = model.synthesizeWithVoiceCloneICL(
text: "Target text to synthesize.",
referenceAudio: refSamples,
referenceSampleRate: 24000,
referenceText: "Exact transcript of reference audio.",
language: "english",
codecEncoder: encoder
)
Modo X-Vector
Usa um codificador ECAPA-TDNN que produz um x-vector de 1024 dim. Nao precisa de transcricao mas tem qualidade menor. Pode falhar em emitir EOS em textos curtos ou certos idiomas.
Arquitetura ECAPA-TDNN
| Estagio | Descricao |
|---|---|
| TDNN | Time Delay Neural Network (128 para 512 canais, kernel size 5) |
| Blocos SE-Res2Net | 3 blocos com Squeeze-and-Excitation (512 canais, dilation 2/3/4) |
| MFA | Multi-layer Feature Aggregation (1536 canais + ReLU) |
| ASP | Attentive Statistics Pooling (1536 canais, softmax sobre o tempo) |
| FC | Camada totalmente conectada (3072 para 1024 dimensoes) |
Os pesos (76 parametros) estao incluidos nos safetensors do Qwen3-TTS — nao e necessario um download separado.
Uso do CLI
# CosyVoice3 voice cloning (CAM++, CoreML Neural Engine)
.build/release/audio speak "Text in the cloned voice" \
--engine cosyvoice --voice-sample reference.wav -o output.wav
# Qwen3-TTS voice cloning (ECAPA-TDNN, MLX GPU)
.build/release/audio speak "Text in the cloned voice" \
--voice-sample reference.wav -o output.wav
Exemplos
# CosyVoice3: multilingual voice cloning (9 languages)
.build/release/audio speak "Hello, this is my cloned voice." \
--engine cosyvoice --voice-sample my_voice.wav -o cloned_hello.wav
# CosyVoice3: clone voice in a different language
.build/release/audio speak "Guten Tag, das ist meine geklonte Stimme." \
--engine cosyvoice --voice-sample my_voice.wav --language german -o german.wav
# Qwen3-TTS: English voice cloning
.build/release/audio speak "The quick brown fox jumps over the lazy dog." \
--voice-sample recording_15s.wav -o cloned_fox.wav
Dialogo multi-locutor
CosyVoice3 suporta dialogo multi-locutor com clonagem de voz por locutor. Use a flag --speakers para mapear tags de falante para arquivos de audio de referencia:
# Two-speaker dialogue with voice cloning
.build/release/audio speak "[S1] Hello there! [S2] Hey, how are you?" \
--engine cosyvoice --speakers s1=alice.wav,s2=bob.wav -o dialogue.wav
# Dialogue with emotion tags + voice cloning
.build/release/audio speak "[S1] (happy) Great news! [S2] (surprised) Really? Tell me more." \
--engine cosyvoice --speakers s1=alice.wav,s2=bob.wav -o emotional_dialogue.wav
# Adjust silence between turns
.build/release/audio speak "[S1] First line. [S2] Second line." \
--engine cosyvoice --speakers s1=a.wav,s2=b.wav --turn-gap 0.5 -o gapped.wav
O audio de referencia de cada falante e processado pelo codificador CAM++ para extrair um embedding de 192 dim. O modelo e carregado uma vez e reutilizado para todos os falantes. Veja o guia do CosyVoice3 para detalhes completos sobre a sintaxe de dialogo e tags de emocao.
Dicas para o audio de referencia
- Duracao: 5 a 15 segundos de fala funciona melhor. Clipes mais curtos podem nao capturar caracteristicas vocais suficientes; clipes mais longos fornecem retornos decrescentes.
- Locutor unico: A referencia deve conter apenas um falante. Audio multi-locutor produzira resultados imprevisiveis.
- Audio limpo: Minimize ruido de fundo, musica e reverberacao. Use o modulo de aprimoramento de fala para limpar referencias ruidosas antes da clonagem.
- Fala natural: Use fala conversacional e natural em vez de sussurros, gritos ou canto.
Para Qwen3-TTS, a clonagem de voz funciona apenas com o modelo base — nao com customVoice. A clonagem de voz do CosyVoice3 funciona com o modelo padrao.
API Swift
import CosyVoiceTTS
// CosyVoice3 voice cloning
let model = try await CosyVoiceTTSModel.fromPretrained()
let speaker = try await CamPlusPlusSpeaker.fromPretrained()
// Extract 192-dim speaker embedding from reference audio
let embedding = try speaker.embed(audio: refSamples, sampleRate: 16000)
// Synthesize with cloned voice
let audio = model.synthesize(
text: "Hello in a cloned voice!",
speakerEmbedding: embedding
)
// With custom instruction + speaker embedding
let styledAudio = model.synthesize(
text: "Hello!",
instruction: "Speak happily and with excitement.",
speakerEmbedding: embedding
)
// Multi-speaker dialogue
let segments = DialogueParser.parse("[S1] (happy) Hi! [S2] Hey there.")
let embeddings = ["S1": aliceEmbedding, "S2": bobEmbedding]
let dialogueAudio = DialogueSynthesizer.synthesize(
segments: segments,
speakerEmbeddings: embeddings,
model: model,
language: "english"
)
import Qwen3TTS
// Qwen3-TTS voice cloning
let model = try await Qwen3TTSModel.fromPretrained()
let audio = model.synthesizeWithVoiceClone(
text: "Hello in a cloned voice!",
referenceAudio: refSamples,
referenceSampleRate: 24000
)