feat: criada a aba Análises no painel CEP para ler do banco (anali

- criada a aba Análises no painel CEP para ler do banco (analises.db) e copiar/abrir o J-SOM de som (transcrição por cena) e o de imagem (evidências visuais), com novo módulo engine/gerar_relatorio_de_analises.py e testes
- criado o módulo engine/editor (leitura do plano de edição em JSON, tradução de tempos de origem para a timeline ativa e aplicação de cortes/zooms/marcadores no Premiere via MCP) e o ponto de entrada engine/aplicar_plano_de_edicao.py, com testes; corrigido engine/integracoes/premiere/cliente_mcp.py para levantar os erros específicos já declarados em erros_mcp.py em vez de RuntimeError genérico

Resumo:
- 15 arquivos alterados
- 8 novos
- 5 modificados
- 2 removidos

 7 files changed, 172 insertions(+), 8 deletions(-)

Arquivos:
  - .jhonny/analises.db
  - .jhonny/analises.db-shm
  - .jhonny/analises.db-wal
  - code/cep-plugin/index.html
  - code/cep-plugin/main.js
  - code/cep-plugin/styles.css
  - code/engine/integracoes/premiere/cliente_mcp.py
  - code/engine/aplicar_plano_de_edicao.py
  - code/engine/editor/
  - code/engine/gerar_relatorio_de_analises.py
  - code/engine/testes/duplos_de_premiere.py
  - code/engine/testes/test_aplicador_de_plano_de_edicao.py
  - code/engine/testes/test_gerar_relatorio_de_analises.py
  - code/engine/testes/test_leitor_de_plano_de_edicao.py
  - code/engine/testes/test_mapeador_de_tempo.py
This commit is contained in:
João Henrique
2026-09-08 19:35:30 -04:00
parent 400c3c93dd
commit 4308c72441
24 changed files with 1591 additions and 8 deletions
+5
View File
@@ -0,0 +1,5 @@
"""Escrita de mutações na sequência ativa do Premiere."""
from .escrita_no_editor import EscritaNoEditor
__all__ = ["EscritaNoEditor"]
@@ -0,0 +1,91 @@
"""Escrita de mutações na sequência ativa do Premiere via MCP.
Isola o nome das ferramentas MCP e o formato de argumentos externos
(``split_clip``, ``remove_from_timeline``, ``set_clip_properties``,
``add_marker``) do resto do domínio. Quem chama esta classe fala só em
segundos de timeline, identificador de clipe e fator de escala — nunca em
nomes de ferramenta ou ticks do Premiere.
"""
from __future__ import annotations
from ...integracoes.premiere.cliente_mcp import ClienteMCP
from ...integracoes.premiere.erros_mcp import ErroDeFerramentaMCP
from ..erros import ErroDeEscritaNoEditor
_CORES_POR_NOME = {
"revisar": 3, # laranja: chama atenção sem parecer um erro (vermelho)
"informar": 5, # branco: marcador neutro
}
class EscritaNoEditor:
"""Aplica, uma de cada vez, as mutações que o aplicador de plano decide fazer."""
def __init__(self, cliente_mcp: ClienteMCP) -> None:
self.cliente_mcp = cliente_mcp
def dividir_clipe_se_necessario(self, instante_da_timeline: float, indice_da_faixa: int, tipo_da_faixa: str) -> bool:
"""Corta, na timeline, o clipe que cobrir ``instante_da_timeline``.
Devolve ``True`` se um corte novo foi criado e ``False`` quando o
instante já era uma borda de clipe (o Premiere recusa dividir onde
não há clipe atravessando o ponto) — esse segundo caso não é um erro,
é o resultado esperado quando o corte pedido coincide com um corte já
existente da análise de cenas.
"""
try:
self.cliente_mcp.chamar(
"split_clip",
{"time_seconds": instante_da_timeline, "track_index": indice_da_faixa, "track_type": tipo_da_faixa},
)
return True
except ErroDeFerramentaMCP:
return False
def remover_trecho(self, identificador_do_clipe: str) -> None:
"""Remove o clipe da timeline, fechando o espaço deixado (ripple).
Levanta :class:`ErroDeEscritaNoEditor` se o Premiere recusar a
remoção.
"""
try:
self.cliente_mcp.chamar("remove_from_timeline", {"node_id": identificador_do_clipe, "ripple": True})
except ErroDeFerramentaMCP as erro:
raise ErroDeEscritaNoEditor(f"Não foi possível remover o clipe {identificador_do_clipe!r}: {erro}") from erro
def aplicar_zoom(self, identificador_do_clipe: str, fator_de_escala: float) -> None:
"""Aplica um punch-in no clipe, escalando-o por ``fator_de_escala`` (1.0 = tamanho original).
Levanta :class:`ErroDeEscritaNoEditor` se o Premiere recusar a
alteração.
"""
try:
self.cliente_mcp.chamar(
"set_clip_properties", {"node_id": identificador_do_clipe, "scale": fator_de_escala * 100}
)
except ErroDeFerramentaMCP as erro:
raise ErroDeEscritaNoEditor(
f"Não foi possível aplicar zoom no clipe {identificador_do_clipe!r}: {erro}"
) from erro
def adicionar_marcador(self, instante_da_timeline: float, nome: str, comentario: str) -> None:
"""Cria um marcador de sequência em ``instante_da_timeline``.
Levanta :class:`ErroDeEscritaNoEditor` se o Premiere recusar a
criação do marcador.
"""
try:
self.cliente_mcp.chamar(
"add_marker",
{
"time_seconds": instante_da_timeline,
"name": nome,
"comments": comentario,
"color": _CORES_POR_NOME["revisar"],
},
)
except ErroDeFerramentaMCP as erro:
raise ErroDeEscritaNoEditor(
f"Não foi possível adicionar o marcador em {instante_da_timeline}s: {erro}"
) from erro