feat: initial commit - Jhonny Editor

- Adicionado estrutura completa do projeto
- Configurado MCP server para Premiere Pro
- Adicionado documentação e skills
- Configurado Gitignore para o projeto
This commit is contained in:
João Henrique
2026-09-08 09:59:31 -04:00
commit b541f502ba
1507 changed files with 387650 additions and 0 deletions
@@ -0,0 +1,5 @@
from .conversor_de_timeline import ConversorDeTimeline
from .conversor_de_faixas import ConversorDeFaixas
from .conversor_de_clipes import ConversorDeClipes
__all__ = ["ConversorDeTimeline", "ConversorDeFaixas", "ConversorDeClipes"]
@@ -0,0 +1,26 @@
from typing import Any
from ....dominio import Clipe, IntervaloDeTempo
from ....scanner.modelos import ErroDeAnalise
class ConversorDeClipes:
def converter(self, dados: dict[str, Any], identificador_da_faixa: str, indice: int = 0) -> Clipe:
inicio = dados.get("start", dados.get("timeline_start"))
fim = dados.get("end", dados.get("timeline_end"))
identificador = dados.get("nodeId", dados.get("id"))
if identificador is None or inicio is None or fim is None:
raise ErroDeAnalise("resposta_incompleta", "Clipe sem identificador ou intervalo obrigatório.",
f"clipes[{indice}]", {"campos": list(dados)})
try:
intervalo = IntervaloDeTempo(float(inicio), float(fim))
origem_inicio = dados.get("inPoint", dados.get("source_start"))
origem_fim = dados.get("outPoint", dados.get("source_end"))
origem = (IntervaloDeTempo(float(origem_inicio), float(origem_fim))
if origem_inicio is not None and origem_fim is not None else None)
except (TypeError, ValueError) as exc:
raise ErroDeAnalise("intervalo_invalido", str(exc), f"clipes[{indice}]") from exc
return Clipe(str(identificador), str(dados.get("name", "")), intervalo, origem,
dados.get("sourceFile"), identificador_da_faixa,
bool(dados.get("offline", False)), dict(dados.get("metadata", {})))
@@ -0,0 +1,17 @@
from typing import Any
from ....dominio import Faixa
from .conversor_de_clipes import ConversorDeClipes
class ConversorDeFaixas:
def __init__(self, conversor_de_clipes: ConversorDeClipes | None = None) -> None:
self.conversor_de_clipes = conversor_de_clipes or ConversorDeClipes()
def converter(self, dados: dict[str, Any], tipo: str, indice: int) -> Faixa:
identificador = str(dados.get("id", f"{tipo}_{indice}"))
faixa = Faixa(identificador, str(dados.get("name", "")), tipo,
int(dados.get("index", indice)))
faixa.clipes = [self.conversor_de_clipes.converter(clipe, identificador, i)
for i, clipe in enumerate(dados.get("clips", []))]
return faixa
@@ -0,0 +1,30 @@
from typing import Any
from ....dominio import Timeline
from .conversor_de_faixas import ConversorDeFaixas
class ConversorDeTimeline:
"""Converte a resposta externa do MCP em objetos do domínio."""
def __init__(self, conversor_de_faixas: ConversorDeFaixas | None = None) -> None:
self.conversor_de_faixas = conversor_de_faixas or ConversorDeFaixas()
def converter(self, dados_brutos: dict[str, Any]) -> Timeline:
if not isinstance(dados_brutos, dict) or dados_brutos.get("id") is None:
from ....scanner.modelos import ErroDeAnalise
raise ErroDeAnalise("timeline_invalida", "A timeline precisa de um identificador.", "timeline.id")
timeline = Timeline(
identificador=str(dados_brutos["id"]),
nome=str(dados_brutos.get("name", "")),
duracao=dados_brutos.get("duration"),
taxa_de_quadros=dados_brutos.get("frameRate"),
largura=dados_brutos.get("frameSizeHorizontal"),
altura=dados_brutos.get("frameSizeVertical"),
)
faixas_de_video = dados_brutos.get("videoTracks", dados_brutos.get("video_tracks", []))
faixas_de_audio = dados_brutos.get("audioTracks", dados_brutos.get("audio_tracks", []))
for tipo, faixas in (("video", faixas_de_video), ("audio", faixas_de_audio)):
timeline.faixas.extend(self.conversor_de_faixas.converter(f, tipo, i)
for i, f in enumerate(faixas))
return timeline