Objetivos de la nueva versión

 

Objetivos de la nueva versión:

  1. Interfaz más amigable y moderna con estilo tipo editor de texto.

  2. No sobrescribe el texto anterior, sino que lo va acumulando conforme hablas.

  3. Incluye un editor enriquecido (Rich Text) directamente en el navegador.

  4. Permite copiar o guardar el texto fácilmente.


🧰 ¿Qué usaremos?

  • ContentEditable: para el editor enriquecido nativo del navegador (no requiere librerías).

  • Un mejor layout con botones y estilos.

  • Mejor manejo de resultados Vosk (agregar texto, no reemplazar).


✅ Código HTML actualizado (index1.html):

html
<!DOCTYPE html> <html lang="es"> <head> <meta charset="UTF-8"> <title>Dictado con Vosk</title> <style> body { font-family: Arial, sans-serif; max-width: 900px; margin: 40px auto; padding: 20px; background-color: #f9f9f9; } h1 { text-align: center; color: #333; } .controls { text-align: center; margin-bottom: 20px; } button { padding: 10px 20px; margin: 0 10px; font-size: 16px; border: none; border-radius: 6px; cursor: pointer; background-color: #007BFF; color: white; } button:disabled { background-color: #ccc; cursor: not-allowed; } #editor { border: 1px solid #ccc; padding: 15px; min-height: 300px; background-color: white; border-radius: 6px; outline: none; overflow-y: auto; } #status { text-align: center; margin-top: 10px; color: green; font-weight: bold; } .tools { text-align: right; margin-top: 10px; } .tools button { background-color: #28a745; } </style> </head> <body> <h1>🗣️ Reconocimiento de Voz con Vosk</h1> <div class="controls"> <button id="startBtn">Comenzar</button> <button id="stopBtn" disabled>Detener</button> </div> <div id="status">Esperando...</div> <div id="editor" contenteditable="true"> <!-- Aquí se insertará el texto --> </div> <div class="tools"> <button id="copiarBtn">📋 Copiar Texto</button> </div> <script src="/socket.io/socket.io.js"></script> <script> const socket = io(); const startBtn = document.getElementById('startBtn'); const stopBtn = document.getElementById('stopBtn'); const status = document.getElementById('status'); const editor = document.getElementById('editor'); const copiarBtn = document.getElementById('copiarBtn'); let audioContext, processor, microphone; // Configurar audio async function setupAudio() { audioContext = new (window.AudioContext || window.webkitAudioContext)(); const stream = await navigator.mediaDevices.getUserMedia({ audio: true }); microphone = audioContext.createMediaStreamSource(stream); processor = audioContext.createScriptProcessor(4096, 1, 1); processor.onaudioprocess = (e) => { const audioData = e.inputBuffer.getChannelData(0); const raw = convertFloat32ToInt16(audioData); socket.emit('audio', raw); }; microphone.connect(processor); processor.connect(audioContext.destination); } // Float32 → Int16 function convertFloat32ToInt16(buffer) { const l = buffer.length; const buf = new Int16Array(l); for (let i = 0; i < l; i++) { buf[i] = Math.min(1, buffer[i]) * 0x7FFF; } return buf.buffer; } // Iniciar dictado startBtn.addEventListener('click', async () => { try { await setupAudio(); socket.emit('start', audioContext.sampleRate); startBtn.disabled = true; stopBtn.disabled = false; status.textContent = "🎤 Escuchando..."; status.style.color = "green"; } catch (err) { console.error("Error:", err); status.textContent = "❌ Error al iniciar micrófono."; status.style.color = "red"; } }); // Detener dictado stopBtn.addEventListener('click', () => { if (processor) { processor.disconnect(); microphone.disconnect(); socket.emit('stop'); startBtn.disabled = false; stopBtn.disabled = true; status.textContent = "⏹️ Detenido."; status.style.color = "orange"; } }); // Resultado parcial socket.on('result', (data) => { if (data.text) { // 👇 Mostrar mientras se dicta (pero no guardar) status.textContent = "🎤 " + data.text; } }); // Resultado final socket.on('final', (data) => { if (data.text) { // 👇 Insertar como párrafo en el editor editor.innerHTML += `<p>${data.text}</p>`; editor.scrollTop = editor.scrollHeight; } }); // Copiar al portapapeles copiarBtn.addEventListener('click', () => { const temp = document.createElement("textarea"); temp.value = editor.innerText; document.body.appendChild(temp); temp.select(); document.execCommand("copy"); document.body.removeChild(temp); alert("Texto copiado al portapapeles"); }); </script> </body> </html>

✅ ¿Qué mejora esto?

  • Editor visual donde el texto se guarda como párrafos.

  • Botón para copiar fácilmente.

  • Indicadores visuales claros de estado.

  • No requiere librerías externas (Bootstrap, Quill, etc.).

  • Ideal para prototipos rápidos de dictado o transcripción judicial.


Si después deseas exportar como PDF, imprimir o usar un editor más avanzado como Quill.js o TinyMCE, también te lo puedo integrar.

¿Quieres que también se pueda guardar en un archivo .txt o .pdf?

Comentarios

Entradas más populares de este blog

index

Vosk en una Página Web

Proyecto de Transcripción de Voz en Tiempo Real