Passa al contenuto principale

Whistle: speech-to-text in 16,9 MB — e le barre del benchmark che nessuno ha etichettato

Intermedio
What you'll learn
  • Capire cosa c'è davvero dentro i 16,9 MB — e quale parte del titolo «9x più piccolo» è architettura e quale è una scelta di quantizzazione che il confronto non tiene costante
  • Leggere il grafico WER del vendor comprese le barre dei concorrenti che non etichetta mai: Whistle vince 5 confronti diretti su 8 e perde i tre che somigliano di più alla vita reale
  • Sapere perché 30 secondi sono un muro nell'encoder e non un'impostazione, e costruire la segmentazione VAD che ne consegue
  • Trovare l'API di streaming che la discussione di lancio ha concluso non esistere, e capire perché la sua latenza reale non è gli 11,1 ms al primo token
  • Usare il keyword biasing come leva principale di accuratezza, non come un optional — è la differenza tra il 41% e il 96% su un vocabolario chiuso
  • Scegliere tra Whistle, Whisper, Parakeet e un'API cloud per il tuo audio specifico

L'8 ottobre 2026 un post di blog intitolato "Whistle: Speech to Text in 16.9 MB" ha raggiunto 768 punti su Hacker News. Il numero nel titolo è tutto il pitch, ed è vero: l'intero modello di riconoscimento vocale multilingue è un singolo file da 16,9 MB che gira su una CPU, senza GPU e senza dipendenze.

La discussione che ne è seguita si è divisa nettamente in due. Chi ha letto il grafico dei benchmark è rimasto colpito. Chi ha puntato un microfono contro il modello no — un tester ha riportato 70 risposte corrette su 170 enunciati. Entrambi i gruppi avevano ragione, e il motivo è stampato nel grafico stesso del vendor. Sta solo nelle barre che non portano alcun numero.

La versione in una frase​

Whistle compra le sue dimensioni quantizzando a 2–4 bit un piccolo modello ASR encoder–decoder e limitando in banda il suo front end a 250–3500 Hz, il che gli costa quasi nulla sul parlato con microfono ravvicinato e un solo parlante — dove batte davvero Whisper base — e gli costa moltissimo sul parlato in campo lontano, sovrapposto o con accento, dove è il peggiore dei tre modelli del suo stesso confronto.

Cosa c'è davvero nei 16,9 MB​

ComponenteDettaglio
Front endfinestra da 25 ms, hop da 10 ms, 80 bin log-mel, limitato in banda a 250–3500 Hz
Stemconvoluzionale a 128 canali, sottocampiona a un frame ogni 80 ms
Encoder8 blocchi Simple Attention, MLP Monarch Hadamard
Decoder8 blocchi Simple Attention «a scala» (laddered), larghezza 512, 8 query head per 2 KV head
Vocabolario8.192 pezzi di testo più 7 token di lingua
Tetto di output320 token per clip
Tetto di input480.000 campioni — 30 s a 16 kHz mono
Contenitore.cact, Cactus Quants, 2–4 bit
LicenzaApache-2.0

Tre di queste righe lavorano più delle altre, e due sono quelle che la gente salta.

Il titolo «9x» sulle dimensioni non tiene costante la precisione​

Il confronto che tutti citano è 16,9 MB contro i 145,3 MB di Whisper base. Cioè un nono delle dimensioni — ma la nota a piè di pagina del vendor stesso dice che Whistle è misurato a 2–4 bit mentre Whisper è fp32 in memoria sulla CPU. Sono 8–16 volte di distanza in bit per peso prima ancora che venga presa una singola decisione architetturale.

La riga onesta, a parità di condizioni, nello stesso grafico è Moonshine tiny v2 a 41,9 MB in int8. Whistle è 2,5 volte più piccolo, non 9. Il 2,5x rimanente è reale ed è dove l'architettura si guadagna il pane — ma se ripeti il numero 9x stai ripetendo soprattutto una scelta di quantizzazione.

È la stessa trappola trattata in come leggere un benchmark di IA senza farsi ingannare: il numero non è sbagliato, è il confronto a non essere tenuto costante.

Limitare la banda a 3500 Hz è una decisione di design con una classe di errore prevedibile​

