feat: indicateur visuel de volume micro en temps réel et boîte de diagnostic des erreurs JS

This commit is contained in:
Michael committed 2026-06-12 16:35:17 +02:00
1 parent e59bdd1feb
commit c06b490a0c
4 files changed
+71

No files matched your search

+42
View File
@@ -1,5 +1,30 @@
const $ = (id) => document.getElementById(id);
// Capturer et afficher les erreurs JavaScript non gérées à l'écran
window.onerror = function (message, source, lineno, colno, error) {
const errText = `Erreur JS : ${message} (Ligne ${lineno}:${colno} dans ${source ? source.split('/').pop() : 'inconnu'})`;
console.error(errText, error);
showVisualError(errText);
};
window.onunhandledrejection = function (event) {
const errText = `Erreur de Promesse : ${event.reason}`;
console.error(errText);
showVisualError(errText);
};
function showVisualError(text) {
let box = $('visual-error-box');
if (!box) {
box = document.createElement('div');
box.id = 'visual-error-box';
box.style.cssText = 'background: #4c1113; color: #ff8589; padding: 14px; margin: 10px; border: 2px solid #e5484d; border-radius: 8px; font-family: monospace; font-size: 0.85rem; white-space: pre-wrap; z-index: 10000; position: relative;';
const parent = $('transcript-panel') || document.body;
parent.insertBefore(box, parent.firstChild);
}
box.textContent = text;
}
// Vérification du contexte sécurisé (requis pour le micro et les périphériques)
if (window.isSecureContext === false) {
const warning = document.createElement('div');
@@ -185,12 +210,29 @@ function stopRecording(abrupt = false) {
}
if ($('title')) $('title').disabled = false;
const bar = $('volume-bar');
if (bar) bar.style.width = '0%';
// Toujours recharger les réunions pour synchroniser la liste (cas d'arrêt abrupt ou échec)
loadMeetings();
}
function updateVolumeIndicator(samples) {
let sum = 0;
for (let i = 0; i < samples.length; i++) {
sum += samples[i] * samples[i];
}
const rms = Math.sqrt(sum / samples.length);
// Normaliser rms (amplitude max ~32768) vers un pourcentage (0 - 100)
// On applique un facteur de boost pour la visibilité des voix normales (divisé par 2500)
const percentage = Math.min(100, Math.round((rms / 2500) * 100));
const bar = $('volume-bar');
if (bar) bar.style.width = percentage + '%';
}
function queuePcm(samples) {
if (!state.recording || !state.ws || state.ws.readyState !== WebSocket.OPEN) return;
updateVolumeIndicator(samples);
state.sendBuffer.push(samples);
state.sendBufferSamples += samples.length;
if (state.sendBufferSamples >= BATCH_SAMPLES) flushPcm();
+3
View File
@@ -27,6 +27,9 @@
</select>
<button id="record-btn" class="record">● Démarrer</button>
<span id="timer">00:00</span>
<div id="volume-container" class="volume-container" title="Volume du micro">
<div id="volume-bar" class="volume-bar"></div>
</div>
<label id="diarization-toggle" class="toggle" title="Identifier les locuteurs">
<input type="checkbox" id="diarization-cb">
<span>👥 Locuteurs</span>
+22
View File
@@ -187,6 +187,28 @@ button.record.recording { background: var(--rec); }
color: var(--text);
}
/* Indicateur de volume micro */
.volume-container {
width: 60px;
height: 8px;
background: var(--panel-2);
border: 1px solid #2c3245;
border-radius: 4px;
overflow: hidden;
display: flex;
align-items: center;
padding: 1px;
}
.volume-bar {
width: 0%;
height: 100%;
background: #30a46c; /* Vert */
border-radius: 2px;
transition: width 0.1s ease;
}
@media (max-width: 720px) {
.layout { flex-direction: column; }
aside { width: 100%; max-height: 30vh; border-right: none; border-bottom: 1px solid #262b3a; }