feat: sincronizado o estado de transcrição, métricas e diarização
- sincronizado o estado de transcrição, métricas e diarização entre SQLite, Scanner e Editar vídeo Resumo: - 6 arquivos alterados - 1 novos - 5 modificados - 0 removidos 5 files changed, 181 insertions(+), 12 deletions(-) Arquivos: - code/cep-plugin/index.html - code/cep-plugin/main.js - code/cep-plugin/styles.css - code/engine/persistencia/consultas.py - code/engine/testes/test_consultas_de_persistencia.py - code/engine/consultar_status_da_analise.py
This commit is contained in:
+123
-9
@@ -266,7 +266,7 @@ function switchTab(name) {
|
||||
if (name === "models") renderModelList();
|
||||
if (name === "silence") { syncTranscribeModelSelect(); syncLanguageInfo(); }
|
||||
if (name === "settings") renderEditorPersonalities();
|
||||
if (name === "scanner") { renderScannerTranscriptionOptions(); loadScannerProfile(); renderScannerHuggingFaceStatus(); }
|
||||
if (name === "scanner") { renderScannerTranscriptionOptions(); loadScannerProfile(); renderScannerHuggingFaceStatus(); scannerListarAnalisesExistentes(); }
|
||||
if (name === "retakes") retakesAoAbrir();
|
||||
if (name === "analises") analisesAoAbrir();
|
||||
if (name === "tipos-video") tiposVideoAoAbrir();
|
||||
@@ -920,6 +920,7 @@ var RETAKES_ENGINE_SCRIPT = "/Volumes/Merongo/SISTEMAS/GENIAL SISTEMAS/Jhonny/co
|
||||
// o `/usr/bin/python3` do macOS (3.9) não aceita. Usar o mesmo venv do projeto
|
||||
// (Python 3.14, com faster_whisper) garante que Scanner e Retakes carreguem bem.
|
||||
var SCANNER_PYTHON_BIN = "/Volumes/Merongo/SISTEMAS/venvs/whisperx-transcricao/bin/python";
|
||||
var ANALISE_STATUS_SCRIPT = "/Volumes/Merongo/SISTEMAS/GENIAL SISTEMAS/Jhonny/code/engine/consultar_status_da_analise.py";
|
||||
var retakesCasoAtual = null;
|
||||
var retakesGrupos = [];
|
||||
var retakesProcesso = null;
|
||||
@@ -1110,6 +1111,7 @@ var scannerTimeline = null;
|
||||
var scannerReportPath = null;
|
||||
var scannerRelatorioExistente = null;
|
||||
var scannerReprocessamentoPendente = false;
|
||||
var scannerAnalisesExistentes = [];
|
||||
var scannerProcesso = null;
|
||||
var scannerCancelSolicitado = false;
|
||||
var SCANNER_ENGINE_SCRIPT = "/Volumes/Merongo/SISTEMAS/GENIAL SISTEMAS/Jhonny/code/engine/executar_scanner.py";
|
||||
@@ -1131,19 +1133,85 @@ function scannerCarregarRelatorioExistente() {
|
||||
} catch (_) { scannerRelatorioExistente = null; }
|
||||
}
|
||||
|
||||
function scannerListarAnalisesExistentes() {
|
||||
var seletor = document.getElementById("scannerExistingAnalysis");
|
||||
var status = document.getElementById("scannerExistingAnalysisStatus");
|
||||
var info = document.getElementById("scannerExistingAnalysisInfo");
|
||||
if (!seletor) return;
|
||||
scannerAnalisesExistentes = [];
|
||||
try {
|
||||
fs.readdirSync(scannerOutputRoot()).forEach(function (nomeDaPasta) {
|
||||
var caminho = path.join(scannerOutputRoot(), nomeDaPasta, nomeDaPasta + "-resultado.json");
|
||||
if (!fs.existsSync(caminho)) return;
|
||||
try {
|
||||
var dados = JSON.parse(fs.readFileSync(caminho, "utf-8"));
|
||||
var estado = silenceConsultarStatusNoBanco((dados.sequencia || {}).id);
|
||||
if (estado) scannerAnalisesExistentes.push({ caminho: caminho, dados: dados, estado: estado });
|
||||
} catch (_) {}
|
||||
});
|
||||
} catch (_) {}
|
||||
scannerAnalisesExistentes.sort(function (a, b) {
|
||||
try { return fs.statSync(b.caminho).mtimeMs - fs.statSync(a.caminho).mtimeMs; } catch (_) { return 0; }
|
||||
});
|
||||
seletor.innerHTML = "";
|
||||
if (!scannerAnalisesExistentes.length) {
|
||||
seletor.innerHTML = "<option value=''>Nenhuma análise carregada</option>";
|
||||
status.textContent = "Nenhuma análise";
|
||||
info.textContent = "Execute o Scanner para criar a primeira análise persistida.";
|
||||
return;
|
||||
}
|
||||
scannerAnalisesExistentes.forEach(function (analise, indice) {
|
||||
var audio = analise.estado.audio || {};
|
||||
var option = document.createElement("option");
|
||||
option.value = String(indice);
|
||||
option.textContent = (analise.dados.sequencia || {}).nome + " · " + audio.total_falas + " falas";
|
||||
seletor.appendChild(option);
|
||||
});
|
||||
seletor.selectedIndex = 0;
|
||||
scannerSelecionarAnaliseExistente();
|
||||
}
|
||||
|
||||
function scannerSelecionarAnaliseExistente() {
|
||||
var seletor = document.getElementById("scannerExistingAnalysis");
|
||||
var analise = scannerAnalisesExistentes[Number(seletor && seletor.value)];
|
||||
var status = document.getElementById("scannerExistingAnalysisStatus");
|
||||
var info = document.getElementById("scannerExistingAnalysisInfo");
|
||||
if (!analise) return;
|
||||
scannerRelatorioExistente = analise.caminho;
|
||||
scannerReportPath = analise.caminho;
|
||||
var audio = analise.estado.audio || {};
|
||||
status.textContent = (audio.metricas_de_voz_disponiveis ? "Métricas prontas" : "Sem métricas") +
|
||||
" · " + (audio.diarizacao_disponivel ? "Diarização pronta" : "Sem diarização");
|
||||
info.textContent = "Transcrição: " + (audio.transcricao_disponivel ? "pronta" : "não encontrada") +
|
||||
" · " + audio.total_falas + " falas · " + (audio.falantes || []).length + " falante(s).";
|
||||
scannerAtualizarComplementos();
|
||||
}
|
||||
|
||||
function scannerAtualizarComplementos() {
|
||||
var relatorio = scannerRelatorioExistente;
|
||||
var arquivoDiarizacao = document.getElementById("btnScannerDiarization");
|
||||
var arquivoMetricas = document.getElementById("btnScannerVoiceFeatures");
|
||||
if (!relatorio) { if (arquivoDiarizacao) arquivoDiarizacao.disabled = true; if (arquivoMetricas) arquivoMetricas.disabled = true; return; }
|
||||
var statusDiarizacao = document.getElementById("scannerDiarizationStatus");
|
||||
var statusMetricas = document.getElementById("scannerVoiceFeaturesStatus");
|
||||
var botaoProcessar = document.getElementById("btnScannerProcess");
|
||||
if (!relatorio) {
|
||||
if (arquivoDiarizacao) arquivoDiarizacao.disabled = true;
|
||||
if (arquivoMetricas) arquivoMetricas.disabled = true;
|
||||
if (statusDiarizacao) statusDiarizacao.textContent = "Ainda não processado";
|
||||
if (statusMetricas) statusMetricas.textContent = "Ainda não processado";
|
||||
return;
|
||||
}
|
||||
var dados = {};
|
||||
try { dados = JSON.parse(fs.readFileSync(relatorio, "utf-8")); } catch (_) {}
|
||||
var transcricao = dados.perfil && dados.perfil.transcricao || {};
|
||||
var audio = dados.artefatos && dados.artefatos.audio || [];
|
||||
var metricas = !!(dados.perfil && dados.perfil.metricas_de_fala) || !!transcricao.metricas_de_fala;
|
||||
var diarizacao = !!transcricao.diarizacao;
|
||||
if (arquivoDiarizacao) { arquivoDiarizacao.disabled = diarizacao || !loadHfToken(); arquivoDiarizacao.textContent = diarizacao ? "Concluído" : "Processar"; }
|
||||
if (arquivoMetricas) { arquivoMetricas.disabled = metricas || !audio.length; arquivoMetricas.textContent = metricas ? "Concluído" : "Processar"; }
|
||||
if (arquivoDiarizacao) arquivoDiarizacao.disabled = true;
|
||||
if (arquivoMetricas) arquivoMetricas.disabled = true;
|
||||
if (statusDiarizacao) { statusDiarizacao.textContent = diarizacao ? "Disponível" : "Não realizada"; statusDiarizacao.dataset.state = diarizacao ? "done" : "pending"; }
|
||||
if (statusMetricas) { statusMetricas.textContent = metricas ? "Disponíveis" : "Não realizadas"; statusMetricas.dataset.state = metricas ? "done" : "pending"; }
|
||||
if (botaoProcessar) { botaoProcessar.disabled = true; botaoProcessar.textContent = "Já processado"; }
|
||||
}
|
||||
|
||||
function scannerSelectedTracks(kind) { return Array.prototype.slice.call(document.querySelectorAll("[data-scanner-track='" + kind + "']:checked")).map(function (item) { return Number(item.value); }).sort(function (a, b) { return a - b; }); }
|
||||
@@ -1245,11 +1313,11 @@ function modelNameFromPath(folder) { var value=String(folder).replace(/.*faster-
|
||||
|
||||
function scannerDetectTracks() {
|
||||
setBusy("btnScannerDetectTracks", true); document.getElementById("scannerTracksHelp").textContent = "Lendo as faixas da sequência ativa…";
|
||||
cs.evalScript("(function(){try{var s=app.project.activeSequence;if(!s)return JSON.stringify({ok:false,error:'Nenhuma sequência ativa.'});function tracks(c,a){for(var i=0;i<c.numTracks;i++){var t=c[i],clips=[];for(var j=0;j<t.clips.numItems;j++){var x=t.clips[j],p=x.projectItem;clips.push({nodeId:x.nodeId,name:x.name,start:Number(x.start.seconds),end:Number(x.end.seconds),inPoint:Number(x.inPoint.seconds),outPoint:Number(x.outPoint.seconds),duration:Number(x.duration.seconds),sourceFile:p&&p.getMediaPath?p.getMediaPath():'',sourceOffline:p&&p.isOffline?p.isOffline():false});}a.push({index:i,name:t.name||('Faixa '+(i+1)),numClips:t.clips.numItems,clips:clips});}}var v=[],a=[];tracks(s.videoTracks,v);tracks(s.audioTracks,a);return JSON.stringify({ok:true,id:s.sequenceID,name:s.name,end:Number(s.end.seconds),videoTracks:v,audioTracks:a});}catch(e){return JSON.stringify({ok:false,error:String(e)});}}())", function(raw) { setBusy("btnScannerDetectTracks", false); var data; try { data=JSON.parse(raw); } catch (_) { data={ok:false,error:"Resposta inválida do Premiere."}; } if (!data.ok) { document.getElementById("scannerTracksHelp").textContent=data.error; showToast("err",data.error); return; } scannerTimeline=data; scannerCarregarRelatorioExistente(); scannerAtualizarComplementos(); var saved; try { saved=JSON.parse(localStorage.getItem(SCANNER_PROFILE_KEY)||"null")||{}; } catch (_) { saved={}; } scannerRenderTracks("video",data.videoTracks,saved.faixas_de_video||data.videoTracks.map(function(t){return t.index;})); scannerRenderTracks("audio",data.audioTracks,saved.faixas_de_audio||[]); document.getElementById("scannerTracksHelp").textContent=data.name+": "+data.videoTracks.length+" faixa(s) de vídeo e "+data.audioTracks.length+" de áudio detectadas."; document.getElementById("btnScannerProcess").disabled=false; });
|
||||
cs.evalScript("(function(){try{var s=app.project.activeSequence;if(!s)return JSON.stringify({ok:false,error:'Nenhuma sequência ativa.'});function tracks(c,a){for(var i=0;i<c.numTracks;i++){var t=c[i],clips=[];for(var j=0;j<t.clips.numItems;j++){var x=t.clips[j],p=x.projectItem;clips.push({nodeId:x.nodeId,name:x.name,start:Number(x.start.seconds),end:Number(x.end.seconds),inPoint:Number(x.inPoint.seconds),outPoint:Number(x.outPoint.seconds),duration:Number(x.duration.seconds),sourceFile:p&&p.getMediaPath?p.getMediaPath():'',sourceOffline:p&&p.isOffline?p.isOffline():false});}a.push({index:i,name:t.name||('Faixa '+(i+1)),numClips:t.clips.numItems,clips:clips});}}var v=[],a=[];tracks(s.videoTracks,v);tracks(s.audioTracks,a);return JSON.stringify({ok:true,id:s.sequenceID,name:s.name,end:Number(s.end.seconds),videoTracks:v,audioTracks:a});}catch(e){return JSON.stringify({ok:false,error:String(e)});}}())", function(raw) { setBusy("btnScannerDetectTracks", false); var data; try { data=JSON.parse(raw); } catch (_) { data={ok:false,error:"Resposta inválida do Premiere."}; } if (!data.ok) { document.getElementById("scannerTracksHelp").textContent=data.error; showToast("err",data.error); return; } scannerTimeline=data; scannerCarregarRelatorioExistente(); scannerAtualizarComplementos(); var saved; try { saved=JSON.parse(localStorage.getItem(SCANNER_PROFILE_KEY)||"null")||{}; } catch (_) { saved={}; } scannerRenderTracks("video",data.videoTracks,saved.faixas_de_video||data.videoTracks.map(function(t){return t.index;})); scannerRenderTracks("audio",data.audioTracks,saved.faixas_de_audio||[]); document.getElementById("scannerTracksHelp").textContent=data.name+": "+data.videoTracks.length+" faixa(s) de vídeo e "+data.audioTracks.length+" de áudio detectadas."; if(!scannerRelatorioExistente){document.getElementById("btnScannerProcess").disabled=false;document.getElementById("btnScannerProcess").textContent="Processar áudio";} });
|
||||
}
|
||||
|
||||
function scannerProcess() {
|
||||
if (scannerRelatorioExistente) { scannerReprocessamentoPendente = true; document.getElementById("scannerReprocessConfirm").hidden = false; return; }
|
||||
if (scannerRelatorioExistente) { showToast("ok", "Esta análise já está pronta. Abra Editar vídeo para utilizá-la."); return; }
|
||||
scannerIniciarProcessamento();
|
||||
}
|
||||
|
||||
@@ -2066,6 +2134,37 @@ function silenceConverterRelatorioDoScannerParaTranscricao(caminhoDoRelatorio, d
|
||||
return { version: 1, segments: segmentos, origem: "scanner" };
|
||||
}
|
||||
|
||||
function silenceConsultarStatusNoBanco(videoId) {
|
||||
if (!videoId || !childProcess.spawnSync) return null;
|
||||
try {
|
||||
var resposta = childProcess.spawnSync(
|
||||
SCANNER_PYTHON_BIN,
|
||||
[ANALISE_STATUS_SCRIPT, videoId, "--banco", "/Volumes/Merongo/SISTEMAS/GENIAL SISTEMAS/Jhonny/.jhonny/analises.db"],
|
||||
{ cwd: "/Volumes/Merongo/SISTEMAS/GENIAL SISTEMAS/Jhonny/code", encoding: "utf-8", maxBuffer: 1024 * 1024 }
|
||||
);
|
||||
if (resposta.status !== 0) return null;
|
||||
return JSON.parse(String(resposta.stdout || "{}"));
|
||||
} catch (_) { return null; }
|
||||
}
|
||||
|
||||
function silenceLocalizarAudioParaFalantes(pasta) {
|
||||
var encontrados = [];
|
||||
function visitar(caminho) {
|
||||
if (encontrados.length) return;
|
||||
try {
|
||||
fs.readdirSync(caminho).forEach(function (nome) {
|
||||
if (encontrados.length) return;
|
||||
var item = path.join(caminho, nome);
|
||||
var estatisticas = fs.statSync(item);
|
||||
if (estatisticas.isDirectory()) visitar(item);
|
||||
else if (/\.wav$/i.test(nome)) encontrados.push(item);
|
||||
});
|
||||
} catch (_) {}
|
||||
}
|
||||
visitar(pasta);
|
||||
return encontrados[0] || null;
|
||||
}
|
||||
|
||||
function silenceLoadScannerAnalysis() {
|
||||
var status = document.getElementById("scannerAnalysisStatus");
|
||||
var info = document.getElementById("scannerAnalysisInfo");
|
||||
@@ -2086,22 +2185,37 @@ function silenceLoadScannerAnalysis() {
|
||||
silenceState.mediaPath = null;
|
||||
silenceState.fileBaseName = path.basename(path.dirname(caminhoDoRelatorio));
|
||||
silenceState.outputDir = path.dirname(caminhoDoRelatorio);
|
||||
silenceState.audioCachePath = silenceLocalizarAudioParaFalantes(silenceState.outputDir);
|
||||
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;
|
||||
var statusDoBanco = silenceConsultarStatusNoBanco(silenceState.sequenceId);
|
||||
if (!statusDoBanco || !statusDoBanco.audio) throw new Error("A análise não foi encontrada no banco de dados.");
|
||||
var audioDoBanco = statusDoBanco.audio;
|
||||
var falantes = audioDoBanco.falantes || [];
|
||||
var turnos = transcricao.segments.filter(function (segmento) { return segmento.falante; }).map(function (segmento) {
|
||||
return { speaker: segmento.falante, start: segmento.start, end: segmento.end };
|
||||
});
|
||||
if (falantes.length) renderSpeakerConfiguration(falantes, turnos);
|
||||
status.textContent = "Carregada";
|
||||
info.textContent = silenceState.sequenceName + " · " + quantidade + " trecho(s) vindos do Scanner.";
|
||||
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(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.";
|
||||
document.getElementById("silenceDiarizeInfo").textContent = audioDoBanco.diarizacao_disponivel
|
||||
? falantes.length + " falante(s) disponíveis no banco de dados."
|
||||
: "Diarização não realizada nesta análise do Scanner.";
|
||||
document.getElementById("silenceVoiceFeaturesInfo").textContent = audioDoBanco.metricas_de_voz_disponiveis
|
||||
? audioDoBanco.falas_com_metricas + " trecho(s) com métricas de voz no banco."
|
||||
: "Métricas de voz não realizadas nesta análise do Scanner.";
|
||||
silenceLog("Análise do Scanner carregada: " + quantidade + " trecho(s).", "ok");
|
||||
showToast("ok", "Análise do Scanner carregada.");
|
||||
} catch (erro) {
|
||||
|
||||
Reference in New Issue
Block a user