feat: criado repositório jhonny-editor no Gitea

criado repositório jhonny-editor no Gitea
adicionado script admin/deploy.command com commit automático
atualizado admin/DEV-NOTES.md com template limpo

Resumo:
- 48 arquivos alterados
- 26 novos
- 19 modificados
- 3 removidos

 22 files changed, 658 insertions(+), 568 deletions(-)

Arquivos:
  - AGENTS.md
  - admin/DEV-NOTES.md
  - admin/OpenCut.command
  - admin/commit.command
  - admin/deploy.command
  - admin/update.command
  - code/cep-plugin/index.html
  - code/cep-plugin/main.js
  - code/cep-plugin/styles.css
  - code/engine/ARQUITETURA.md
  - code/engine/arquitetura/README.md
  - code/engine/gerar_relatorio_timeline.py
  - code/engine/integracoes/apple_speech/apple_speech_transcriber.swift
  - code/engine/integracoes/apple_speech/provider_de_transcricao_apple.py
  - code/engine/integracoes/midia/__init__.py
  - code/engine/integracoes/whisper/provider_de_transcricao_local.py
  - code/engine/scanner/__init__.py
  - code/engine/scanner/coordenacao/__init__.py
  - code/engine/scanner/descoberta/__init__.py
  - code/engine/scanner/modelos.py
  - code/engine/scanner/transcricao_da_timeline.py
  - code/src/tools/discovery.ts
  - :memory:.ses
  - admin/Jhonny.command
  - admin/inativos/OpenCut.command
  - admin/inativos/update.command
  - code/docs/glossario-analise-emocional.md
  - code/docs/levantamento-apple-vision-e-apple-intelligence.md
  - code/docs/levantamento-ferramentas-analise-visual-local.md
  - code/engine/arquitetura/biblioteca-inteligente-de-videos.md
  - code/engine/executar_scanner.py
  - code/engine/integracoes/huggingface/
  - code/engine/integracoes/midia/extracao_de_metadados.py
  - code/engine/integracoes/visual/
  - code/engine/requirements-visual.txt
  - code/engine/scanner/configuracao_visual.py
  - code/engine/scanner/descoberta/descoberta_de_arquivos.py
  - code/engine/scanner/metadados.py
  - code/engine/scanner/relatorio_visual.py
  - code/engine/scanner/retakes/
  - code/engine/scanner/visual.py
  - code/engine/testes/test_analise_visual_local.py
  - code/engine/testes/test_arquivos_e_metadados.py
  - code/engine/testes/test_provider_de_transcricao_apple.py
  - code/relatorios/analise-brools/
  - code/relatorios/analise-visual/
  - code/relatorios/audio/arquivos/
  - code/relatorios/transcricao-timeline.md
This commit is contained in:
João Henrique
2026-09-08 16:13:27 -04:00
parent b541f502ba
commit b9bf3b2863
76 changed files with 16147 additions and 322 deletions
+79
View File
@@ -0,0 +1,79 @@
"""Exportação estruturada de uma leitura visual de clipe."""
from collections import defaultdict
from dataclasses import asdict
from datetime import datetime, timezone
import json
from pathlib import Path
from ..dominio import Clipe
from .visual import ResultadoVisualDoClipe
VERSAO_DO_RELATORIO_VISUAL = "1.0"
def gerar_relatorio_visual(clipe: Clipe, resultado: ResultadoVisualDoClipe,
destino: str | Path, intervalo_de_amostragem: float) -> Path:
"""Grava um JSON autocontido, com fatos por frame e fatos temporais separados."""
if intervalo_de_amostragem <= 0:
raise ValueError("intervalo_de_amostragem deve ser positivo.")
caminho = Path(destino)
caminho.parent.mkdir(parents=True, exist_ok=True)
caminho.write_text(json.dumps(_dados_do_relatorio(clipe, resultado, intervalo_de_amostragem),
ensure_ascii=False, indent=2), encoding="utf-8")
return caminho
def gerar_resumo_visual_markdown(clipe: Clipe, resultado: ResultadoVisualDoClipe,
destino: str | Path, intervalo_de_amostragem: float) -> Path:
"""Grava uma visão humana do mesmo resultado exportado em JSON."""
caminho = Path(destino)
caminho.parent.mkdir(parents=True, exist_ok=True)
dados = _dados_do_relatorio(clipe, resultado, intervalo_de_amostragem)
linhas = [f"# Relatório visual — {clipe.nome}", "",
f"- Clipe: `{clipe.identificador}`",
f"- Origem: `{clipe.arquivo}`",
f"- Timeline: {clipe.intervalo_na_timeline.inicio:.3f}s–{clipe.intervalo_na_timeline.fim:.3f}s",
f"- Amostragem: a cada {intervalo_de_amostragem:g} segundo(s)", "",
"## Observações por frame", ""]
for frame in dados["observacoes_por_frame"]:
tipos = ", ".join(item["tipo"] for item in frame["evidencias"])
linhas.extend([f"### Origem {frame['timestamp_na_origem']:.3f}s", "", tipos or "Sem evidências.", ""])
linhas.extend(["## Continuidade", ""])
for evidencia in dados["evidencias_temporais"]:
linhas.append(f"- {evidencia['tipo']}: {evidencia['inicio']:.3f}s–{evidencia['fim']:.3f}s — "
f"`{json.dumps(evidencia['valor'], ensure_ascii=False)}`")
caminho.write_text("\n".join(linhas) + "\n", encoding="utf-8")
return caminho
def _dados_do_relatorio(clipe: Clipe, resultado: ResultadoVisualDoClipe,
intervalo_de_amostragem: float) -> dict:
por_frame = defaultdict(list)
temporais = []
for evidencia in resultado.evidencias:
item = asdict(evidencia)
if evidencia.inicio == evidencia.fim:
por_frame[evidencia.inicio].append(item)
else:
temporais.append(item)
origem = clipe.intervalo_na_origem
return {
"versao": VERSAO_DO_RELATORIO_VISUAL,
"gerado_em": datetime.now(timezone.utc).isoformat(),
"clipe": {
"identificador": clipe.identificador,
"nome": clipe.nome,
"arquivo_original": clipe.arquivo,
"intervalo_na_timeline": asdict(clipe.intervalo_na_timeline),
"intervalo_na_origem": asdict(origem) if origem else None,
},
"amostragem": {"intervalo_em_segundos": intervalo_de_amostragem},
"observacoes_por_frame": [
{"timestamp_na_origem": timestamp, "evidencias": evidencias}
for timestamp, evidencias in sorted(por_frame.items())
],
"evidencias_temporais": temporais,
"cenas": [asdict(cena) for cena in resultado.cenas_visuais],
}