Vosk 0.3.45 testé pour de vrai : protocole, script et mesures (2026-10-18)
Test exécuté le 18 octobre 2026 (page rédigée le 18 octobre 2026).
Test d'usage réel mais limité : une machine, un jeu de test synthétique, aucune note ni classement. Les résultats ne se généralisent pas à d'autres données. Notre méthode.
En résumé
Le 2026-10-18, nous avons installé Vosk 0.3.45 dans un environnement Python neuf, téléchargé le petit modèle français vosk-model-small-fr-0.22, vérifié les empreintes, puis transcrit un seul extrait audio en français de 25,95 s produit par une voix de synthèse. Ce test porte sur une machine, une version, un modèle et 63 mots : il décrit ce que nous avons observé, il ne mesure pas la qualité générale de Vosk et ne se généralise pas à vos enregistrements. Il complète l'avis MagicMate sur Vosk, qui reste une lecture des sources publiques, en particulier pour les licences des modèles.
Ce que nous avons observé :
- Temps de traitement : 3 514, 3 571, 3 536 et 3 544 ms sur 4 exécutions (moyenne 3 541 ms), chargement du modèle inclus (environ 330 à 345 ms), soit un facteur temps réel d'environ 0,14. Processeur seul.
- Transcription : 6 erreurs de mots sur 63 mots de référence (9,5 %) avec notre normalisation, sur un seul extrait synthétique, sans valeur statistique.
- Les nombres sont restitués en toutes lettres (« vingt-trois », « deux mille vingt-six ») ; le nom propre inventé est déformé ; la sortie est en minuscules, sans ponctuation.
- Les 4 exécutions ont donné exactement le même texte.
Protocole et commandes
Machine : Windows 11, Intel Core i5-10400F (6 cœurs, 12 threads), processeur seul, Python 3.13.13. Commandes en PowerShell. Dans les commandes, $b désigne un dossier de travail neuf (sous-dossiers dl, audio, src, venv, model). Aucun accès réseau pendant la transcription.
- Environnement isolé :
python -m venv $b\venv. - Paquet Vosk. La version 0.3.45 (publiée le 2022-12-14) est la plus récente indiquée par l'API JSON de PyPI le 2026-10-18. Téléchargement sans installation :
$b\venv\Scripts\python.exe -m pip download vosk==0.3.45 --no-deps --only-binary=:all: --platform win_amd64 --python-version 3.13 -d $b\dl. Fichiervosk-0.3.45-py3-none-win_amd64.whl, SHA-256 calculé avecGet-FileHash <fichier> -Algorithm SHA256:6994ddc68556c7e5730c3b6f6bad13320e3519b13ce3ed2aa25a86724e7c10ac, identique à celui publié par PyPI pour ce fichier. - Installation :
$b\venv\Scripts\python.exe -m pip install --no-index --no-deps $b\dl\vosk-0.3.45-py3-none-win_amd64.whl, puis les dépendancescffi srt websockets tqdm requests(versions résolues le jour même : cffi 2.1.1, srt 3.5.3, websockets 17.2, tqdm 4.70.1, requests 2.34.2). - Modèle :
Invoke-WebRequest https://alphacephei.com/vosk/models/vosk-model-small-fr-0.22.zip -OutFile $b\dl\vosk-model-small-fr-0.22.zip. Taille 42 233 323 octets, identique à la taille de la liste officielle des modèles (model-list.json). Cette liste ne publie qu'une empreinte MD5,8873b1234503f6edd55f54bfff31cf3e, que nous avons retrouvée avecGet-FileHash -Algorithm MD5. Le SHA-256 que nous avons calculé, sans valeur officielle à comparer, estcabf6180e177eb9b3a9a9d43a437bd5e549f3a7d09525e5d69a3fed787be12ad. Extraction :Expand-Archive <zip> -DestinationPath $b\model(68,5 Mo décompressés). - Audio de référence : synthèse vocale Windows (System.Speech, voix « Microsoft Hortense Desktop », fr-FR), écrite avec
SetOutputToWaveFileen 16 kHz, 16 bits, mono, fichiertest-fr.wavde 830 286 octets, 25,95 s, SHA-25631e92d62f7fa7eec8c9fc4a7955b485a103b43edb1bb75595d6e2eccf8becb06. Le texte est identique à celui de notre test de whisper.cpp et le fichier a la même taille en octets. - Transcription :
$b\venv\Scripts\python.exe -I $b\src\run_vosk.py $b\model\vosk-model-small-fr-0.22 $b\audio\test-fr.wav $b\src\reference.txt 4. Le script est conservé ci-dessous (SHA-256a656a264cbc4bdd43bfe14d5feebbe0fc8501cd33f64ff614cbbc61884690fb6). Il charge le modèle à chaque exécution, lit le WAV par blocs de 4 000 images, activeSetWords(True)(horodatage par mot) et mesure le temps avectime.perf_counter()autour du chargement et de la reconnaissance. Le pic de mémoire est lu en fin de processus (PeakWorkingSetSize) : il couvre donc les 4 exécutions du même processus. - Taux d'erreur de mots : distance de Levenshtein sur les mots, en minuscules, avec les tirets et apostrophes traités comme séparateurs et la ponctuation retirée (fonctions
normetwerdu script). Cette normalisation compte 63 mots de référence ; notre test de whisper.cpp en comptait 62 avec un script qui n'a pas été conservé : les deux pourcentages ne sont donc pas comparés ici.
Texte de référence exact (sans donnée personnelle, nom propre fictif), enregistré dans reference.txt et lu par la voix de synthèse :
Aujourd'hui, le ciel est nuageux sur la région de Lyon. La température maximale atteindra vingt-trois degrés cet après-midi. Madame Odette Brancourt a présenté le bulletin météo le douze mars deux mille vingt-six. Demain, il pleuvra sur le nord du pays, avec des vents de soixante kilomètres par heure. Le week-end sera plus ensoleillé, et les températures remonteront progressivement.
Script exact run_vosk.py :
# Usage: python -I run_vosk.py <model_dir> <wav> <reference.txt> <runs>
import sys, json, time, wave, re, unicodedata, ctypes
from ctypes import wintypes
from vosk import Model, KaldiRecognizer, SetLogLevel
SetLogLevel(-1)
model_dir, wav_path, ref_path, runs = sys.argv[1], sys.argv[2], sys.argv[3], int(sys.argv[4])
class PMC(ctypes.Structure):
_fields_ = [("cb", wintypes.DWORD), ("PageFaultCount", wintypes.DWORD),
("PeakWorkingSetSize", ctypes.c_size_t), ("WorkingSetSize", ctypes.c_size_t),
("QuotaPeakPagedPoolUsage", ctypes.c_size_t), ("QuotaPagedPoolUsage", ctypes.c_size_t),
("QuotaPeakNonPagedPoolUsage", ctypes.c_size_t), ("QuotaNonPagedPoolUsage", ctypes.c_size_t),
("PagefileUsage", ctypes.c_size_t), ("PeakPagefileUsage", ctypes.c_size_t)]
def peak_mb():
k = ctypes.WinDLL("kernel32", use_last_error=True); p = ctypes.WinDLL("psapi", use_last_error=True)
k.GetCurrentProcess.restype = wintypes.HANDLE
p.GetProcessMemoryInfo.argtypes = [wintypes.HANDLE, ctypes.POINTER(PMC), wintypes.DWORD]
c = PMC(); c.cb = ctypes.sizeof(PMC)
p.GetProcessMemoryInfo(k.GetCurrentProcess(), ctypes.byref(c), c.cb)
return c.PeakWorkingSetSize / 1048576
def norm(s):
s = s.lower().replace("’", "'")
s = re.sub(r"[-']", " ", s)
s = re.sub(r"[^\w\s]", " ", s)
return s.split()
def wer(ref, hyp):
d = list(range(len(hyp) + 1))
for i in range(1, len(ref) + 1):
prev, d[0] = d[0], i
for j in range(1, len(hyp) + 1):
cur = d[j]
d[j] = min(d[j] + 1, d[j - 1] + 1, prev + (ref[i - 1] != hyp[j - 1]))
prev = cur
return d[len(hyp)]
ref = open(ref_path, encoding="utf-8").read()
refw = norm(ref)
res = []
for r in range(runs):
t0 = time.perf_counter()
m = Model(model_dir); t_load = time.perf_counter()
wf = wave.open(wav_path, "rb")
rec = KaldiRecognizer(m, wf.getframerate()); rec.SetWords(True)
parts = []
while True:
data = wf.readframes(4000)
if not data: break
if rec.AcceptWaveform(data): parts.append(json.loads(rec.Result()))
parts.append(json.loads(rec.FinalResult()))
t1 = time.perf_counter()
text = " ".join(p.get("text", "") for p in parts).strip()
dur = wf.getnframes() / wf.getframerate()
res.append(dict(run=r + 1, total_ms=round((t1 - t0) * 1000), load_ms=round((t_load - t0) * 1000), dur_s=round(dur, 2), text=text))
if r == 0:
json.dump(parts, open(sys.argv[3] + ".vosk-words.json", "w", encoding="utf-8"), ensure_ascii=False, indent=1)
hypw = norm(res[0]["text"])
print(json.dumps(res, ensure_ascii=False, indent=1))
print("ref_words", len(refw), "hyp_words", len(hypw), "errors_raw", wer(refw, hypw), "peak_mb", round(peak_mb(), 1))
print("HYP:", res[0]["text"])
Résultats mesurés
| Mesure | Valeur |
|---|---|
| Durée de l'audio | 25,95 s |
| Temps total, 4 exécutions | 3 514 / 3 571 / 3 536 / 3 544 ms (moyenne 3 541 ms) |
| Dont chargement du modèle | 344 / 335 / 331 / 332 ms |
| Facteur temps réel | environ 0,14 (environ 7 fois plus rapide que le temps réel) |
| Pic de mémoire du processus | 318,8 Mo (couvre les 4 chargements successifs) |
| Taille du modèle | 42,2 Mo compressé, 68,5 Mo décompressé |
| Erreurs de mots | 6 sur 63 mots de référence (9,5 %) |
Transcription obtenue, identique sur les 4 exécutions (accents restitués) : « aujourd'hui le ciel nuageux sur la région de lyon la température maximale atteindra vingt-trois degrés cet après-midi mme odette brand cours a présenté le bulletin météo le douze mars deux mille vingt-six demain il pleuvra sur le nord du pays avec des vents de soixante kilomètres par heure le week-end sera plus ensoleillés et les températures remonterons progressivement ».
Les 6 erreurs, relevées en comparant à la main avec le texte de référence : « est » omis dans « le ciel est nuageux » (1) ; « Madame » rendu « mme » (1) ; « Brancourt » rendu « brand cours », une substitution et une insertion (2) ; « ensoleillé » rendu « ensoleillés » (1) ; « remonteront » rendu « remonterons » (1). Nous ne qualifions pas ces erreurs au-delà de ce relevé.
Horodatage par mot : le premier segment renvoyé contient 9 mots, avec pour chacun un début, une fin et une confiance (par exemple « aujourd'hui », de 0,12 s à 0,84 s). Nous n'avons pas vérifié la précision de ces horodatages.
Le fichier README du modèle indique une mesure de l'éditeur, « %WER 23.95 », sur un jeu de test Common Voice. C'est une affirmation de l'éditeur sur un autre jeu de données : elle n'est ni reproduite ni comparable à notre mesure.
Limites du test
- Une seule machine (Windows 11, processeur i5-10400F), une seule version (Vosk 0.3.45, modèle
vosk-model-small-fr-0.22). - Un seul extrait de 25,95 s et 63 mots, généré par une voix de synthèse claire, sans bruit ni chevauchement de voix : les erreurs ne représentent pas celles d'enregistrements réels.
- Le pourcentage d'erreur dépend de la normalisation choisie (apostrophes et tirets séparateurs, minuscules) : avec un autre choix, il changerait.
- Le pic de mémoire couvre les 4 chargements dans un même processus ; il n'a pas été mesuré pour une exécution isolée.
- Les temps incluent le chargement du modèle ; ils ne sont pas représentatifs d'un autre matériel.
- Nous ne comparons pas ces chiffres à ceux de whisper.cpp : modèles, scripts de calcul et normalisations diffèrent.
Ce que nous n'avons pas testé
- Des enregistrements réels (téléphone, bruit, plusieurs locuteurs, accents), des fichiers longs, la reconnaissance en flux continu depuis un micro.
- Les autres modèles français (dont ceux sous licence non commerciale ou AGPL signalés dans l'avis), les grands modèles, les autres langues, la reconnaissance des locuteurs.
- Le mode vocabulaire restreint (grammaire), les liaisons Java, Node.JS, C#, C++, Rust, Go, l'exécution sur Raspberry Pi ou téléphone, le serveur WebSocket.
- D'autres systèmes d'exploitation et versions, y compris toute version postérieure à la 0.3.45.
- La licence propre au modèle utilisé, au-delà de la mention de la page publique (voir l'avis).
Sources
- Notre test du 2026-10-18, décrit ci-dessus (Vosk 0.3.45, modèle 0.22, empreintes vérifiées).
- https://github.com/alphacep/vosk-api
- https://pypi.org/project/vosk/0.3.45/ (empreinte SHA-256 du fichier)
- https://alphacephei.com/vosk/models (liste des modèles, taille et MD5 du modèle)
- Avis MagicMate sur Vosk pour la lecture des sources publiques et des licences.
Aller plus loin
- Avis MagicMate sur l'outil
- Fiche produit Vosk dans le catalogue MARKETIA
- Comparatif : Transcrire de l'audio en local : Whisper, WhisperX, Vosk et applications, ce que disent les sources
- Demander une installation sur devis (installation de Vosk chez vous, réponse sous 5 jours ouvrés, sans engagement)
- Tous les tests réels
- Dépôt du projet : https://github.com/alphacep/vosk-api