"""
Moteur de transcription vocale Whisper Turbo via mlx_whisper.
"""
import mlx.core as mx
import mlx_whisper
import numpy as np
from ...audio.audioProcessor import AudioProcessor
from ...core.logger import getMirzaLogger
from ...core.textCleaner import TextCleaner
from ..interfaces.baseStt import BaseStt
logger = getMirzaLogger("mirza.stt.whisper")
[docs]
class MlxWhisperStt(BaseStt):
"""
Whisper Turbo local sur puce Apple Silicon (MLX).
Modele quantifie en 4 bits, pour une empreinte VRAM d'environ 450 Mo.
"""
[docs]
def __init__(self, modelRepo: str = "mlx-community/whisper-large-v3-turbo-q4"):
"""
Initialise le moteur Whisper ASR.
Parameters
----------
modelRepo : str, optional
Depot HuggingFace du modele Whisper MLX. Defaut :
"mlx-community/whisper-large-v3-turbo-q4".
"""
self.modelRepo = modelRepo
[docs]
def warmUp(self) -> None:
"""
Pre-charge integralement les poids et calibre le pipeline Metal.
"""
try:
dummyAudio = np.zeros(16000, dtype=np.float32)
mlx_whisper.transcribe(
dummyAudio,
path_or_hf_repo=self.modelRepo,
fp16=True,
)
mx.clear_cache()
print(f"[STT (MLX_WHISPER)] Whisper Turbo quantifié pré-chargé en VRAM ({self.modelRepo}).")
except Exception as e:
print(f"[STT (MLX_WHISPER)] Avertissement warmUp : {e}")
[docs]
def transcribe(
self,
audioArray: np.ndarray,
language: str = "fr",
initialPrompt: str = "Bonjour Mirza.",
) -> str:
"""
Transcrit le flux audio avec Whisper Turbo MLX via MLXs.
Parameters
----------
audioArray : np.ndarray
Echantillons audio mono 16 kHz au format float32.
language : str, optional
Code langue ISO (ex: 'fr'). Defaut : "fr".
initialPrompt : str, optional
Prompt textuel de guidage contextuel. Defaut : "Bonjour Mirza.".
Returns
-------
str
Texte transcrit filtre du bruit ou vide si inaudible.
"""
if audioArray is None or len(audioArray) == 0:
return ""
try:
if isinstance(audioArray, np.ndarray):
processedAudio = AudioProcessor.normalizeAudio(
audioArray,
targetPeak=0.95,
allowAmplification=False,
)
else:
processedAudio = audioArray
sttResult = mlx_whisper.transcribe(
processedAudio,
path_or_hf_repo=self.modelRepo,
language=language,
temperature=0.0,
initial_prompt=initialPrompt if initialPrompt else None,
fp16=True,
)
mx.clear_cache()
rawText = sttResult.get("text", "").strip()
cleanedText = TextCleaner.cleanSttText(rawText)
if TextCleaner.isNoiseTranscription(cleanedText):
return ""
return cleanedText
except Exception as e:
print(f"[STT (MLX_WHISPER)] Erreur transcription : {e}")
return ""
[docs]
def unload(self) -> None:
"""
Libere le modele Whisper.
Sans effet sur ce moteur, qui ne charge ses poids qu'a la premiere
transcription.
"""
return None