Ditado em streaming
Parakeet-EOU-120M e um modelo pequeno de ASR em streaming RNN-T com uma cabeca explicita de end-of-utterance (EOU), construido para ditado em tempo real no Neural Engine do Apple Silicon. Este guia tambem cobre o DictateDemo, o app de referencia para barra de menus do macOS que conecta o modelo de streaming ao Silero VAD para ditado maos-livres que cola em qualquer lugar.
O que e
- Parciais ao vivo — o texto atualiza conforme voce fala, ~340 ms apos cada chunk
- EOU explicito — o modelo decide quando um enunciado termina, sem botao manual
- Force-finalize guiado por VAD — o backstop Silero confirma enunciados mesmo quando o EOU fica preso em ruido de fundo
- 120 MB CoreML INT8 — roda no Neural Engine, deixando a GPU livre para outros modelos
- 25 idiomas europeus — mesma familia de vocabulario do NeMo Parakeet TDT upstream
Arquitetura
Tres modelos CoreML em pipeline por chunk de audio:
| Componente | Descricao |
|---|---|
| Codificador | Conformer ciente de cache. Recebe um chunk mel de 64 frames (640 ms) mais seis tensores de estado — KV cache de atencao, cache de conv depthwise e um pre_cache mel loopback que prepende o audio recente para que o FFT veja sinal continuo atraves dos limites do chunk. |
| Decodificador | Rede de predicao LSTM de passo unico. Consome o token nao-blank anterior, emite um embedding mais estado (h, c) atualizado. |
| Joint + cabeca EOU | Funde saidas do codificador e decodificador em logits sobre vocab + blank + EOU. A classe EOU e o sinal duro do modelo de que um enunciado terminou. |
Por que um token EOU separado
RNNT puro emite blanks durante silencio, que o decodificador absorve sem sinalizar "enunciado terminado". Uma cabeca EOU dedicada permite ao modelo fazer um corte duro para confirmar o parcial como final, resetar o estado de pontuacao/capitalizacao e disparar acoes posteriores como colar no app.
Cliques de teclado, movimento do mouse e ruido ambiente durante uma pausa "silenciosa" podem fazer o joint ocasionalmente emitir um token nao-blank, resetando o timer de debounce do EOU e travando o commit. Pipelines de producao combinam o EOU do joint com um backstop externo forceEndOfUtterance() guiado por VAD — veja DictateDemo abaixo.
Modelo
| Modelo | Tamanho | HuggingFace |
|---|---|---|
| Parakeet-EOU-120M (CoreML INT8) | ~120 MB | aufklarer/Parakeet-EOU-120M-CoreML-INT8 |
Desempenho
| Metrica | Valor |
|---|---|
| Memoria de pesos | ~120 MB (INT8) |
| Memoria de inferencia de pico | ~200 MB |
| Latencia por chunk (serie M) | ~30 ms de computacao / 640 ms de audio (RTF ~0.056) |
| Latencia de parcial end-to-end | ~340 ms (um chunk) |
| Latencia de commit (caminho VAD) | ~1 s apos a fala parar |
| Alvo de computacao | Neural Engine (CoreML) |
Inicio rapido — transcricao em batch
O modelo de streaming tambem conforma a SpeechRecognitionModel, entao funciona como um drop-in para qualquer codigo que aceite um modelo STT generico:
import ParakeetStreamingASR
let model = try await ParakeetStreamingASRModel.fromPretrained()
let text = try model.transcribeAudio(audioSamples, sampleRate: 16000)
Inicio rapido — streaming async
for await partial in model.transcribeStream(audio: samples, sampleRate: 16000) {
if partial.isFinal { print("FINAL: \(partial.text)") }
else { print("... \(partial.text)") }
}
Cada PartialTranscript carrega text, isFinal, confidence, eouDetected (joint disparou vs force-finalize) e um segmentIndex monotonico.
API de sessao de longa duracao (entrada de mic)
Para ditado ao vivo, crie uma sessao uma vez e alimente-a com chunks conforme chegam do microfone. A sessao mantem buffer interno e roda o codificador quando amostras suficientes acumulam, entao voce pode enviar tamanhos de chunk arbitrarios:
let session = try model.createSession()
// each mic chunk:
let partials = try session.pushAudio(float32Chunk16kHz)
for p in partials {
if p.isFinal { commit(p.text) }
else { showPartial(p.text) }
}
// when the stream ends:
let trailing = try session.finalize()
Padrao de force-finalize via VAD
Quando um Silero VAD ja esta rodando no seu pipeline, use-o para guiar um commit de fallback para que ruido de fundo nao trave o timer de debounce do EOU:
if hasPendingUtterance && !vadSpeechActive && vadSilentChunks >= 30 {
// ~960 ms of sustained silence per Silero
if let forced = session.forceEndOfUtterance() {
commit(forced.text)
}
hasPendingUtterance = false
}
// guardrail: don't double-commit if joint already fired EOU
if partials.contains(where: { $0.isFinal }) {
hasPendingUtterance = false
}
DictateDemo — app de referencia na barra de menus do macOS
DictateDemo e um agent completo de barra de menus do macOS construido sobre a sessao de streaming. Roda como um app em segundo plano, transcreve do microfone com parciais ao vivo, confirma automaticamente enunciados em EOU ou silencio VAD e cola os resultados no app mais a frente.
- App de barra de menus com hotkey global
Cmd+Shift+D - Parciais ao vivo com HUD flutuante e indicador de nivel de audio
- Force-finalize protegido por VAD (o padrao de producao acima)
- Colar no app mais a frente com
Cmd+Shift+V - O modelo e baixado automaticamente no primeiro lancamento (~120 MB)
cd Examples/DictateDemo
swift build
.build/debug/DictateDemo
A implementacao completa vive em Examples/DictateDemo/DictateDemo/DictateViewModel.swift: um sink de audio off-main com um buffer protegido por lock, um tick de timer de 300 ms que o drena, Silero VAD com carry-over de amostras restantes e um force-finalize protegido. Os testes de regressao correspondentes em Examples/DictateDemo/Tests/DictateDemoTests.swift cobrem cenarios de multi-enunciado, EOU travado e silencio ruidoso.
Streaming vs Parakeet em batch
| Parakeet-EOU-120M (streaming) | Parakeet TDT 0.6B (batch) | |
|---|---|---|
| Caso de uso | Ditado ao vivo, legendas em tempo real | Transcricao de arquivo, jobs offline |
| Decodificador | RNN-T + cabeca EOU | Token-and-Duration Transducer |
| Tamanho do chunk | Streaming de 640 ms | Batch de arquivo completo |
| Memoria de pesos | ~120 MB | 500 MB |
| Throughput | ~18x tempo real | ~32x tempo real |
| Latencia | Parciais de ~340 ms | Somente no fim do arquivo |
…voce precisa de parciais antes do usuario terminar de falar. Para transcricao em batch de arquivos de audio, o Parakeet TDT 0.6B maior e mais rapido end-to-end e mais preciso. Os dois modelos compartilham o mesmo vocabulario SentencePiece, entao voce pode alternar entre eles sem mudar a tokenizacao.