Il front end tiene 250–3500 Hz e butta via tutto il resto. È più o meno la banda telefonica, ed è una scelta sensata per un modello pensato per girare su un dispositivo indossabile — la maggior parte dell'energia vocale sta sotto.

La maggior parte, non tutta. La letteratura di fonetica acustica è precisa su questo: 3–4 kHz bastano per vocali intelligibili ma non per la maggior parte delle fricative sorde, i cui spettri sono concentrati sopra i 4 kHz. La s inglese ha la massima concentrazione di energia nell'intervallo 5–10 kHz circa, con picco vicino agli 8 kHz — più del doppio del taglio di Whistle — e la sh è centrata vicino ai 4 kHz con energia che si estende fino a 8.

Tagliare a 3500 Hz non rende quei suoni inudibili. Elimina la banda che li separa più nettamente l'uno dall'altro.

Quindi prima ancora di eseguire un singolo test puoi prevedere la classe di errore: confusioni e terminazioni di parola perse sulle fricative, peggiori sui parlanti il cui ritmo o accento dà a quelle consonanti meno durata con cui compensare. I resoconti dal campo nel thread di lancio — output in spagnolo con «parole inesistenti e terribili refusi», accenti messicani e venezuelani non riconosciuti, accenti marcati che degradano nettamente — sono quella previsione che si avvera puntuale.

Le barre del benchmark che nessuno ha etichettato​

Ecco la parte che vale la pagina. Il grafico di Whistle riporta il tasso di errore sulle parole su nove set di test per tre modelli. Stampa un numero su ogni barra di Whistle e su nessuna delle altre.

Le barre però ci sono, disegnate in scala lineare. Le etichette stampate di Whistle calibrano quella scala con esattezza — 6,867 pixel per punto di WER, coerente a ±0,01 su tutti e nove — quindi i valori dei concorrenti si ricavano dall'altezza delle barre. Farlo produce la tabella che il grafico si ferma un attimo prima di darti.

Set di testCos'èWhistleWhisper base ≈Moonshine tiny v2 ≈
LibriSpeech test-cleanAudiolibri letti, puliti4.314.894.51
LibriSpeech test-otherAudiolibri letti, più difficili10.4911.0011.71
SPGISpeechChiamate finanziarie7.65—7.70
Earnings-22Chiamate sugli utili, con accento19.01—21.25
AMIRiunioni, campo lontano, sovrapposizioni26.0721.5022.78
AMI cleanedIdem, riferimenti ripuliti22.87——
TED-LIUMConferenze7.614.995.64
FLEURSParlato letto multilingue21.3924.50—
MLSAudiolibri multilingue24.9023.10—

Più basso è meglio; il grassetto indica il vincitore di ogni riga. La colonna di Whistle riporta i valori stampati dal vendor. Le altre due colonne sono lette dalle barre del grafico — il vendor dichiara che sono i numeri pubblicati da Whisper e Moonshine, e si rifiuta di stamparli.

Whistle vince cinque delle otto righe in cui esiste un confronto. Per un modello 2,5 volte più piccolo del rivale a precisione più vicina è un risultato genuino, e la riga FLEURS — 3,1 punti meglio di Whisper base sul parlato letto multilingue — è la cosa più impressionante del grafico.

Ora guarda cosa perde:

  • AMI, di 4,57 punti contro Whisper base. Microfoni in campo lontano, più parlanti, sovrapposizioni, interruzioni. Whistle non è solo indietro, è il peggiore dei tre, e perde contro un modello 8,6 volte più grande.
  • TED-LIUM, di 2,62 punti. Un solo parlante, ma una sala grande, un microfono da palco e un eloquio non scritto.
  • MLS, di 1,80 punti. Multilingue a lunga durata, mediato su sei lingue non inglesi.

Lo schema non è sottile una volta che i numeri sono affiancati. Ogni riga che Whistle vince è con microfono ravvicinato e, di fatto, un solo parlante. Ogni riga che perde ha distanza tra bocca e microfono oppure più di una persona nella stanza. Gli audiolibri letti e il parlato dettato sono esattamente il profilo che un front end limitato in banda a 16 kHz con un encoder minuscolo gestisce bene. Riverbero e parlanti sovrapposti sono esattamente ciò che non può permettersi di avere la capacità di districare.

Quest'unica frase concilia le due metà del thread di lancio. Chi ha provato la dettatura in un telefono tenuto vicino al viso l'ha apprezzato. Chi lo ha puntato su una clip di un film, una riunione o una stanza no. Nessuno stava misurando male.

