feat: aprimorado o preview de falantes na tela Refinar para reprod

- aprimorado o preview de falantes na tela Refinar para reproduzir os trechos do vídeo

Resumo:
- 6 arquivos alterados
- 2 novos
- 4 modificados
- 0 removidos

 4 files changed, 97 insertions(+), 11 deletions(-)

Arquivos:
  - .jhonny/analises.db
  - code/cep-plugin/index.html
  - code/cep-plugin/main.js
  - code/cep-plugin/styles.css
  - .jhonny/analises.db-shm
  - .jhonny/analises.db-wal
This commit is contained in:
João Henrique
2026-09-10 09:19:08 -04:00
parent c1b544f4b5
commit 485c35c4e8
6 changed files with 97 additions and 11 deletions
+87 -8
View File
@@ -2376,6 +2376,8 @@ function atualizarTelaRefinar(falantes, audioDoBanco) {
var speakerAudioPlayer = null;
var speakerAudioQueue = null;
var speakerVideoPlayer = null;
var speakerVideoQueue = null;
// ---- Central transcript cache ----
// Evita rodar o Whisper de novo para um vídeo já transcrito antes: indexa
@@ -2982,10 +2984,13 @@ function renderSpeakerConfiguration(speakerIds, speakerTurns, alvo) {
var play = document.createElement("button");
play.type = "button";
play.className = "button speaker-play-button";
play.textContent = "▶";
play.title = "Ouvir trechos de " + speaker.id;
play.setAttribute("aria-label", "Ouvir trechos de " + speaker.id);
play.addEventListener("click", function () { toggleSpeakerAudio(speaker.id, play); });
play.textContent = alvo.video ? "▶ vídeo" : "▶ áudio";
play.title = (alvo.video ? "Ver" : "Ouvir") + " trechos de " + speaker.id;
play.setAttribute("aria-label", (alvo.video ? "Ver" : "Ouvir") + " trechos de " + speaker.id);
play.addEventListener("click", function () {
if (alvo.video) toggleSpeakerVideo(speaker.id, play);
else toggleSpeakerAudio(speaker.id, play);
});
var input = document.createElement("input");
input.type = "text";
input.className = "select-field speaker-name-input";
@@ -3020,12 +3025,12 @@ function renderSpeakerConfiguration(speakerIds, speakerTurns, alvo) {
var refineConfig = document.getElementById("refinarSpeakerConfig");
if (refineConfig && config.id !== refineConfig.id) {
renderSpeakerConfiguration(speakerIds, speakerTurns, {
config: "refinarSpeakerConfig", list: "refinarSpeakerList", count: "refinarSpeakerCount"
config: "refinarSpeakerConfig", list: "refinarSpeakerList", count: "refinarSpeakerCount", video: true
});
}
}
function speakerAudioFileUrl(filePath) {
function speakerMediaFileUrl(filePath) {
return encodeURI("file://" + String(filePath || ""));
}
@@ -3037,12 +3042,86 @@ function stopSpeakerAudio() {
}
speakerAudioPlayer = null;
speakerAudioQueue = null;
if (speakerVideoPlayer) {
speakerVideoPlayer.pause();
speakerVideoPlayer.onloadedmetadata = null;
speakerVideoPlayer.ontimeupdate = null;
speakerVideoPlayer.onended = null;
speakerVideoPlayer.onerror = null;
speakerVideoPlayer.removeAttribute("src");
speakerVideoPlayer.load();
}
speakerVideoPlayer = null;
speakerVideoQueue = null;
var videoPreview = document.getElementById("refinarSpeakerPreview");
if (videoPreview) videoPreview.hidden = true;
document.querySelectorAll(".speaker-play-button").forEach(function (button) {
button.textContent = "▶";
button.textContent = button.closest("#refinarSpeakerList") ? "▶ vídeo" : "▶ áudio";
button.classList.remove("is-playing");
});
}
function toggleSpeakerVideo(speakerId, button) {
if (speakerVideoPlayer && speakerVideoQueue && speakerVideoQueue.speakerId === speakerId) {
stopSpeakerAudio();
return;
}
stopSpeakerAudio();
var ranges = silenceState.speakerTurns.filter(function (turn) {
return turn.speaker === speakerId && Number(turn.end) > Number(turn.start);
}).sort(function (a, b) { return Number(a.start) - Number(b.start); });
if (!ranges.length) {
showToast("err", "Não há intervalos de vídeo disponíveis para " + speakerId + ".");
return;
}
if (!silenceState.mediaPath || !fs.existsSync(silenceState.mediaPath)) {
showToast("err", "Arquivo de vídeo da análise não encontrado.");
return;
}
var video = document.getElementById("refinarSpeakerVideo");
var preview = document.getElementById("refinarSpeakerPreview");
var info = document.getElementById("refinarSpeakerPreviewInfo");
if (!video || !preview) {
showToast("err", "Preview de vídeo indisponível nesta versão do painel.");
return;
}
speakerVideoQueue = { speakerId: speakerId, ranges: ranges, index: 0, button: button };
speakerVideoPlayer = video;
preview.hidden = false;
if (info) info.textContent = "Reproduzindo os trechos de " + speakerId + ".";
video.src = speakerMediaFileUrl(silenceState.mediaPath);
button.textContent = "■ vídeo";
button.classList.add("is-playing");
video.onloadedmetadata = playCurrentSpeakerVideoRange;
video.ontimeupdate = advanceSpeakerVideoRange;
video.onended = advanceSpeakerVideoRange;
video.onerror = function () {
stopSpeakerAudio();
showToast("err", "Não foi possível reproduzir o vídeo deste falante.");
};
}
function playCurrentSpeakerVideoRange() {
if (!speakerVideoPlayer || !speakerVideoQueue) return;
var range = speakerVideoQueue.ranges[speakerVideoQueue.index];
if (!range) { stopSpeakerAudio(); return; }
speakerVideoPlayer.currentTime = Math.max(0, Number(range.start) - 0.15);
var playPromise = speakerVideoPlayer.play();
if (playPromise && playPromise.catch) playPromise.catch(function () { stopSpeakerAudio(); });
}
function advanceSpeakerVideoRange() {
if (!speakerVideoPlayer || !speakerVideoQueue) return;
var range = speakerVideoQueue.ranges[speakerVideoQueue.index];
if (!range || speakerVideoPlayer.currentTime < Number(range.end)) return;
speakerVideoQueue.index += 1;
if (speakerVideoQueue.index >= speakerVideoQueue.ranges.length) {
stopSpeakerAudio();
return;
}
playCurrentSpeakerVideoRange();
}
function toggleSpeakerAudio(speakerId, button) {
if (speakerAudioPlayer && speakerAudioQueue && speakerAudioQueue.speakerId === speakerId) {
stopSpeakerAudio();
@@ -3061,7 +3140,7 @@ function toggleSpeakerAudio(speakerId, button) {
return;
}
speakerAudioQueue = { speakerId: speakerId, ranges: ranges, index: 0, button: button };
speakerAudioPlayer = new Audio(speakerAudioFileUrl(silenceState.audioCachePath));
speakerAudioPlayer = new Audio(speakerMediaFileUrl(silenceState.audioCachePath));
button.textContent = "■";
button.classList.add("is-playing");
speakerAudioPlayer.addEventListener("loadedmetadata", playCurrentSpeakerRange);