feat: copiada a skill editar-por-voz e seus critérios para as skil
- copiada a skill editar-por-voz e seus critérios para as skills do projeto - adaptada a skill editar-por-voz para usar o banco SQLite como fonte oficial - corrigida a cópia do JSON do tipo de vídeo para priorizar clipboard Unicode - criado carregador único do contexto de edição por voz a partir do SQLite - criada entrada para registrar planos no SQLite e reaproveitar o mesmo plano na aplicação - habilitado carregamento do plano editorial diretamente do SQLite na interface - corrigido o bloqueio visual da etapa de carregamento do plano salvo - configurado carregamento automático do plano salvo após selecionar a sequência - documentada a sequência como raiz de retomada do fluxo de edição - criada a estrutura local para análise de músicas instrumentais com Essentia Resumo: - 22 arquivos alterados - 11 novos - 11 modificados - 0 removidos 11 files changed, 270 insertions(+), 34 deletions(-) Arquivos: - .jhonny/analises.db - CONTEXT.md - code/cep-plugin/index.html - code/cep-plugin/main.js - code/engine/README.md - code/engine/aplicar_plano_de_edicao.py - code/engine/integracoes/audio/__init__.py - code/engine/persistencia/consultas.py - code/engine/requirements-audio.txt - code/engine/testes/test_consultas_de_persistencia.py - code/tests/cep-tipos-video-encoding.test.ts - code/.jhonny/ - code/engine/carregar_plano_de_edicao.py - code/engine/integracoes/audio/contratos.py - code/engine/integracoes/audio/modelos_de_analise_musical.py - code/engine/integracoes/audio/provider_de_analise_musical_essentia.py - code/engine/preparar_edicao_por_voz.py - code/engine/registrar_plano_de_edicao.py - code/engine/testes/test_analisador_de_musica_essentia.py - code/engine/testes/test_carregar_plano_de_edicao.py - code/engine/testes/test_registrar_plano_de_edicao.py - code/plugins/premiere-pro/skills/editar-por-voz/
This commit is contained in:
@@ -135,6 +135,105 @@ class ConsultasDeAnalises:
|
||||
},
|
||||
}
|
||||
|
||||
def consultar_contexto_da_edicao(
|
||||
self,
|
||||
video_id: str | None = None,
|
||||
incluir_palavras: bool = True,
|
||||
) -> dict | None:
|
||||
"""
|
||||
Carrega a edição concluída mais recente e seu contexto editorial.
|
||||
|
||||
Quando ``video_id`` não é informado, seleciona a edição concluída mais
|
||||
recente do banco. O retorno reúne a configuração editorial, o vídeo,
|
||||
os clipes, as falas e o histórico resumido de planos, para que um
|
||||
agente possa iniciar uma edição sem escrever SQL nem procurar arquivos
|
||||
auxiliares.
|
||||
|
||||
Parâmetros:
|
||||
video_id: Restringe a busca a um vídeo quando informado.
|
||||
incluir_palavras: Inclui palavras da transcrição para decisões
|
||||
que dependem de limites precisos.
|
||||
|
||||
Retorna:
|
||||
Contexto completo da edição mais recente, ou None quando não há
|
||||
edição concluída compatível.
|
||||
|
||||
Pode gerar:
|
||||
ErroDeConsultaInvalida: quando ``video_id`` for vazio ou a
|
||||
configuração persistida não for um JSON válido.
|
||||
"""
|
||||
if video_id is not None:
|
||||
self._validar_texto_obrigatorio("video_id", video_id)
|
||||
condicao = "WHERE video_id = ?" if video_id is not None else ""
|
||||
parametros = (video_id,) if video_id is not None else ()
|
||||
edicao = self.conexao.execute(
|
||||
f"""SELECT id, video_id, sequencia, origem, tipo_de_video,
|
||||
configuracao, concluida_em
|
||||
FROM edicoes_de_video
|
||||
{condicao}
|
||||
ORDER BY concluida_em DESC, id DESC
|
||||
LIMIT 1""",
|
||||
parametros,
|
||||
).fetchone()
|
||||
if edicao is None:
|
||||
return None
|
||||
try:
|
||||
configuracao = json.loads(edicao["configuracao"])
|
||||
except (TypeError, json.JSONDecodeError) as erro:
|
||||
raise ErroDeConsultaInvalida(
|
||||
f"A configuração da edição {edicao['id']} não é um JSON válido."
|
||||
) from erro
|
||||
if not isinstance(configuracao, dict):
|
||||
raise ErroDeConsultaInvalida(
|
||||
f"A configuração da edição {edicao['id']} precisa ser um objeto."
|
||||
)
|
||||
|
||||
identificador_do_video = edicao["video_id"]
|
||||
clipes = [
|
||||
dict(linha) for linha in self.conexao.execute(
|
||||
"""SELECT id, faixa_id, nome, inicio_na_timeline, fim_na_timeline,
|
||||
inicio_na_origem, fim_na_origem, arquivo, offline
|
||||
FROM clipes
|
||||
WHERE video_id = ?
|
||||
ORDER BY inicio_na_timeline, id""",
|
||||
(identificador_do_video,),
|
||||
).fetchall()
|
||||
]
|
||||
planos = [
|
||||
dict(linha) for linha in self.conexao.execute(
|
||||
"""SELECT p.id, p.origem, p.tipo_de_video, p.modelo_da_ia,
|
||||
p.intencao, p.criado_em,
|
||||
COUNT(a.id) AS total_de_acoes,
|
||||
(SELECT COUNT(*) FROM aplicacoes_do_plano ap
|
||||
WHERE ap.plano_id = p.id AND ap.sucesso = 1)
|
||||
AS aplicacoes_com_sucesso
|
||||
FROM planos_de_edicao p
|
||||
LEFT JOIN acoes_do_plano a ON a.plano_id = p.id
|
||||
WHERE p.video_id = ?
|
||||
GROUP BY p.id
|
||||
ORDER BY p.criado_em DESC, p.id DESC""",
|
||||
(identificador_do_video,),
|
||||
).fetchall()
|
||||
]
|
||||
return {
|
||||
"edicao": {
|
||||
"id": edicao["id"],
|
||||
"video_id": identificador_do_video,
|
||||
"sequencia": edicao["sequencia"],
|
||||
"origem": edicao["origem"],
|
||||
"tipo_de_video": edicao["tipo_de_video"],
|
||||
"configuracao": configuracao,
|
||||
"concluida_em": edicao["concluida_em"],
|
||||
},
|
||||
"video": self.consultar_resumo_do_video(identificador_do_video),
|
||||
"analise": self.consultar_status_da_analise(identificador_do_video),
|
||||
"clipes": clipes,
|
||||
"falas": self.listar_falas_no_intervalo(
|
||||
identificador_do_video, incluir_palavras=incluir_palavras,
|
||||
),
|
||||
"planos": planos,
|
||||
}
|
||||
|
||||
def listar_intervalos_de_preview_dos_falantes(self, video_id: str) -> list[dict]:
|
||||
"""
|
||||
Lista os intervalos dos falantes convertidos para o arquivo de vídeo.
|
||||
|
||||
Reference in New Issue
Block a user