Kazeia-central/kazeia_central/voice/transcribe.py

46 lines
1.6 KiB
Python

"""Transcription Whisper (PC) du segment de référence — tourne sous cv_venv.
Important : on transcrit le **segment préparé** (mono/16k/~15 s), PAS la capture
brute. Le texte du `.cvps` doit correspondre à ce qui est parlé DANS le segment
enrôlé (§3/§4) ; transcrire les 111 s d'origine donnerait un texte qui ne colle pas
aux ~15 s réellement extraits. `prepare_wav` étant déterministe, le segment transcrit
ici == le segment enrôlé.
"""
from __future__ import annotations
import os
import tempfile
from .enroll import prepare_wav
# Défaut "small" : "base" transcrit mal le FR (validé), "small" est le bon compromis
# qualité/CPU ; "medium" encore mieux mais lourd. La transcription est de toute façon
# relue par l'opérateur. Configurable via CV_WHISPER_MODEL.
CV_WHISPER_MODEL = os.environ.get("CV_WHISPER_MODEL", "small")
_model_cache: dict[str, object] = {}
def _model(size: str):
if size not in _model_cache:
import whisper # openai-whisper (présent dans cv_venv)
_model_cache[size] = whisper.load_model(size)
return _model_cache[size]
def transcribe(wav_path: str, model: str | None = None) -> dict:
"""Transcrit le segment de référence. Renvoie {text, language, model, prep}."""
size = model or CV_WHISPER_MODEL
m = _model(size)
with tempfile.TemporaryDirectory() as td:
prep = os.path.join(td, "prep.wav")
prep_info = prepare_wav(wav_path, prep)
result = m.transcribe(prep, fp16=False) # CPU → fp16 off
return {
"text": (result.get("text") or "").strip(),
"language": result.get("language"),
"model": size,
"prep": prep_info,
}