- corrigida a reprodução do trecho de áudio do falante na tela Refinar usando os tempos da origem do WAV. - alterado o passo de geração de JSON para concluir a edição e salvar a configuração editorial no banco. Resumo: - 9 arquivos alterados - 3 novos - 6 modificados - 0 removidos 6 files changed, 136 insertions(+), 109 deletions(-) Arquivos: - .jhonny/analises.db - code/cep-plugin/index.html - code/cep-plugin/main.js - code/engine/persistencia/__init__.py - code/engine/persistencia/esquema.py - code/engine/testes/test_persistencia_sqlite.py - code/engine/persistencia/repositorio_de_edicoes.py - code/engine/registrar_edicao.py - code/tests/cep-refinar-preview.test.ts
84 lines
3.1 KiB
Python
84 lines
3.1 KiB
Python
"""Persistência da configuração editorial escolhida no painel CEP.
|
|
|
|
Este módulo registra a conclusão da seleção de um tipo de vídeo e suas opções.
|
|
Ele não executa cortes, não gera o plano da IA e não duplica a análise do
|
|
Scanner; apenas cria o vínculo persistido entre a análise e a edição desejada.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import json
|
|
import sqlite3
|
|
from dataclasses import dataclass
|
|
|
|
|
|
class ErroDeEdicao(ValueError):
|
|
"""Configuração editorial inválida para persistência."""
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
class EdicaoDeVideo:
|
|
"""Representa a configuração editorial concluída para um vídeo."""
|
|
|
|
video_id: str
|
|
sequencia: str
|
|
tipo_de_video: str
|
|
configuracao: dict[str, object]
|
|
origem: str | None = None
|
|
|
|
|
|
class RepositorioDeEdicoes:
|
|
"""Grava configurações editoriais sem alterar os dados da análise."""
|
|
|
|
def __init__(self, conexao: sqlite3.Connection) -> None:
|
|
"""Inicializa o repositório com uma conexão SQLite preparada."""
|
|
self.conexao = conexao
|
|
|
|
def registrar(self, edicao: EdicaoDeVideo) -> int:
|
|
"""Registra uma edição concluída e devolve seu identificador."""
|
|
if not edicao.video_id.strip():
|
|
raise ErroDeEdicao("A edição precisa indicar o vídeo da análise.")
|
|
if not edicao.sequencia.strip():
|
|
raise ErroDeEdicao("A edição precisa indicar a sequência.")
|
|
if not edicao.tipo_de_video.strip():
|
|
raise ErroDeEdicao("A edição precisa indicar o tipo de vídeo.")
|
|
if not edicao.configuracao:
|
|
raise ErroDeEdicao("A edição precisa ter uma configuração.")
|
|
|
|
with self.conexao:
|
|
self.conexao.execute(
|
|
"INSERT OR IGNORE INTO videos (id, nome) VALUES (?, ?)",
|
|
(edicao.video_id, edicao.sequencia),
|
|
)
|
|
cursor = self.conexao.execute(
|
|
"""INSERT INTO edicoes_de_video
|
|
(video_id, sequencia, origem, tipo_de_video, configuracao)
|
|
VALUES (?, ?, ?, ?, ?)""",
|
|
(
|
|
edicao.video_id,
|
|
edicao.sequencia,
|
|
edicao.origem,
|
|
edicao.tipo_de_video,
|
|
json.dumps(edicao.configuracao, ensure_ascii=False),
|
|
),
|
|
)
|
|
return int(cursor.lastrowid)
|
|
|
|
|
|
def edicao_de_dict(dados: dict[str, object]) -> EdicaoDeVideo:
|
|
"""Converte o pedido externo do painel em uma entidade validável."""
|
|
try:
|
|
video_id = str(dados["video_id"])
|
|
sequencia = str(dados["sequencia"])
|
|
tipo_de_video = str(dados["tipo_de_video"])
|
|
configuracao = dados["configuracao"]
|
|
except KeyError as erro:
|
|
raise ErroDeEdicao(f"Campo obrigatório ausente: {erro.args[0]}.") from erro
|
|
if not isinstance(configuracao, dict):
|
|
raise ErroDeEdicao("O campo configuracao precisa ser um objeto.")
|
|
origem = dados.get("origem")
|
|
return EdicaoDeVideo(video_id, sequencia, tipo_de_video, configuracao, str(origem) if origem else None)
|
|
|
|
|
|
__all__ = ["EdicaoDeVideo", "ErroDeEdicao", "RepositorioDeEdicoes", "edicao_de_dict"]
|