Phase 06 - Lesson 05
Whisper — Arquitetura e Fine-Tuning
O Whisper é um encoder-decoder transformer com janela de 30 segundos, treinado em 680 mil horas de pares áudio-texto multilíngues com supervisão fraca. Uma única arquitetura, múltiplas tarefas, robusta em 99 idiomas. O ASR de referência em 2026.
Tipo: Build Linguagens: Python Pré-requisitos: Fase 6 · 04 (ASR), Fase 5 · 10 (Atenção), Fase 7 · 05 (Transformer Completo) Tempo: ~75 minutos
O Problema
O Whisper, lançado pela OpenAI em setembro de 2022, foi o primeiro modelo de ASR a chegar como commodity: cole o áudio, receba o texto, 99 idiomas, robusto a ruído, rodando em um laptop. Em 2024 a OpenAI já tinha lançado as variantes Large-v3 e Turbo; em 2026, o Whisper é o baseline padrão para tudo, da transcrição de podcasts a assistentes de voz e legendas do YouTube.
Mas o Whisper não é um pipeline que você possa tratar como caixa-preta para sempre. O domain shift o derruba — jargão técnico, sotaques de falantes, nomes próprios, clipes curtos, silêncio. Você precisa saber:
- O que ele realmente é por dentro.
- Como entregar a ele áudio em chunks, em streaming ou de formato longo da maneira correta.
- Quando fazer fine-tune e como.
O Conceito
Arquitetura. Encoder-decoder transformer padrão.
- Entrada: espectrograma log-mel de 30 segundos, 80 mels, hop de 10 ms → 3000 frames. Clipes mais curtos recebem zero-padding, clipes mais longos são divididos em chunks.
- Encoder: conv-downsample (stride 2) +
Nblocos transformer. Para o Large-v3: 32 camadas, 1280 dimensões, 20 cabeças. - Decoder:
Nblocos transformer com self-attn causal + cross-attn para a saída do encoder. Mesmo tamanho do encoder. - Saída: tokens BPE sobre um vocabulário de 51.865 tokens.
O Large-v3 tem 1,55 bilhão de parâmetros. O Turbo usa um decoder de 4 camadas (em vez de 32), reduzindo a latência em 8× com uma perda de WER inferior a 1%.
O formato do prompt. O Whisper é um modelo multitarefa guiado por tokens especiais no prompt do decoder:
<|startoftranscript|><|en|><|transcribe|><|notimestamps|> Hello world.<|endoftext|>
<|en|>— tag de idioma; força o comportamento de tradução vs. transcrição.<|transcribe|>ou<|translate|>— traduzir a saída para inglês a partir de uma entrada em qualquer idioma, ou transcrever literalmente.<|notimestamps|>— pular timestamps em nível de palavra (mais rápido).
O prompt é o que permite a um único modelo realizar muitas tarefas. Troque <|en|> por <|fr|> e ele transcreve francês.
Janela de 30 segundos. Tudo está fixado em 30 segundos. Clipes mais longos precisam de chunking; clipes mais curtos recebem padding. As janelas não são processadas em streaming nativamente — é por isso que existem WhisperX, Whisper-Streaming e faster-whisper.
Normalização log-mel. (log_mel - mean) / std, onde as estatísticas vêm do próprio corpus de treinamento do Whisper. Você precisa usar o pré-processamento do Whisper (whisper.audio.log_mel_spectrogram), não o librosa.feature.melspectrogram.
Variantes em 2026
| Variante | Parâmetros | Latência (A100) | WER (LibriSpeech-clean) |
|---|---|---|---|
| Tiny | 39M | 1× tempo real | 5,4% |
| Base | 74M | 1× | 4,1% |
| Small | 244M | 1× | 3,0% |
| Medium | 769M | 1× | 2,7% |
| Large-v3 | 1,55B | 2× | 1,8% |
| Large-v3-turbo | 809M | 8× | 1,58% |
| Whisper-Streaming (2024) | 1,55B | streaming | 2,0% |
Fine-tuning
Fluxo de trabalho canônico em 2026:
- Colete de 10 a 100 horas de áudio do domínio-alvo com transcrições alinhadas.
- Execute o
transformers.Seq2SeqTrainercom o callbackgenerate_with_loss. - Eficiente em parâmetros: LoRA em
q_proj,k_proj,v_projdas camadas de atenção reduz a memória de GPU em 4× com custo de WER inferior a 0,3. - Congele o encoder se você tiver menos de 10 horas. Ajuste apenas o decoder.
- Use o próprio tokenizer e formato de prompt do Whisper; nunca troque o tokenizer.
Resultados da comunidade: fazer fine-tune do Medium em 20 horas de ditado médico reduz o WER de 12% para 4,5% em vocabulário médico. Fazer fine-tune do Turbo em 4 horas de islandês reduz o WER de 18% para 6%.
Construa
Passo 1: rode o Whisper sem ajustes
import whisper
model = whisper.load_model("large-v3-turbo")
result = model.transcribe(
"clip.wav",
language="en",
task="transcribe",
temperature=0.0,
condition_on_previous_text=False, # prevents runaway repetition
)
print(result["text"])
for seg in result["segments"]:
print(f"[{seg['start']:.2f}–{seg['end']:.2f}] {seg['text']}")
Padrões importantes que você deve sempre sobrescrever: temperature=0.0 (a amostragem usa por padrão a cadeia de fallback 0.0 → 0.2 → 0.4 …), condition_on_previous_text=False (previne o problema de alucinação em cascata) e no_speech_threshold=0.6 (detecção de silêncio).
Passo 2: formato longo em chunks
# whisperx is the 2026 reference for long-form with word-level timestamps
import whisperx
model = whisperx.load_model("large-v3-turbo", device="cuda", compute_type="float16")
segments = model.transcribe("1hour.mp3", batch_size=16, chunk_size=30)
O WhisperX adiciona (1) gating por VAD Silero, (2) alinhamento em nível de palavra via wav2vec 2.0, (3) diarização via pyannote.audio. O cavalo de batalha de 2026 para transcrição em produção.
Passo 3: fine-tune com LoRA
from transformers import WhisperForConditionalGeneration, WhisperProcessor
from peft import LoraConfig, get_peft_model
model = WhisperForConditionalGeneration.from_pretrained("openai/whisper-large-v3-turbo")
lora = LoraConfig(
r=16, lora_alpha=32, target_modules=["q_proj", "v_proj"],
lora_dropout=0.1, bias="none", task_type="SEQ_2_SEQ_LM",
)
model = get_peft_model(model, lora)
# model.print_trainable_parameters() -> ~3M trainable / 809M total
Em seguida, o loop padrão do Trainer. Faça checkpoint a cada 1000 passos. Avalie com WER em um conjunto de validação separado.
Passo 4: inspecione o que cada camada aprende
# Grab cross-attention weights during decode to see what the decoder attends to.
with torch.inference_mode():
out = model.generate(
input_features=features,
return_dict_in_generate=True,
output_attentions=True,
)
# out.cross_attentions: layer × head × step × src_len
Visualize com um heatmap — você verá o alinhamento diagonal conforme os passos do decoder varrem os frames do encoder. Essa diagonal é a noção de timestamps de palavras do Whisper.
Use
A stack de 2026:
| Situação | Escolha |
|---|---|
| Inglês geral, offline | Large-v3-turbo via whisperx |
| Mobile / edge | Whisper-Tiny quantizado (int8) ou Moonshine |
| Formato longo multilíngue | Large-v3 via whisperx + diarização |
| Idioma de poucos recursos | Fine-tune do Medium ou Turbo com LoRA |
| Streaming (2 s de latência) | Whisper-Streaming ou Parakeet-TDT |
| Timestamps em nível de palavra | WhisperX (alinhamento forçado via wav2vec 2.0) |
O faster-whisper (backend CTranslate2) é o runtime de inferência CPU+GPU mais rápido em 2026 — 4× mais rápido que o original com saída idêntica.
Armadilhas que ainda aparecem em 2026
- Texto alucinado no silêncio. O Whisper foi treinado em legendas que incluem "Thanks for watching!", "Subscribe!", letras de música. Sempre aplique gating por VAD antes de chamar.
- Cascata de
condition_on_previous_text. Uma alucinação polui as janelas subsequentes. Defina comoFalsea menos que você precise de fluência entre os chunks. - Padding de clipe curto. Um clipe de 2 segundos preenchido até 30 segundos pode alucinar no silêncio final. Use
pad=Falseou gating por VAD. - Estatísticas de mel erradas. Usar os mels do librosa em vez dos do Whisper produz saída quase aleatória. Use
whisper.audio.log_mel_spectrogram.
Entregue
Salve como outputs/skill-whisper-tuner.md. Projete um pipeline de fine-tune ou de inferência do Whisper para um domínio específico.
Exercícios
- Fácil. Execute
code/main.py. Ele tokeniza um prompt no estilo Whisper, calcula os orçamentos de shape decodificado e imprime o cronograma de chunks para um clipe de 10 minutos. - Médio. Instale o
faster-whisper, transcreva um podcast de 10 minutos e compare o WER com uma transcrição humana. Testelanguage="auto"vs.language="en"forçado. - Difícil. Usando
datasetsdo HF, escolha um idioma em que o Whisper tem dificuldade (por exemplo, urdu), faça fine-tune do Medium com LoRA por 2 epochs em 2 horas e reporte o delta de WER.
Termos-Chave
| Termo | O que as pessoas dizem | O que realmente significa |
|---|---|---|
| Janela de 30 s | O limite do Whisper | Teto rígido de entrada; divida áudios mais longos em chunks. |
| SOT | Start-of-transcript | `< |
| Token de timestamps | Alinhamento temporal | Cada offset de 0,02 s é um token especial no vocabulário de 51k. |
| Turbo | A variante rápida | Decoder de 4 camadas, 8× mais rápido, regressão de WER <1%. |
| WhisperX | O wrapper para formato longo | VAD + Whisper + alinhamento wav2vec + diarização. |
| Fine-tune com LoRA | Ajuste eficiente | Adiciona adaptadores de baixo posto à atenção; treina ~0,3% dos parâmetros. |
| Alucinação | A falha silenciosa | O Whisper produz inglês fluente a partir de ruído/silêncio. |
Leitura Complementar
- Radford et al. (2022). Artigo do Whisper — a arquitetura original e a receita de treinamento.
- OpenAI (2024). Lançamento do Whisper Large-v3-turbo — decoder de 4 camadas, 8× mais rápido.
- Bain et al. (2023). WhisperX — formato longo, alinhado por palavra, diarizado.
- Systran — repositório do faster-whisper — backend CTranslate2, 4× mais rápido.
- HuggingFace — tutorial de fine-tune do Whisper — passo a passo canônico de LoRA / full-FT.