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:
@@ -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],
|
||||
}
|
||||
Reference in New Issue
Block a user