Spaces:
Sleeping
Sleeping
Update index.html
Browse files- index.html +45 -11
index.html
CHANGED
|
@@ -1,4 +1,5 @@
|
|
| 1 |
<!DOCTYPE html>
|
|
|
|
| 2 |
<html lang="es">
|
| 3 |
<head>
|
| 4 |
<meta charset="UTF-8">
|
|
@@ -122,6 +123,12 @@
|
|
| 122 |
cursor: not-allowed;
|
| 123 |
}
|
| 124 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 125 |
#status {
|
| 126 |
margin-top: 16px;
|
| 127 |
font-size: 0.875rem;
|
|
@@ -146,13 +153,14 @@
|
|
| 146 |
</div>
|
| 147 |
|
| 148 |
<div class="form-group">
|
| 149 |
-
<label for="word">Palabra a decir:</label>
|
| 150 |
<input type="text" id="word" value="casa">
|
|
|
|
| 151 |
</div>
|
| 152 |
|
| 153 |
-
<div class="form-group">
|
| 154 |
<label for="max_repetitions">Máx. Repeticiones:</label>
|
| 155 |
-
<input type="number" id="max_repetitions" value="
|
| 156 |
</div>
|
| 157 |
|
| 158 |
<button id="recordBtn">Grabar (3 segundos)</button>
|
|
@@ -165,6 +173,23 @@
|
|
| 165 |
</div>
|
| 166 |
|
| 167 |
<script>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 168 |
let mediaRecorder;
|
| 169 |
let audioChunks = [];
|
| 170 |
let timerInterval;
|
|
@@ -183,7 +208,6 @@
|
|
| 183 |
}
|
| 184 |
|
| 185 |
recordBtn.addEventListener('click', async () => {
|
| 186 |
-
// Si ya está grabando, ignorar o detener
|
| 187 |
if (mediaRecorder && mediaRecorder.state === 'recording') return;
|
| 188 |
|
| 189 |
try {
|
|
@@ -206,8 +230,8 @@
|
|
| 206 |
const audioBlob = new Blob(audioChunks, { type: 'audio/wav' });
|
| 207 |
const formData = new FormData();
|
| 208 |
formData.append('file', audioBlob, 'audio.wav');
|
| 209 |
-
formData.append('word',
|
| 210 |
-
formData.append('max_repetitions',
|
| 211 |
formData.append('dataset_name', document.getElementById('dataset_name').value);
|
| 212 |
|
| 213 |
try {
|
|
@@ -218,9 +242,23 @@
|
|
| 218 |
const result = await response.json();
|
| 219 |
|
| 220 |
if (response.ok) {
|
| 221 |
-
setStatus(`✅ Guardado: ${result.repetition}/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 222 |
} else {
|
| 223 |
setStatus(`❌ Límite/Error: ${result.detail || 'Error en servidor'}`, 'error');
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 224 |
}
|
| 225 |
} catch (err) {
|
| 226 |
setStatus(`❌ Error de red: ${err.message}`, 'error');
|
|
@@ -230,17 +268,14 @@
|
|
| 230 |
recordBtn.textContent = 'Grabar (3 segundos)';
|
| 231 |
}
|
| 232 |
|
| 233 |
-
// Apagar micrófono
|
| 234 |
stream.getTracks().forEach(track => track.stop());
|
| 235 |
};
|
| 236 |
|
| 237 |
-
// Iniciar grabación UI
|
| 238 |
mediaRecorder.start();
|
| 239 |
recordBtn.classList.add('recording');
|
| 240 |
recordBtn.textContent = '🔴 Grabando...';
|
| 241 |
setStatus('Habla ahora...');
|
| 242 |
|
| 243 |
-
// Mostrar barra de progreso
|
| 244 |
progressContainer.style.display = 'block';
|
| 245 |
progressBar.style.width = '0%';
|
| 246 |
|
|
@@ -253,7 +288,6 @@
|
|
| 253 |
progressBar.style.width = pct + '%';
|
| 254 |
}, 50);
|
| 255 |
|
| 256 |
-
// Detener automáticamente a los 3 segundos
|
| 257 |
timeoutHandle = setTimeout(() => {
|
| 258 |
if (mediaRecorder && mediaRecorder.state === 'recording') {
|
| 259 |
mediaRecorder.stop();
|
|
|
|
| 1 |
<!DOCTYPE html>
|
| 2 |
+
<!DOCTYPE html>
|
| 3 |
<html lang="es">
|
| 4 |
<head>
|
| 5 |
<meta charset="UTF-8">
|
|
|
|
| 123 |
cursor: not-allowed;
|
| 124 |
}
|
| 125 |
|
| 126 |
+
#word-queue-info {
|
| 127 |
+
font-size: 0.8rem;
|
| 128 |
+
color: var(--text-secondary);
|
| 129 |
+
margin-top: 4px;
|
| 130 |
+
}
|
| 131 |
+
|
| 132 |
#status {
|
| 133 |
margin-top: 16px;
|
| 134 |
font-size: 0.875rem;
|
|
|
|
| 153 |
</div>
|
| 154 |
|
| 155 |
<div class="form-group">
|
| 156 |
+
<label for="word">Palabra actual a decir:</label>
|
| 157 |
<input type="text" id="word" value="casa">
|
| 158 |
+
<div id="word-queue-info">Palabra 1 de N en cola (4 reps c/u)</div>
|
| 159 |
</div>
|
| 160 |
|
| 161 |
+
<div class="form-group" style="display:none;">
|
| 162 |
<label for="max_repetitions">Máx. Repeticiones:</label>
|
| 163 |
+
<input type="number" id="max_repetitions" value="4">
|
| 164 |
</div>
|
| 165 |
|
| 166 |
<button id="recordBtn">Grabar (3 segundos)</button>
|
|
|
|
| 173 |
</div>
|
| 174 |
|
| 175 |
<script>
|
| 176 |
+
// Lista de palabras de ejemplo (personalízalas o cárgalas dinámicamente)
|
| 177 |
+
const wordList = ["casa", "perro", "gato", "agua", "luz"];
|
| 178 |
+
let currentWordIndex = 0;
|
| 179 |
+
let repeticionesActualesPalabra = {}; // rastrea repeticiones locales en cliente o confía en backend
|
| 180 |
+
|
| 181 |
+
// Inicializar primer valor
|
| 182 |
+
const wordInput = document.getElementById('word');
|
| 183 |
+
const queueInfo = document.getElementById('word-queue-info');
|
| 184 |
+
const maxRepInput = document.getElementById('max_repetitions');
|
| 185 |
+
maxRepInput.value = 4;
|
| 186 |
+
|
| 187 |
+
function updateWordDisplay() {
|
| 188 |
+
wordInput.value = wordList[currentWordIndex] || wordList[0];
|
| 189 |
+
queueInfo.textContent = `Palabra ${currentWordIndex + 1} de ${wordList.length} ("${wordInput.value}" - meta: 4 reps)`;
|
| 190 |
+
}
|
| 191 |
+
updateWordDisplay();
|
| 192 |
+
|
| 193 |
let mediaRecorder;
|
| 194 |
let audioChunks = [];
|
| 195 |
let timerInterval;
|
|
|
|
| 208 |
}
|
| 209 |
|
| 210 |
recordBtn.addEventListener('click', async () => {
|
|
|
|
| 211 |
if (mediaRecorder && mediaRecorder.state === 'recording') return;
|
| 212 |
|
| 213 |
try {
|
|
|
|
| 230 |
const audioBlob = new Blob(audioChunks, { type: 'audio/wav' });
|
| 231 |
const formData = new FormData();
|
| 232 |
formData.append('file', audioBlob, 'audio.wav');
|
| 233 |
+
formData.append('word', wordInput.value);
|
| 234 |
+
formData.append('max_repetitions', maxRepInput.value);
|
| 235 |
formData.append('dataset_name', document.getElementById('dataset_name').value);
|
| 236 |
|
| 237 |
try {
|
|
|
|
| 242 |
const result = await response.json();
|
| 243 |
|
| 244 |
if (response.ok) {
|
| 245 |
+
setStatus(`✅ Guardado: Rep. ${result.repetition}/4`, 'success');
|
| 246 |
+
|
| 247 |
+
// Si alcanzó o superó las 4 repeticiones, avanzar automáticamente a la siguiente palabra
|
| 248 |
+
if (result.repetition >= 4) {
|
| 249 |
+
currentWordIndex = (currentWordIndex + 1) % wordList.length;
|
| 250 |
+
setTimeout(() => {
|
| 251 |
+
updateWordDisplay();
|
| 252 |
+
setStatus(`🔄 Cambiado automáticamente a: "${wordInput.value}"`);
|
| 253 |
+
}, 1200);
|
| 254 |
+
}
|
| 255 |
} else {
|
| 256 |
setStatus(`❌ Límite/Error: ${result.detail || 'Error en servidor'}`, 'error');
|
| 257 |
+
// Si dice que ya alcanzó el límite, por seguridad avanzamos también de palabra
|
| 258 |
+
if (result.detail && result.detail.includes("límite máximo")) {
|
| 259 |
+
currentWordIndex = (currentWordIndex + 1) % wordList.length;
|
| 260 |
+
setTimeout(() => updateWordDisplay(), 1500);
|
| 261 |
+
}
|
| 262 |
}
|
| 263 |
} catch (err) {
|
| 264 |
setStatus(`❌ Error de red: ${err.message}`, 'error');
|
|
|
|
| 268 |
recordBtn.textContent = 'Grabar (3 segundos)';
|
| 269 |
}
|
| 270 |
|
|
|
|
| 271 |
stream.getTracks().forEach(track => track.stop());
|
| 272 |
};
|
| 273 |
|
|
|
|
| 274 |
mediaRecorder.start();
|
| 275 |
recordBtn.classList.add('recording');
|
| 276 |
recordBtn.textContent = '🔴 Grabando...';
|
| 277 |
setStatus('Habla ahora...');
|
| 278 |
|
|
|
|
| 279 |
progressContainer.style.display = 'block';
|
| 280 |
progressBar.style.width = '0%';
|
| 281 |
|
|
|
|
| 288 |
progressBar.style.width = pct + '%';
|
| 289 |
}, 50);
|
| 290 |
|
|
|
|
| 291 |
timeoutHandle = setTimeout(() => {
|
| 292 |
if (mediaRecorder && mediaRecorder.state === 'recording') {
|
| 293 |
mediaRecorder.stop();
|