diff --git a/.jhonny/analises.db b/.jhonny/analises.db index 6a1bbcf..f3b048d 100644 Binary files a/.jhonny/analises.db and b/.jhonny/analises.db differ diff --git a/code/cep-plugin/index.html b/code/cep-plugin/index.html index f13a9d6..19368f6 100755 --- a/code/cep-plugin/index.html +++ b/code/cep-plugin/index.html @@ -82,9 +82,15 @@
-

Siga os passos de cima para baixo. Cada passo libera o seguinte.

+

A edição usa a análise já concluída pelo Scanner. Revise os dados, gere o plano JSON e aplique-o na timeline.

-
+
+

Análise do Scanner

Não carregada
+

Carregue a análise mais recente do Scanner antes de gerar o plano de edição.

+ +
+ +
@@ -109,7 +115,7 @@
-
+
diff --git a/code/cep-plugin/main.js b/code/cep-plugin/main.js index e8a114c..8d89d3e 100755 --- a/code/cep-plugin/main.js +++ b/code/cep-plugin/main.js @@ -2025,6 +2025,93 @@ var silenceState = { speakerTurns: [], }; +function silenceLocalizarUltimoRelatorioDoScanner() { + var raiz = scannerOutputRoot(); + var candidatos = []; + try { + fs.readdirSync(raiz).forEach(function (nomeDaPasta) { + var pasta = path.join(raiz, nomeDaPasta); + var relatorio = path.join(pasta, nomeDaPasta + "-resultado.json"); + if (fs.existsSync(relatorio)) candidatos.push(relatorio); + }); + } catch (_) {} + candidatos.sort(function (a, b) { + try { return fs.statSync(b).mtimeMs - fs.statSync(a).mtimeMs; } catch (_) { return 0; } + }); + return candidatos[0] || null; +} + +function silenceConverterRelatorioDoScannerParaTranscricao(caminhoDoRelatorio, dadosDoRelatorio) { + var segmentos = []; + (dadosDoRelatorio.artefatos && dadosDoRelatorio.artefatos.audio || []).forEach(function (nomeDoArquivo) { + var caminhoDoAudio = path.join(path.dirname(caminhoDoRelatorio), nomeDoArquivo); + if (!fs.existsSync(caminhoDoAudio)) return; + var dadosDoAudio; + try { dadosDoAudio = JSON.parse(fs.readFileSync(caminhoDoAudio, "utf-8")); } catch (_) { return; } + (dadosDoAudio.segmentos_por_clipe || []).forEach(function (grupo) { + (grupo.segmentos || []).forEach(function (segmento) { + segmentos.push({ + start: Number(segmento.inicio), end: Number(segmento.fim), + inicio: Number(segmento.inicio), fim: Number(segmento.fim), + text: segmento.texto || "", texto: segmento.texto || "", + confidence: segmento.confianca, confianca: segmento.confianca, + speaker: segmento.falante, falante: segmento.falante, + caracteristicas_acusticas: segmento.caracteristicas_acusticas || {}, + words: segmento.palavras || [], palavras: segmento.palavras || [], + }); + }); + }); + }); + segmentos.sort(function (a, b) { return a.start - b.start; }); + return { version: 1, segments: segmentos, origem: "scanner" }; +} + +function silenceLoadScannerAnalysis() { + var status = document.getElementById("scannerAnalysisStatus"); + var info = document.getElementById("scannerAnalysisInfo"); + setBusy("btnLoadScannerAnalysis", true); + var caminhoDoRelatorio = silenceLocalizarUltimoRelatorioDoScanner(); + if (!caminhoDoRelatorio) { + setBusy("btnLoadScannerAnalysis", false); + status.textContent = "Não encontrada"; + info.textContent = "Execute o Scanner primeiro para criar uma análise reutilizável."; + showToast("err", info.textContent); + return; + } + try { + var dadosDoRelatorio = JSON.parse(fs.readFileSync(caminhoDoRelatorio, "utf-8")); + var sequencia = dadosDoRelatorio.sequencia || {}; + silenceState.sequenceId = sequencia.id || null; + silenceState.sequenceName = sequencia.nome || path.basename(caminhoDoRelatorio); + silenceState.mediaPath = null; + silenceState.fileBaseName = path.basename(path.dirname(caminhoDoRelatorio)); + silenceState.outputDir = path.dirname(caminhoDoRelatorio); + silenceState.transcriptPath = path.join(silenceState.outputDir, "transcricao-do-scanner.json"); + silenceState.cachedTranscriptPath = null; + fs.writeFileSync(silenceState.transcriptPath, JSON.stringify( + silenceConverterRelatorioDoScannerParaTranscricao(caminhoDoRelatorio, dadosDoRelatorio), null, 2), "utf-8"); + var transcricao = JSON.parse(fs.readFileSync(silenceState.transcriptPath, "utf-8")); + var quantidade = transcricao.segments.length; + status.textContent = "Carregada"; + info.textContent = silenceState.sequenceName + " · " + quantidade + " trecho(s) vindos do Scanner."; + setStep(3, "ready", "Pronto"); + setStep(4, "ready", "Pronto"); + setStep(5, "locked", "Bloqueado"); + document.getElementById("btnBuildPlan").disabled = false; + document.getElementById("btnDiarize").disabled = true; + document.getElementById("btnVoiceFeatures").disabled = true; + document.getElementById("silenceDiarizeInfo").textContent = "Os falantes disponíveis vieram da análise do Scanner."; + document.getElementById("silenceVoiceFeaturesInfo").textContent = "As métricas disponíveis vieram da análise do Scanner."; + silenceLog("Análise do Scanner carregada: " + quantidade + " trecho(s).", "ok"); + showToast("ok", "Análise do Scanner carregada."); + } catch (erro) { + status.textContent = "Erro"; + info.textContent = "Não foi possível ler a análise: " + erro.message; + showToast("err", info.textContent); + } + setBusy("btnLoadScannerAnalysis", false); +} + var speakerAudioPlayer = null; var speakerAudioQueue = null; @@ -3578,9 +3665,12 @@ function downloadModel(model, btn, approxMB) { renderEditorPersonalities(); restaurarConfiguracaoDeLegendas(); - // Passo 1 é o único liberado até o vídeo ser detectado. - setStep(1, "ready", "Comece aqui"); - lockStepsFrom(2); + // A aba Editar vídeo começa com a análise já produzida pelo Scanner. + setStep(1, "locked", "Scanner"); + setStep(2, "locked", "Scanner"); + setStep(3, "ready", "Aguardando análise"); + setStep(4, "locked", "Aguardando análise"); + setStep(5, "locked", "Aguardando plano"); log("MCP for Adobe Premiere Pro CEP connector loaded"); setStatus("waiting", "Aguardando — a ponte está iniciando"); diff --git a/code/cep-plugin/styles.css b/code/cep-plugin/styles.css index e849670..1f28000 100755 --- a/code/cep-plugin/styles.css +++ b/code/cep-plugin/styles.css @@ -175,6 +175,8 @@ h1, h2, h3 { margin: 0; } .scanner-option-row .checkbox-field { flex: 1; } .button-mini { padding: 4px 8px; font-size: 10px; } .editorial-plan-json { width: 100%; min-height: 150px; resize: vertical; box-sizing: border-box; font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 11px; line-height: 1.45; color: var(--text); background: var(--surface); border: 1px solid var(--border); border-radius: 6px; padding: 9px; } +.editar-video-legado { display: none; } +.scanner-analysis-card { margin-bottom: 12px; } /* --------------------- Painel de progresso (task dock) ------------------- */ .task-dock {