"""Adapta o faster-whisper para a transcrição local do Scanner.""" from pathlib import Path from typing import Any from ...scanner.modelos import PalavraDeTranscricao, SegmentoDeTranscricao class ProviderDeTranscricaoLocal: """Executa transcrição local em lote, sem transmitir a mídia.""" def __init__(self, modelo: str, dispositivo: str = "cpu", tipo_de_calculo: str = "int8", idioma: str = "pt", tamanho_do_lote: int = 16) -> None: """Carrega o modelo local e configura o tamanho do lote de inferência.""" if tamanho_do_lote < 1: raise ValueError("O tamanho do lote deve ser maior que zero.") self.nome_do_modelo = Path(modelo).name if "faster-whisper-" in modelo: self.nome_do_modelo = modelo.split("faster-whisper-", 1)[1].split("/", 1)[0] from faster_whisper import BatchedInferencePipeline, WhisperModel self.modelo = WhisperModel(modelo, device=dispositivo, compute_type=tipo_de_calculo) self.pipeline = BatchedInferencePipeline(model=self.modelo) self.idioma = idioma self.tamanho_do_lote = tamanho_do_lote def transcrever(self, clipe: Any) -> list[SegmentoDeTranscricao]: """Transcreve o áudio com VAD, timestamps e inferência em lote.""" arquivo = Path(clipe.arquivo) if not arquivo.is_file(): raise FileNotFoundError(f"Arquivo de áudio não encontrado: {arquivo}") segmentos, _ = self.pipeline.transcribe( str(arquivo), language=self.idioma, vad_filter=True, word_timestamps=True, batch_size=self.tamanho_do_lote, ) return [SegmentoDeTranscricao(float(s.start), float(s.end), s.text.strip(), None, tuple(PalavraDeTranscricao(w.word.strip(), float(w.start), float(w.end), getattr(w, "probability", None)) for w in (s.words or []) if w.word.strip())) for s in segmentos]