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

  1. Grave ou forneca uma amostra de audio de referencia da voz alvo
  2. Extracao do embedding de falante — um codificador de falante processa o audio de referencia em um vetor de embedding de dimensao fixa
  3. Injecao do embedding — o embedding de falante condiciona o modelo TTS durante a sintese
  4. 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:

EngineCodificador de falanteEmbeddingBackend
Qwen3-TTSECAPA-TDNNx-vector de 1024 dimMLX (GPU)
CosyVoice3CAM++192 dimCoreML (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++

EstagioDescricao
FCMModulo convolucional front-end (Conv2d + 2 ResBlocks, 32 canais)
TDNNTime Delay Neural Network (320 para 128 canais, kernel size 5)
Blocos D-TDNN3 blocos densamente conectados (12/24/16 camadas) com mascaramento context-aware
Stats PoolPooling de media + desvio padrao (estatisticas globais)
DenseProjecao 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

EstagioDescricao
TDNNTime Delay Neural Network (128 para 512 canais, kernel size 5)
Blocos SE-Res2Net3 blocos com Squeeze-and-Excitation (512 canais, dilation 2/3/4)
MFAMulti-layer Feature Aggregation (1536 canais + ReLU)
ASPAttentive Statistics Pooling (1536 canais, softmax sobre o tempo)
FCCamada 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

Importante

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
)