Qwen3-TTS
Qwen3-TTS e um modelo de linguagem codec de 12Hz com decodificador Mimi para sintese de texto para fala de alta qualidade. O caminho MLX padrao agora usa o pacote 1.7B Base bf16; pacotes 8-bit continuam disponiveis para downloads menores. int4 foi descontinuado por qualidade de TTS.
Pipeline
A sintese de fala segue um pipeline em tres etapas:
- Talker — transformer de 28 camadas que converte texto de entrada em tokens do primeiro codebook a 12.5 Hz
- Code Predictor — transformer de 5 camadas que preve os 15 codebooks restantes a partir dos hidden states do primeiro codebook
- Decodificador Mimi Codec — converte todos os 16 tokens de codebook em uma forma de onda de audio a 24 kHz
Arquitetura
Talker
O Talker e o modelo autoregressivo central que gera tokens de codec a partir da entrada de texto.
| Parametro | Valor |
|---|---|
| Camadas | 28 |
| Dimensao oculta | 1024 |
| Cabecas de query | 16 |
| Cabecas de key/value | 8 (GQA) |
| MLP | SwiGLU |
| Codificacao de posicao | RoPE |
Code Predictor
Um transformer leve de 5 camadas que recebe os hidden states do primeiro codebook e preve os 15 codebooks restantes em paralelo. Isso evita executar o Talker completo 16 vezes por passo.
Decodificador Mimi Codec
O decodificador Mimi converte tokens de codec quantizados de volta em audio:
- Decodificacao RVQ (16 codebooks)
- Pre-convolucao (512 para 1024 canais)
- Pre-transformer (gargalo 1024 para 512, 8 camadas, SwiGLU + LayerScale)
- Upsample (2x, 2x)
- Decodificador SEANet (estagios de upsample 8x, 5x, 4x, 3x)
- Saida de forma de onda a 24 kHz
Variantes do modelo
| Modelo | Tamanho | HuggingFace |
|---|---|---|
| Qwen3-TTS-0.6B Base (8-bit) | 1.3 GB | aufklarer/Qwen3-TTS-12Hz-0.6B-Base-MLX-8bit |
| Qwen3-TTS-1.7B Base (8-bit) | 2.4 GB | aufklarer/Qwen3-TTS-12Hz-1.7B-Base-MLX-8bit |
| Qwen3-TTS-1.7B Base (bf16, default) | 3.9 GB | aufklarer/Qwen3-TTS-12Hz-1.7B-Base-MLX-bf16 |
| Qwen3-TTS-0.6B CustomVoice (bf16) | 1.8 GB | aufklarer/Qwen3-TTS-12Hz-0.6B-CustomVoice-MLX-bf16 |
| Qwen3-TTS CoreML (FP16) | 2.1 GB | aufklarer/Qwen3-TTS-CoreML |
Backend CoreML
CoreML executa seis componentes compilados. O dispositivo de cálculo depende do pacote selecionado.
- TextProjector — projeta embeddings de tokens de texto para o espaco oculto compartilhado
- CodeEmbedder — incorpora tokens do primeiro codebook e tokens de controle
- MultiCodeEmbedder — incorpora tokens dos codebooks 1–15
- CodeDecoder — transformer autoregressivo de 28 camadas com cache KV sem estado (maximo de 256 posicoes)
- MultiCodeDecoder — code predictor de 5 camadas para os codebooks 1–15
- SpeechDecoder — decodificador Mimi codec, converte 16 tokens de codebook em audio a 24 kHz
# CoreML synthesis
.build/release/speech speak "Hello, world!" --engine coreml -o hello.wav
# CoreML uses temperature 0.8 by default (required for quality output)
.build/release/speech speak "Long text here." --engine coreml --temperature 0.9 -o out.wav
0.6B: O CodeDecoder CoreML usa um cache KV fixo de 256 posicoes. Passagens mais longas devem ser divididas em frases individuais. Os tokens de decodificacao sao automaticamente limitados para caber nos slots de cache restantes apos o prefill.
Exportação experimental de 1.7B para CoreML
O decodificador usa cálculos FP32 porque FP16 falhou na validação do modelo; os tensores do cache continuam em FP16.
O conversor de seis componentes suporta 1.7B Base e um CodeDecoder com estado de 1024 posições. O talker e a representação do locutor têm 2048 dimensões; o preditor de códigos de 1024 dimensões inclui a projeção de entrada treinada.
Swift suporta os pacotes 0.6B/256 e 1.7B/1024; 0.6B continua a ser o padrão. O pacote experimental 1.7B usa CPU por padrão e requer uma representação do locutor Float32 .npy com 2048 canais, preparada e fornecida através de --speaker-embedding. GPU/ANE e iOS exigem validação separada.
O cache inclui posições do texto de entrada e do áudio. SpeechDecoder tem um limite padrão separado de 125 quadros (10 segundos); aumentar o cache de CodeDecoder não amplia esse limite.
Código de conversão e guia de validação
speech qwen3-tts-coreml "Hello world" \
--model aufklarer/Qwen3-TTS-1.7B-CoreML \
--speaker-embedding speaker-17b.npy --output hello-17b.wav
Uso do CLI
Gere fala a partir de texto:
.build/release/speech speak "Hello, world!" --output hello.wav
Opcoes
| Flag | Descricao |
|---|---|
--engine | Engine TTS: qwen3 (MLX, padrao), coreml (CoreML/GPU) ou cosyvoice |
--output, -o | Caminho do arquivo WAV de saida |
--language | Idioma (padrao: english). Omita para usar o dialeto nativo do locutor. |
--model | Variante do modelo: base ou customVoice |
--speaker | Voz do locutor (requer --model customVoice) |
--temperature | Temperatura de amostragem (padrao: 0.3) |
--top-k | Parametro de amostragem top-k |
--max-tokens | Numero maximo de tokens a gerar (padrao: 500) |
--stream | Habilita streaming — emite chunks de audio durante a geracao |
--first-chunk-frames | Numero de frames no primeiro chunk transmitido |
--chunk-frames | Numero de frames por chunk subsequente |
--batch-file | Caminho para um arquivo de texto com um enunciado por linha para sintese em lote |
--batch-size | Numero de enunciados paralelos no modo batch |
Exemplos
# Basic synthesis
.build/release/speech speak "The quick brown fox." -o fox.wav
# Streaming output
.build/release/speech speak "Long passage of text..." --stream -o stream.wav
# Batch synthesis from file
.build/release/speech speak --batch-file sentences.txt --batch-size 4 -o output_dir/
Streaming
A flag --stream habilita saida de audio em chunks durante a geracao. Em vez de aguardar a conclusao do enunciado inteiro, o audio e emitido em chunks conforme os tokens sao produzidos. Use --first-chunk-frames e --chunk-frames para controlar o tamanho de cada chunk.
Modo batch
Para sintetizar varios enunciados, use --batch-file com um arquivo de texto contendo uma linha por enunciado. A flag --batch-size controla quantos enunciados sao processados em paralelo.
Desempenho
Em um M2 Max, o Qwen3-TTS alcanca um RTF (fator de tempo real) de aproximadamente 0.55, ou seja, gera fala mais rapido que tempo real. Com aquecimento via compile(), cada passo leva cerca de 37 ms.
O maximo padrao e de 500 tokens, o que produz aproximadamente 40 segundos de audio a 12.5 Hz. Definir valores mais altos arrisca exceder o watchdog da GPU Metal, o que pode causar uma reinicializacao do sistema em Apple Silicon, ja que a GPU e compartilhada com o compositor.
Idiomas
Qwen3-TTS suporta sintese de texto para fala multilingue. O modelo detecta automaticamente o idioma de entrada e gera fala adequadamente.
API Swift
import Qwen3TTS
import AudioCommon
let model = try await Qwen3TTSModel.fromPretrained()
let audio = model.synthesize(text: "Hello, world!", language: "english")
try WAVWriter.write(samples: audio, sampleRate: 24000, to: URL(filePath: "hello.wav"))
Bundles apenas locais
Use fromLocal quando o app controlar a aquisição e o armazenamento do modelo. Informe separadamente os diretórios do modelo TTS principal e do tokenizador de fala. A chamada não resolve cache nem acessa a rede e lê o config.json do bundle principal antes de alocar módulos MLX.
let model = try Qwen3TTSModel.fromLocal(
modelDirectory: ttsDirectory,
tokenizerDirectory: speechTokenizerDirectory
)
fromLocal usa .none por padrão e não altera o limite de memória wired do Metal para o processo. fromPretrained mantém .pin(fraction: 0.9). Os dois loaders pretreinados aceitam um tokenizerCacheDir separado.
Diagnóstico
O Qwen3-TTS envia os diagnósticos de carregamento do modelo e inferência para AudioLog.modelLoading e AudioLog.inference, em vez de stdout ou stderr. Contagens, formas e tempos permanecem visíveis; os valores de idioma e locutor fornecidos pelo chamador ficam privados e o texto de entrada nunca é registrado.