feat: integrado o classificador Essentia de gênero e humor ao resu

- integrado o classificador Essentia de gênero e humor ao resultado musical
- reorganizado o fluxo da aba Editar vídeo para revisar o plano antes de aplicar

Resumo:
- 3 arquivos alterados
- 0 novos
- 3 modificados
- 0 removidos

 3 files changed, 32 insertions(+), 21 deletions(-)

Arquivos:
  - code/cep-plugin/index.html
  - code/cep-plugin/main.js
  - code/engine/integracoes/audio/provider_de_analise_musical_essentia.py
This commit is contained in:
João Henrique
2026-09-10 13:36:42 -04:00
parent 5644b42722
commit bb4e7ba663
3 changed files with 32 additions and 21 deletions
+6 -8
View File
@@ -162,13 +162,14 @@
<div class="step-head">
<span class="step-number" aria-hidden="true">2</span>
<div class="step-title">
<h2>Concluir edição</h2>
<p>Salva no banco a análise carregada, o tipo de vídeo e as configurações editoriais escolhidas. O JSON para a IA poderá ser gerado depois, quando necessário.</p>
<h2>Revisar plano de edição</h2>
<p>Carrega do banco o plano criado para esta sequência e mostra as decisões antes da aplicação.</p>
</div>
<span class="step-chip" id="step2Chip">Bloqueado</span>
<span class="step-chip" id="step2Chip">Aguardando plano</span>
</div>
<div class="step-body">
<button id="btnBuildPlan" class="button button-primary" onclick="silenceConcluirEdicao()" type="button" disabled>Concluir edição</button>
<p class="field-help" id="planoResumoEdicao">O plano editorial pendente será carregado automaticamente da sequência selecionada.</p>
<button id="btnBuildPlan" class="button button-primary" onclick="carregarPlanoEditorialSalvo()" type="button" disabled>Carregar plano salvo</button>
<dl class="kv" id="silenceJsonCard" hidden>
<div><dt>Trechos</dt><dd id="jsonSegmentCount">—</dd></div>
<div><dt>Arquivo</dt><dd class="kv-path" id="jsonOutputPath">—</dd></div>
@@ -191,10 +192,7 @@
<span class="step-chip" id="step3Chip">Bloqueado</span>
</div>
<div class="step-body">
<label class="field-label" for="editorialPlanJson">JSON de ações devolvido pela IA</label>
<div class="button-row">
<button type="button" class="button button-ghost" id="btnLoadSavedEditorialPlan" onclick="carregarPlanoEditorialSalvo()" disabled>Carregar plano salvo no banco</button>
</div>
<label class="field-label" for="editorialPlanJson">Plano carregado do banco</label>
<p class="field-help" id="editorialSavedPlanStatus">O plano será lido diretamente do banco da edição concluída.</p>
<textarea id="editorialPlanJson" class="editorial-plan-json" rows="10" spellcheck="false" placeholder='Cole aqui o JSON com source e actions.'></textarea>
<p class="field-help" id="editorialPlanJsonStatus">Cole o plano recebido da IA. O painel valida o formato antes de executar.</p>
+11 -10
View File
@@ -2157,7 +2157,7 @@ function silenceSelecionarTipoVideo() {
if (!tipo) {
document.getElementById("silenceTipoVideoInfo").textContent = "Selecione um tipo cadastrado para continuar.";
setStep(1, "ready", "Selecione um tipo");
setStep(2, "locked", "Selecione o tipo");
setStep(2, "locked", "Aguardando plano");
document.getElementById("btnBuildPlan").disabled = true;
return;
}
@@ -2383,9 +2383,9 @@ function silenceLoadScannerAnalysis() {
info.textContent = silenceState.sequenceName + " · " + quantidade + " trecho(s) · " +
(audioDoBanco.metricas_de_voz_disponiveis ? "métricas disponíveis" : "métricas não realizadas") + " · " +
(audioDoBanco.diarizacao_disponivel ? falantes.length + " falante(s)" : "diarização não realizada");
setStep(2, "locked", "Selecione o tipo");
setStep(1, "ready", "Selecione um tipo");
setStep(3, "locked", "Aguardando conclusão");
setStep(2, "locked", "Aguardando plano");
setStep(1, "ready", "Tipo no Projeto");
setStep(3, "locked", "Aguardando plano");
renderizarTiposDeVideoParaEdicao();
document.getElementById("btnBuildPlan").disabled = true;
// btnDiarize/btnVoiceFeatures/silenceDiarizeInfo/silenceVoiceFeaturesInfo ficavam no
@@ -2711,8 +2711,8 @@ function silenceSelectSequence() {
setStep(1, "done", "Timeline escolhida");
lockStepsFrom(2);
setStep(2, "ready", "Sua vez");
document.getElementById("btnBuildPlan").disabled = false;
setStep(3, "ready", "Carregar plano salvo");
document.getElementById("btnLoadSavedEditorialPlan").disabled = false;
document.getElementById("btnTranscribe").disabled = false;
document.getElementById("silenceJsonCard").hidden = true;
document.getElementById("jsonFileActions").hidden = true;
@@ -2734,7 +2734,7 @@ function lockStepsFrom(first) {
if (first <= 3) planoEditorialIdCarregado = null;
var buttons = {
2: ["btnBuildPlan"],
3: ["btnApplyEditorialActions", "btnLoadSavedEditorialPlan"],
3: ["btnApplyEditorialActions"],
};
for (var n = first; n <= 5; n++) {
setStep(n, "locked", "Bloqueado");
@@ -3316,7 +3316,6 @@ function silenceConcluirEdicao() {
}
setStep(2, "done", "Edição concluída");
setStep(3, "locked", "Aguardando plano da IA");
document.getElementById("btnLoadSavedEditorialPlan").disabled = false;
taskEnd(true, "Edição concluída e salva no banco.");
silenceLog("Edição concluída e salva no banco de análises.", "ok");
showToast("ok", "Edição concluída e salva no banco.");
@@ -3330,14 +3329,14 @@ function carregarPlanoEditorialSalvo() {
showToast("err", "Detecte a sequência antes de carregar o plano.");
return;
}
setBusy("btnLoadSavedEditorialPlan", true);
setBusy("btnBuildPlan", true);
silenceLog("Lendo o plano editorial diretamente do banco…");
runStreamed(
SCANNER_PYTHON_BIN,
[CARREGAR_PLANO_SCRIPT, "--banco", ANALISES_DB_PATH, "--video-id", String(silenceState.sequenceId)],
function (linha) { silenceLog(linha); },
function (codigo, ultimoErro) {
setBusy("btnLoadSavedEditorialPlan", false);
setBusy("btnBuildPlan", false);
if (codigo !== 0) {
silenceLog("Não foi possível carregar o plano salvo.", "err");
showToast("err", ultimoErro || "Nenhum plano salvo encontrado para este vídeo.");
@@ -3348,10 +3347,12 @@ function carregarPlanoEditorialSalvo() {
if (!resposta.ok || !resposta.plano) throw new Error("Resposta inválida do banco.");
planoEditorialIdCarregado = resposta.plano.plano_id;
document.getElementById("editorialPlanJson").value = JSON.stringify(resposta.plano, null, 2);
document.getElementById("planoResumoEdicao").textContent = "Plano " + planoEditorialIdCarregado + " encontrado · " + resposta.plano.actions.length + " ação(ões) · aguardando aprovação.";
document.getElementById("editorialSavedPlanStatus").textContent = "Plano " + planoEditorialIdCarregado + " carregado do banco.";
document.getElementById("editorialPlanJsonStatus").textContent = "Plano salvo no SQLite; pronto para aprovação e aplicação.";
document.getElementById("btnApplyEditorialActions").disabled = false;
setStep(3, "ready", "Plano carregado");
setStep(2, "done", "Plano carregado");
setStep(3, "ready", "Pronto para aplicar");
silenceLog("Plano " + planoEditorialIdCarregado + " carregado diretamente do SQLite.", "ok");
showToast("ok", "Plano salvo carregado.");
} catch (erro) {