Il numero da portare a casa

4,31 e 26,07 sono lo stesso modello con gli stessi pesi. Se di Whistle ricordi un solo valore di WER, ricorda la forbice, non il titolo.

Una nota sul risultato 70/170​

Il risultato dal campo più citato nel thread — 70 corrette su 170, contro 168/170 di un modello ASR Qwen molto più grande — è una misura reale, ma è la misura delle impostazioni di default su un vocabolario chiuso. Lo stesso tester ha riportato 164/170 dopo la messa a punto. Cosa è cambiato è l'argomento della prossima sezione, ed è la funzione più sottovalutata della scheda del modello.

Il keyword biasing è la leva principale di accuratezza​

Whistle decodifica con cinque beam valutati da una log-probabilità normalizzata per lunghezza, e accetta un elenco di parole che ti aspetti di sentire e le favorisce durante quella ricerca, con corrispondenza tramite un automa di Aho-Corasick.

In un modello ASR generalista questa è una comodità. In un modello da 16,9 MB con un vocabolario di 8.192 pezzi è più vicina a un elemento portante. Il modello ha pochissima capacità da spendere in un modello linguistico implicito, quindi nomi propri, nomi di prodotto, toponimi e gergo di dominio sono esattamente ciò che sbaglia — ed esattamente ciò che una lista di keyword corregge. Passare da 70/170 a 164/170 significa dal 41% al 96% con gli stessi pesi.

Trascrivi con i due argomenti che contano

import needle

r = needle.transcribe(
  "clip.wav",
  keywords=["Kubernetes", "Grafana", "Prometheus", "Aoife", "Nguyen"],
  word_timestamps=True,
  language="en",          # skip detection when you already know
)

print(r["text"])
for w in r["words"]:
  print(w["word"], w["start"], w["end"], w["probability"])

Tre cose in quello snippet vanno dette chiaramente:

  1. keywords non è un filtro di post-elaborazione. Cambia la ricerca a beam, quindi può recuperare una parola che il decoder altrimenti non avrebbe mai collocato.
  2. language="en" elimina una modalità di fallimento, non solo latenza. Il rilevamento automatico su sette lingue in una clip breve o rumorosa è un'altra cosa che può andare storta. Se la tua app conosce la lingua, dichiarala.
  3. Ogni parola porta la propria probability. È la tua soglia di confidenza — vedi il pattern di passaggio di consegne più sotto.
Watch out
  • Una lista di keyword troppo lunga diluisce il bias e comincia a spingere il decoder verso parole che nessuno ha detto. Tienila al vocabolario che i tuoi utenti producono davvero in quel contesto — la schermata corrente, la rubrica corrente, il documento corrente — non l'intero glossario del prodotto.

Il muro dei 30 secondi è nell'encoder, non in un file di configurazione​

30 secondi a 16 kHz sono 480.000 campioni. Dopo lo stem convoluzionale è un frame ogni 80 ms, quindi 375 frame dell'encoder, e il decoder si ferma a 320 token di output. Sono forme fisse in un file di tensori da 16,9 MB. Non esiste un flag che le alzi, e un tester nel thread di lancio che ha registrato oltre il limite ha ottenuto un errore di runtime anziché una trascrizione troncata.

Quindi qualsiasi clip più lunga di 30 secondi significa che la segmentazione è tua — e la segmentazione è dove vive davvero l'accuratezza dell'ASR a lunga durata, perché un taglio a metà di una parola o di una proposizione è un errore da cui il modello non si può riprendere.

Guided walkthrough1 of 5
  1. 16 kHz mono non è un consiglio, è il contratto di input. Un file stereo a 44,1 kHz va convertito prima che raggiunga il modello; l'installazione base gestisce WAV a 16 kHz e campioni grezzi, e l'extra [mic] aggiunge ricampionamento e acquisizione dal microfono.

Il silenzio è gestito; il parlato a basso SNR no​

La scheda del modello fa un'affermazione precisa e gradita: silenzio e rumore stazionario restituiscono una trascrizione vuota anziché una frase inventata, perché il rilevamento del silenzio gira prima della ricerca a beam. È una correzione diretta del difetto più noto di Whisper — allucinare con sicurezza sottotitoli sul nulla.

