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

Arquitetura

Tres modelos CoreML em pipeline por chunk de audio:

ComponenteDescricao
CodificadorConformer 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.
DecodificadorRede de predicao LSTM de passo unico. Consome o token nao-blank anterior, emite um embedding mais estado (h, c) atualizado.
Joint + cabeca EOUFunde 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.

EOU e ruidoso no mundo real

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

ModeloTamanhoHuggingFace
Parakeet-EOU-120M (CoreML INT8)~120 MBaufklarer/Parakeet-EOU-120M-CoreML-INT8

Desempenho

MetricaValor
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 computacaoNeural 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.

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 usoDitado ao vivo, legendas em tempo realTranscricao de arquivo, jobs offline
DecodificadorRNN-T + cabeca EOUToken-and-Duration Transducer
Tamanho do chunkStreaming de 640 msBatch de arquivo completo
Memoria de pesos~120 MB500 MB
Throughput~18x tempo real~32x tempo real
LatenciaParciais de ~340 msSomente no fim do arquivo
Escolha o modelo de streaming quando…

…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.