"""Detecção de sinais de reinício/recomeço de fala. Analisa padrões de que a pessoa começou novamente uma ideia: repetição do início de uma frase, pausas longas, marcadores explícitos ("não", "pera", "vamos de novo", "desculpa") e repetição de palavras consecutivas. """ from __future__ import annotations import re from typing import Iterable from .comparador_de_falas import ComparadorDeFalas from .modelos_de_retakes import Fala, SinalDeReinicio _MARCADORES = ( "não", "pera", "peraí", "pera ai", "espera", "vamos de novo", "de novo", "vamos recomeçar", "recomeçar", "desculpa", "desculpe", "deixa eu ver", "vou repetir", "esquece", "hmm", "hm", "uhm", "tá", "ta", ) _RE_MARCADOR = re.compile( r"\b(?:" + "|".join(re.escape(m) for m in _MARCADORES) + r")\b", re.IGNORECASE, ) _PAUSA_LONGA = 1.2 # segundos a partir dos quais a pausa sugere recomeço. class DetectorDeReinicios: """Encontra ``SinalDeReinicio`` em cada fala em relação à anterior.""" def __init__( self, comparador: ComparadorDeFalas | None = None, pausa_longa: float = _PAUSA_LONGA, ) -> None: self.comparador = comparador or ComparadorDeFalas() self.pausa_longa = pausa_longa def detectar(self, falas: Iterable[Fala]) -> list[SinalDeReinicio]: falas = list(falas) sinais: list[SinalDeReinicio] = [] for indice, fala in enumerate(falas): sinal = self._analisar(fala, falas[indice - 1] if indice > 0 else None) if sinal: sinais.append(sinal) return sinais def _analisar(self, fala: Fala, anterior: Fala | None) -> SinalDeReinicio | None: evidencias: list[str] = [] intensidades: list[float] = [] palavras = fala.texto_normalizado.split() # 1. Marcadores explícitos de recomeço no início. if palavras and _RE_MARCADOR.match(palavras[0]): evidencias.append("marcador explícito de recomeço") intensidades.append(0.9) if anterior is None: if intensidades: return SinalDeReinicio(fala.id, "reinicio_explicito", round(max(intensidades), 3), evidencias) return None # 2. Pausa longa antes da fala. pausa = fala.inicio - anterior.fim if pausa >= self.pausa_longa: evidencias.append(f"pausa de {pausa:.1f} segundos") intensidades.append(min(1.0, 0.5 + pausa / 8.0)) # 3. Repetição do início da frase anterior. prefixo = self.comparador.prefixo_comum_em_palavras(anterior.texto, fala.texto) if prefixo >= 3: evidencias.append(f"repetição das primeiras {prefixo} palavras") intensidades.append(min(1.0, 0.4 + prefixo * 0.08)) if not evidencias: return None return SinalDeReinicio( fala_id=fala.id, tipo="repeticao_do_inicio" if any("repetição" in e for e in evidencias) else "reinicio_pos_pausa", intensidade=round(min(1.0, max(intensidades)), 3), evidencias=evidencias, )