Leggi l'affermazione con precisione. Copre silenzio e rumore stazionario. Non copre il parlato basso, distante o sovrapposto, e il thread contiene proprio quel fallimento: un tester ha riportato che il modello emetteva «Thank you.» in ripetizione per oltre un minuto mentre veniva riprodotto un dialogo reale, e un altro ha trovato una negazione ribaltata — «can handle» al posto di «can't handle» — più una parola inventata di sana pianta.

Sono i classici artefatti dell'addestramento su sottotitoli di video web, dove «Thanks for watching» occupa una quota enorme del testo, e sopravvivono al filtro del silenzio perché il filtro non era mai stato pensato per loro. Se un n't perso cambierebbe ciò che fa la tua applicazione, un controllo sulla probabilità per parola non è facoltativo.

Lo streaming esiste — il thread di lancio ha concluso di no​

Una lamentela ricorrente nella discussione era che Whistle non può fare trascrizione dal vivo, perché la demo non mostrava testo parziale durante il parlato. La demo no; la libreria sì. needle.stream(chunks) prende input dal microfono in tempo reale e conferma le parole su cui passaggi consecutivi sovrapposti concordano.

Quella politica — decodificare ripetutamente una finestra sovrapposta, emettere solo il prefisso su cui due passaggi concordano — è la famiglia LocalAgreement dell'ASR in streaming, e saperlo ti dice ciò che la scheda tecnica non dirà:

La latenza percepita non è gli 11,1 ms al primo token. È il ritardo di accordo: quanto una parola deve aspettare prima che un secondo passaggio la confermi. Il TTFT è una misura di velocità di decodifica su una clip completa da 10 secondi. In un ciclo di streaming il numero visibile all'utente è fissato dal passo della tua finestra e da quanto sei disposto ad aspettare per la stabilità, e saranno centinaia di millisecondi, non undici.

Veloce resta veloce — 11,1 ms contro i 73,2 ms di Whisper base e i 22,8 ms di Moonshine, e 1.319 token/s di decodifica contro 266 e 262, misurati su 10 s di audio su una CPU Apple M4 Pro. Solo, non promettere a un product manager 11 ms di sottotitoli dal vivo.

Due funzioni silenziosamente più interessanti delle dimensioni​

Il decoder è «a scala», quindi un file è una famiglia​

Ogni profondità da due layer in su è un modello distribuibile, selezionato al caricamento con --audio-depth. Scarichi un unico blob da 16,9 MB e scegli il tuo punto accuratezza/latenza sul dispositivo, che è il posto giusto dove sceglierlo — un orologio e un telefono possono eseguire lo stesso artefatto a profondità diverse. Per dare la scala, il modello di testo Needle fratello decodifica a circa 4.000 token/s con due layer e 400 con venti su un Raspberry Pi 5.

embed() ti dà il riconoscimento vocale senza alcuna trascrizione​

L'output dell'encoder è disponibile direttamente: una riga per frame da 80 ms, tramite needle.Whistle().embed(audio). È rilevamento di wake word, matching di comandi, deduplicazione audio e «trova dove in questa registrazione qualcuno ha detto questo» — senza decodificare testo, senza un modello linguistico e senza le classi di errore discusse sopra, perché non gli chiedi mai di scrivere nulla.

