vocal_helper.nemotron_asr module
Transcription par l’encodeur de Nemotron 3.5 Transcribe, sans torch : onnxruntime et numpy.
Pourquoi ce module
Nemotron 3.5 Transcribe est un LLM de parole de 30 milliards de paramètres,
réservé aux GPU NVIDIA. Sous le LLM, son encodeur audio de 600 millions de
paramètres porte une tête CTC qui transcrit seule, dans une quarantaine de
langues, avec un horodatage par trame de 40 ms. C’est cette partie, exportée
en ONNX par studies/nemotron_asr_export.py, que ce module fait tourner :
le même fichier marche sous Linux, Windows et macOS, sur CPU comme sur CUDA, et
se charge depuis Rust par la caisse ort.
Ce que l’hôte fait autour du graphe
Le graphe prend un log-mel normalisé et rend, toutes les 40 ms, le jeton le plus probable, sa log-probabilité et celle du blanc. Le reste est ici, en numpy pur, donc vérifiable sans modèle :
le front-end de NeMo, avec la fenêtre et le banc de filtres du point de contrôle, que le graphe porte dans ses métadonnées ;
la normalisation par bande, sur l’enregistrement entier ;
le découpage en fenêtres de 30 s, la longueur que l’encodeur a apprise ;
le décodage CTC glouton, puis le regroupement des pièces SentencePiece en mots horodatés, sans dépendre de
sentencepiece.
Le vocabulaire contient aussi des balises : changement de locuteur
(<spk:N>), événement (<ev:laughter>…), début et fin de style
(<sty:stt:…>). Elles sont rendues à part, jamais mêlées aux mots.
- class vocal_helper.nemotron_asr.AsrSettings(fb, window, vocab, blank_id, sample_rate=16000, n_fft=512, hop_length=160, preemphasis=0.97, log_guard=5.960464477539063e-08, stack=8, frame_s=0.04, chunk_s=30.0)[source]
Bases:
objectLe front-end et le vocabulaire, tels que le graphe les porte.
- Parameters:
- fb
Banc de filtres mel
(n_mels, n_fft // 2 + 1)du point de contrôle.- Type:
NDArray[np.float32]
- window
Fenêtre d’analyse
(win_length,), centrée dans la transformée.- Type:
NDArray[np.float32]
- classmethod from_metadata(metadata)[source]
Lire les réglages des métadonnées du graphe.
- Raises:
ValueError – Si le graphe ne suit pas le contrat attendu.
- Parameters:
- Return type:
- class vocal_helper.nemotron_asr.CtcToken(id, first, last, logprob)[source]
Bases:
objectUn jeton émis par le décodage glouton, avec ses trames.
- class vocal_helper.nemotron_asr.NemotronAsrStage(graph=None, *, batch=False, max_chunk_s=30.0, precision='int8', providers=None, threads=None, warmup=False, **_ignored)[source]
Bases:
objectL’étage de transcription de la pipeline, par le graphe Nemotron.
Même contrat que
vocal_helper.asr.WhisperStage: il consomme desDiarizedSegmentet rend uneUtterancepar segment, dans l’ordre, avec le locuteur du diariseur. On le choisit parasr={"engine": "nemotron"}.Les segments consécutifs sont mis bout à bout dans des fenêtres d’au plus
max_chunk_ssecondes, un appel au graphe par fenêtre ; chaque mot revient au segment qui contient son milieu. Hors ligne c’est le chemin à plein régime ; en direct (batch=False) chaque segment part seul, dès qu’il arrive.Le modèle ne dit pas la langue qu’il entend :
languageresteNone.- Parameters:
graph (str or Path, optional) – Le graphe ; par défaut celui de
resolve_graph().precision (str) –
"int8"(défaut) ou"fp32".batch (bool) – Regrouper les segments (hors ligne) ou les traiter un par un (direct).
max_chunk_s (float) – Longueur maximale d’une fenêtre ; 30 s, celle que l’encodeur a apprise.
warmup (bool) – Ouvrir le graphe dès le démarrage plutôt qu’au premier segment, pour que la première énonciation en direct n’attende pas le chargement.
providers (list[str] | None) – Comme
NemotronOnnxAsr.threads (int | None) – Comme
NemotronOnnxAsr._ignored (Any)
- class vocal_helper.nemotron_asr.NemotronOnnxAsr(graph=None, *, precision='int8', providers=None, threads=None)[source]
Bases:
objectTranscrire un fichier avec le graphe ONNX de l’encodeur Nemotron.
- Parameters:
graph (str or Path, optional) – Le graphe. Par défaut
resolve_graph():$VH_NEMOTRON_ASR_GRAPH, sinon le cache, rempli une fois depuisderaison.ai/nemotron-onnx.precision (str) –
"int8"(défaut, 669 Mo) ou"fp32"(2,7 Go, exact).providers (list of str, optional) – Les moteurs d’exécution ; même ordre d’autorité que le diariseur : l’argument, puis
$VOCAL_HELPER_PROVIDER, puis l’ordre mesuré.threads (int, optional) – Fils du moteur CPU ;
Nonelaisse onnxruntime choisir.
- frames(audio, sample_rate)[source]
Jetons, log-probabilités et log-probabilités du blanc, toutes les 40 ms.
Normalisation sur l’enregistrement entier, puis fenêtres indépendantes de
chunk_ssecondes : l’encodeur de référence découpe ainsi.
- locate()[source]
Le chemin du graphe : l’argument, sinon
resolve_graph().- Raises:
FileNotFoundError – Si le graphe désigné n’existe pas.
- Return type:
- property settings: AsrSettings
Les réglages du graphe, lus sans charger ses poids.
- streaming_frames(audio, sample_rate, *, hop_s=2.0, left_s=8.0, right_s=0.0, normalize='running')[source]
Les trames d’un flux simulé, et le retard de chacune.
Toutes les
hop_ssecondes, on transcrit lesleft_s + hop_s + right_sdernières secondes et on arrête les trames de[t - right_s - hop_s, t - right_s). Une trame attend donc entreright_setright_s + hop_savant d’être écrite, calcul en sus. La concaténation des trames arrêtées se décode comme un fichier.Un flux ne connaît pas la suite, donc pas la moyenne de l’enregistrement que la normalisation hors ligne emploie.
normalize="running"prend la moyenne et l’écart-type par bande de tout l’audio déjà vu, ce qui reste causal ;"window"les prend sur la fenêtre seule.- Returns:
ids,logprob,blank_logprobetdelay_s, le retard de chaque trame entre la fin de son audio et son écriture, calcul compris.- Return type:
- Raises:
ValueError – Si la fréquence n’est pas celle du modèle, si la fenêtre dépasse celle que l’encodeur a apprise, ou si
normalizeest inconnu.- Parameters:
- class vocal_helper.nemotron_asr.Transcript(words=<factory>, tags=<factory>, speech=<factory>)[source]
Bases:
objectLes mots, et à part les balises que la tête CTC émet.
- Parameters:
- class vocal_helper.nemotron_asr.Word(text, start_s, end_s, confidence)[source]
Bases:
objectUn mot horodaté ;
confidenceest la moyenne des probabilités de ses pièces.
- vocal_helper.nemotron_asr.greedy_ctc(ids, logprob, blank_id)[source]
Fusionner les répétitions et retirer les blancs, en gardant les trames.
Examples
>>> import numpy as np >>> toks = greedy_ctc(np.array([9, 5, 5, 9, 5, 7]), np.zeros(6), blank_id=9) >>> [(t.id, t.first, t.last) for t in toks] [(5, 1, 2), (5, 4, 4), (7, 5, 5)]
- vocal_helper.nemotron_asr.log_mel(audio, settings)[source]
Le log-mel de NeMo,
(n_mels, T), et le nombre de trames valides.La recette de
FilterbankFeatures: pré-accentuation, transformée centrée sur un remplissage constant (et non par réflexion, à la différence du front-end du diariseur), fenêtre de 400 points centrée dans 512, puissance, banc de filtres,log(x + 2**-24). Les trames au-delà delen(audio) // hopsont mises à zéro, comme NeMo le fait.Examples
>>> import numpy as np >>> s = AsrSettings(np.ones((128, 257), np.float32), np.hanning(400).astype(np.float32), (), 0) >>> mel, valid = log_mel(np.zeros(16000, np.float32), s) >>> mel.shape, valid ((128, 101), 100)
- vocal_helper.nemotron_asr.normalize_per_feature(mel, valid)[source]
Centrer et réduire chaque bande sur les trames valides, comme NeMo.
Écart-type sans biais (division par
n - 1), plancher de1e-5ajouté après, trames invalides remises à zéro.Examples
>>> import numpy as np >>> out = normalize_per_feature(np.array([[1.0, 3.0, 9.0]], np.float32), 2) >>> [round(float(v), 4) for v in out[0]] [-0.7071, 0.7071, 0.0]
- vocal_helper.nemotron_asr.resolve_graph(precision='int8')[source]
Le graphe de la précision demandée, téléchargé une fois puis lu du cache.
Ordre :
$VH_NEMOTRON_ASR_GRAPHs’il est défini, sinon le cache ($VH_CACHE_DIR/nemotron-onnx, par défaut~/.cache/vocal-helper), rempli au besoin depuis$VH_NEMOTRON_ASR_URLouDEFAULT_BASE_URL. Le téléchargement passe par os-helper : reprise, nouvelles tentatives, écriture atomique, et vérification de l’empreinte sur l’adresse par défaut.- Raises:
ValueError – Si la précision est inconnue.
- Parameters:
precision (str)
- Return type:
- vocal_helper.nemotron_asr.tokens_to_words(tokens, vocab, frame_s)[source]
Regrouper les pièces en mots horodatés, et sortir les balises à part.
Une pièce qui commence par
▁ouvre un mot ; les autres le prolongent. Une balise (<spk:1>,<ev:laughter>…) clôt le mot en cours.Examples
>>> vocab = ("<spk:1>", "▁bon", "jour", "▁à", "▁tous") >>> toks = [CtcToken(1, 0, 1, 0.0), CtcToken(2, 3, 3, 0.0), CtcToken(0, 5, 5, 0.0), ... CtcToken(3, 6, 6, 0.0), CtcToken(4, 8, 9, 0.0)] >>> words, tags = tokens_to_words(toks, vocab, 0.04) >>> [(w.text, w.start_s, w.end_s) for w in words] [('bonjour', 0.0, 0.16), ('à', 0.24, 0.28), ('tous', 0.32, 0.4)] >>> tags [(0.2, '<spk:1>')]