- Adicionado estrutura completa do projeto - Configurado MCP server para Premiere Pro - Adicionado documentação e skills - Configurado Gitignore para o projeto
64 lines
2.9 KiB
Python
64 lines
2.9 KiB
Python
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
|