Per molti compiti embedded («l'utente ha detto una di queste undici cose?») questo è lo strumento giusto e la trascrizione è la deviazione.

Eseguilo dalla CLI, compreso il confronto a tre integrato

pip install cactus-needle

# microphone playground
needle whistle playground

# put Whistle next to Whisper and Moonshine on YOUR audio
needle whistle compare my-clip.wav

# air-gapped / embedded: fetch a platform engine and the weights
needle download macos-arm64
needle download whistle
./macos-arm64/needle --model whistle.cact --audio clip.wav --audio-word-timestamps

Il sottocomando compare merita una menzione: il vendor distribuisce lo strumento che verifica le sue stesse affermazioni sul tuo audio. Data quanto la forbice di WER sopra dipende dalle condizioni di registrazione, eseguirlo su una clip rappresentativa del tuo audio vale più di qualsiasi tabella di questa pagina.

Una proprietà di riproducibilità da copiare​

Il motore non legge alcuna variabile d'ambiente. Ogni comportamento è un default compilato o un flag esplicito. Significa che lo stesso blob con gli stessi flag dà lo stesso punteggio su qualsiasi macchina, una proprietà che la maggior parte degli stack di inferenza non può vantare e che conta moltissimo quando cerchi di capire se è regredita la valutazione della settimana scorsa o la shell della settimana scorsa.

Scegliere: Whistle, Whisper, Parakeet o un'API cloud​

La tua situazioneScegliPerché
Dettatura su telefono o dispositivo indossabile, microfono ravvicinato, offline, 7 lingue supportateWhistleÈ il centro di progetto. 16,9 MB, niente GPU, timestamp per parola, e batte Whisper base proprio su questo profilo audio
Wake word o insiemi fissi di comandi su un microcontrolloreWhistle embed()Salta del tutto la trascrizione; confronta i frame dell'encoder
Registrazioni di riunioni, più parlanti, microfoni da stanzaNon WhistleIl suo stesso grafico lo mette ultimo su AMI. Usa un Whisper a dimensione piena, Parakeet o un ASR cloud con diarizzazione
Qualsiasi lingua fuori dalle setteNon WhistleSolo inglese, tedesco, francese, spagnolo, italiano, olandese e polacco. Niente cinese, nonostante sia stata l'aggiunta più richiesta nel thread di lancio
Miglior accuratezza open-weight per secondo su GPU, ingleseParakeetparakeet-tdt-0.6b-v2 di NVIDIA era il favorito dei professionisti nel thread; CC-BY-4.0
Audio che non puoi inviare da nessuna parte, e l'accuratezza conta più delle dimensioniWhisper large, in localeResta il riferimento di accuratezza. Scambi un ingombro ~100 volte maggiore per averla
Trascrizioni mediche, legali o finanziarie a valore di registroASR cloud con un umano nel cicloLa modalità di fallimento del ribaltamento della negazione descritta sopra è da sola squalificante

Un ibrido è di solito la risposta giusta, e ha la stessa forma di ogni altra divisione locale/remoto di questo sito: esegui il modello piccolo su tutto, usa le probabilità per parola come soglia, fai salire la frazione incerta. Vedi Claude plus local models per il pattern generale e a private local AI stack per capire dove si colloca in esso un passaggio di trascrizione.

Cosa ci dice questo sull'ondata on-device in generale​

Whistle è una buona istanza di uno schema che compare sempre più tra i modelli piccoli: la capacità è reale e l'involucro operativo è stretto, e solo la prima metà sta in un titolo. La quantizzazione a 2 bit non è un trucco — il modello funziona davvero — ma compra le sue dimensioni spendendo la capacità che avrebbe gestito l'audio difficile, e il grafico del vendor mostra esattamente dove cade il conto etichettando solo le righe in cui non cade.

La regola pratica si generalizza oltre l'ASR: quando un modello piccolo pubblica una forbice ampia di benchmark, la forbice è la specifica. Trova la riga in cui va peggio, capisci cosa ha quel set di test che gli altri non hanno e verifica se il tuo input reale somiglia a quella riga. Per Whistle la risposta è distanza e sovrapposizione. Per un modello linguistico quantizzato di solito è il contesto lungo — vedi cosa nasconde «98,2% di retention».

Check yourself

0/6
  1. Whistle è 16,9 MB contro i 145,3 MB di Whisper base. Cosa rende fuorviante quel confronto 9x?
  2. Whistle ottiene 4,31 di WER su LibriSpeech test-clean e 26,07 su AMI. Cosa distingue i set di test che vince da quelli che perde?
  3. La tua app deve trascrivere una nota vocale di 90 secondi. Cosa richiede il limite di 30 secondi di Whistle?
  4. Un tester è passato da 70/170 a 164/170 enunciati corretti con gli stessi pesi di Whistle. Qual è la leva più probabile?
  5. Whistle riporta 11,1 ms al primo token. Cosa vedrà un utente in un ciclo di sottotitolazione dal vivo?
  6. La scheda del modello dice che il silenzio restituisce una trascrizione vuota anziché una frase inventata. Da cosa NON ti protegge?
Premi Invio o Spazio per girare la carta. Usa le frecce sinistra e destra per spostarti tra le carte.Termine mostrato.
1 / 12

Fonti e approfondimenti​

Prossimi passi​