Beta/superviseur/whisper_worker.py

59 lines
2.3 KiB
Python
Raw Normal View History

2026-02-06 22:23:20 +01:00
import os
import logging
import asyncio
from concurrent.futures import ThreadPoolExecutor
from typing import Optional
logger = logging.getLogger('Superviseur')
class WhisperWorker:
"""Handles local STT transcription using faster-whisper."""
def __init__(self, model_size="large-v3", device="cpu"):
self.model_size = model_size
self.device = device
self.model = None
self.executor = ThreadPoolExecutor(max_workers=2)
self.initialized = False
def initialize(self):
"""Load the model into RAM/VRAM."""
try:
from faster_whisper import WhisperModel
logger.info(f"◈ SYSTEM: Initializing Whisper ({self.model_size}) on {self.device}...")
# On tente le chargement. Si device="cuda" échoue (AMD), on bascule sur CPU.
try:
self.model = WhisperModel(self.model_size, device=self.device, compute_type="int8")
except Exception as e:
if self.device != "cpu":
logger.warning(f"◈ GPU failure ({e}). Falling back to CPU.")
self.device = "cpu"
self.model = WhisperModel(self.model_size, device="cpu", compute_type="int8")
else:
raise e
self.initialized = True
logger.info(f"◈ SYSTEM: Whisper Model Loaded on {self.device}. Ear Protocol Active.")
except Exception as e:
logger.error(f"Failed to initialize Whisper: {e}")
self.initialized = False
async def transcribe(self, audio_path: str) -> Optional[str]:
"""Transcribe an audio file asynchronously."""
if not self.initialized or not self.model:
return None
def _run():
try:
segments, info = self.model.transcribe(audio_path, beam_size=5)
text = " ".join([segment.text for segment in segments]).strip()
logger.debug(f"◈ Whisper: Transcription result: '{text}' (lang: {info.language})")
return text
except Exception as e:
logger.error(f"Transcription error: {e}")
return None
loop = asyncio.get_event_loop()
return await loop.run_in_executor(self.executor, _run)