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
@@ -78,9 +78,24 @@ class RepositorioDeTrilhasSQLite:
(trilha_id,),
)
def reabrir_analises_sem_etiquetas(self, pasta_id: int | None = None) -> None:
"""Volta a enfileirar análises antigas que não têm classificação semântica."""
filtro = "" if pasta_id is None else " AND t.pasta_id = ?"
parametros = () if pasta_id is None else (pasta_id,)
with self.conexao:
self.conexao.execute(
"""UPDATE trilhas_musicais AS t SET status = 'aguardando', erro = NULL
WHERE t.status = 'concluida' AND EXISTS (
SELECT 1 FROM analises_musicais AS a
WHERE a.trilha_id = t.id
AND NOT EXISTS (SELECT 1 FROM etiquetas_musicais e WHERE e.analise_id = a.id)
)""" + filtro,
parametros,
)
def registrar_analise(self, trilha: TrilhaMusical, resultado: ResultadoDaAnaliseMusical) -> None:
"""Grava descritores e etiquetas produzidos pelo áudio da trilha."""
bruto = json.dumps({"generos": resultado.generos, "humores": resultado.humores}, ensure_ascii=False)
bruto = json.dumps({"generos": resultado.generos, "humores": resultado.humores, "temas": resultado.temas, "instrumentos": resultado.instrumentos, "etiquetas": resultado.etiquetas}, ensure_ascii=False)
with self.conexao:
self.conexao.execute(
"UPDATE trilhas_musicais SET hash_do_conteudo = ?, status = 'concluida', erro = NULL, atualizada_em = strftime('%Y-%m-%dT%H:%M:%fZ','now') WHERE id = ?",
@@ -88,14 +103,14 @@ class RepositorioDeTrilhasSQLite:
)
cursor = self.conexao.execute(
"""INSERT INTO analises_musicais
(trilha_id, provedor, modelo, duracao_em_segundos, batidas_por_minuto, tonalidade, modo, intensidade, dancabilidade, resultado_bruto_json)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)""",
(trilha_id, provedor, modelo, duracao_em_segundos, batidas_por_minuto, tonalidade, modo, intensidade, dancabilidade, temas_json, instrumentos_json, etiquetas_json, resultado_bruto_json)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)""",
(trilha.identificador, resultado.provedor, resultado.modelo, resultado.duracao_em_segundos,
resultado.batidas_por_minuto, resultado.tonalidade, resultado.modo, resultado.intensidade,
resultado.dancabilidade, bruto),
resultado.dancabilidade, json.dumps(resultado.temas, ensure_ascii=False), json.dumps(resultado.instrumentos, ensure_ascii=False), json.dumps(resultado.etiquetas, ensure_ascii=False), bruto),
)
analise_id = cursor.lastrowid
for tipo, etiquetas in (("genero", resultado.pontuacoes_de_genero), ("humor", resultado.pontuacoes_de_humor)):
for tipo, etiquetas in (("genero", resultado.pontuacoes_de_genero), ("humor", resultado.pontuacoes_de_humor), ("tema", resultado.pontuacoes_de_tema)):
self.conexao.executemany(
"INSERT INTO etiquetas_musicais(analise_id, tipo, etiqueta, confianca, ordem) VALUES (?, ?, ?, ?, ?)",
((analise_id, tipo, item.etiqueta, item.confianca, ordem) for ordem, item in enumerate(etiquetas)),