feat: criado monitoramento contínuo de trilhas com varredura recur

- criado monitoramento contínuo de trilhas com varredura recursiva e baixa prioridade
- gerado e validado plano editorial revisável do depoimento da Erika sem aplicação na timeline
- adicionada leitura e comparação estrutural da timeline após aplicar planos de edição
- limitadas as classificações de trilhas às duas maiores probabilidades de cada categoria
- limpo o catálogo musical para reiniciar as análises sem remover dados de vídeo

Resumo:
- 34 arquivos alterados
- 6 novos
- 28 modificados
- 0 removidos

 28 files changed, 833 insertions(+), 75 deletions(-)

Arquivos:
  - .jhonny/analises.db
  - code/cep-plugin/index.html
  - code/cep-plugin/main.js
  - code/engine/analisar_trilhas.py
  - code/engine/aplicar_plano_de_edicao.py
  - code/engine/consultar_detalhes_de_trilha.py
  - code/engine/editor/__init__.py
  - code/engine/editor/aplicador_de_plano_de_edicao.py
  - code/engine/editor/backup_de_sequencia.py
  - code/engine/editor/escrita/escrita_no_editor.py
  - code/engine/editor/modelos.py
  - code/engine/editor/validacao_semantica.py
  - code/engine/integracoes/audio/classificador_de_musica_essentia.py
  - code/engine/integracoes/audio/modelos_de_analise_musical.py
  - code/engine/integracoes/audio/provider_de_analise_musical_essentia.py
  - code/engine/persistencia/esquema.py
  - code/engine/persistencia/repositorio_de_trilhas.py
  - code/engine/testes/duplos_de_premiere.py
  - code/engine/testes/test_aplicador_de_plano_de_edicao.py
  - code/engine/testes/test_aplicar_plano_de_edicao.py
  - code/engine/testes/test_escrita_no_editor.py
  - code/engine/testes/test_leitor_de_plano_de_edicao.py
  - code/engine/testes/test_validador_semantico_de_plano.py
  - code/plugins/premiere-pro/skills/editar-por-voz/SKILL.md
  - code/plugins/premiere-pro/skills/editar-por-voz/criterios/08-formato-de-saida.md
  - code/plugins/premiere-pro/skills/editar-por-voz/criterios/10-revisao-humana.md
  - code/src/tools/timeline.ts
  - code/tests/tools/tool-modules.test.ts
  - .jhonny/planos/
  - code/.jhonny/analises.db-shm
  - code/.jhonny/analises.db-wal
  - code/engine/editor/verificador_da_aplicacao.py
  - code/engine/testes/test_verificador_da_aplicacao.py
  - code/plugins/premiere-pro/skills/editar-por-voz/criterios/11-gancho.md
This commit is contained in:
João Henrique
2026-09-10 15:09:27 -04:00
parent da400de7d3
commit 2c9bdf2ff0
34 changed files with 1179 additions and 75 deletions
+40 -1
View File
@@ -5,7 +5,8 @@ têm posição na timeline diferente da posição no arquivo de origem — o mes
descompasso encontrado no projeto real entre ``inicio_na_timeline`` e
``inicio_na_origem`` do banco de análises. Implementa só as ferramentas MCP
que o módulo ``engine.editor`` usa: ``get_active_sequence``, ``split_clip``,
``remove_from_timeline``, ``remove_linked_from_timeline``, ``set_clip_properties`` e ``add_marker``.
``remove_from_timeline``, ``remove_linked_from_timeline``,
``duplicate_linked_range_to_start``, ``set_clip_properties`` e ``add_marker``.
"""
from __future__ import annotations
@@ -100,6 +101,7 @@ class ClienteMCPFalso(ClienteMCP):
"split_clip": self._simular_split_clip,
"remove_from_timeline": self._simular_ripple_delete,
"remove_linked_from_timeline": self._simular_remocao_vinculada,
"duplicate_linked_range_to_start": self._simular_gancho_vinculado_no_inicio,
"set_clip_properties": self._simular_set_clip_properties,
"add_marker": self._simular_add_marker,
"undo": self._simular_undo,
@@ -223,6 +225,43 @@ class ClienteMCPFalso(ClienteMCP):
self._simular_ripple_delete({"node_id": identificador, "ripple": True})
return {"removed": True, "verified": True}
def _simular_gancho_vinculado_no_inicio(self, argumentos: dict[str, Any]) -> dict[str, Any]:
"""Duplica um par isolado no início e preserva sua ocorrência original."""
identificadores = argumentos["node_ids"]
encontrados: list[tuple[str, _ClipeFalso]] = []
for identificador_da_faixa, clipes in self._faixas.items():
for clipe in clipes:
if clipe.identificador in identificadores:
encontrados.append((identificador_da_faixa, clipe))
if len(encontrados) != 2 or {faixa.split("_")[0] for faixa, _ in encontrados} != {"video", "audio"}:
raise ErroDeFerramentaMCP("O gancho exige um par de vídeo e áudio existente.")
inicios = {round(clipe.inicio_na_timeline, 6) for _, clipe in encontrados}
fins = {round(clipe.fim_na_timeline, 6) for _, clipe in encontrados}
if len(inicios) != 1 or len(fins) != 1:
raise ErroDeFerramentaMCP("O par não ocupa o mesmo intervalo.")
self._salvar_estado()
inicio_na_origem = float(argumentos["source_in_seconds"])
fim_na_origem = float(argumentos["source_out_seconds"])
duracao = fim_na_origem - inicio_na_origem
novos_ids: list[str] = []
for identificador_da_faixa, clipe in encontrados:
faixa = self._faixas[identificador_da_faixa]
for outro in faixa:
outro.inicio_na_timeline += duracao
outro.fim_na_timeline += duracao
novo = self._novo_clipe(
clipe.nome,
0.0,
duracao,
inicio_na_origem,
fim_na_origem,
)
faixa.append(novo)
faixa.sort(key=lambda item: item.inicio_na_timeline)
novos_ids.append(novo.identificador)
return {"duplicated": True, "verified": True, "insertedNodeIds": novos_ids}
def _simular_set_clip_properties(self, argumentos: dict[str, Any]) -> dict[str, Any]:
"""Aceita a alteração de propriedades sem simular geometria (não é usada pelos testes)."""
del argumentos