from dataclasses import asdict, dataclass import json from pathlib import Path from typing import Any, Callable from ..integracoes.midia import ExtracaoDeAudio from .modelos import SegmentoDeTranscricao @dataclass(frozen=True) class TranscricaoDoClipe: identificador_do_clipe: str arquivo: str inicio_na_timeline: float fim_na_timeline: float segmentos: list[SegmentoDeTranscricao] @property def texto(self) -> str: return " ".join(s.texto for s in self.segmentos if s.texto).strip() class TranscricaoDaTimeline: """Transcreve somente os intervalos efetivamente usados na timeline.""" def __init__(self, provider: Any, extrator: ExtracaoDeAudio | None = None, diretoria_de_trabalho: str | Path = ".transcricao") -> None: self.provider = provider self.extrator = extrator or ExtracaoDeAudio() self.diretoria_de_trabalho = Path(diretoria_de_trabalho) def executar(self, timeline: Any) -> list[TranscricaoDoClipe]: resultados: list[TranscricaoDoClipe] = [] for faixa in timeline.faixas: for clipe in faixa.clipes: if not clipe.arquivo or clipe.offline: continue intervalo = clipe.intervalo_na_timeline pasta = self.diretoria_de_trabalho / clipe.identificador origem = clipe.intervalo_na_origem partes = self.extrator.extrair_intervalo( clipe.arquivo, pasta, origem.inicio if origem else 0.0, origem.fim if origem else None, ) segmentos: list[SegmentoDeTranscricao] = [] for parte in partes: for segmento in self.provider.transcrever(type("Audio", (), {"arquivo": str(parte.caminho)})()): base_origem = origem.inicio if origem else 0.0 inicio = max(intervalo.inicio, intervalo.inicio + (parte.inicio - base_origem) + segmento.inicio) fim = min(intervalo.fim, intervalo.inicio + (parte.inicio - base_origem) + segmento.fim) if inicio < intervalo.fim and fim > inicio: segmentos.append(SegmentoDeTranscricao(inicio, fim, segmento.texto, segmento.confianca)) resultados.append(TranscricaoDoClipe(clipe.identificador, clipe.arquivo, intervalo.inicio, intervalo.fim, segmentos)) return resultados @staticmethod def gerar_relatorio(resultados: list[TranscricaoDoClipe], destino: str | Path) -> Path: caminho = Path(destino) dados = [{**asdict(item), "segmentos": [asdict(s) for s in item.segmentos], "texto": item.texto} for item in resultados] caminho.write_text(json.dumps(dados, ensure_ascii=False, indent=2), encoding="utf-8") return caminho