Supresor de Ruido-JavaScript para Capturar Webcam y Microfono

 Código con Supresor de Ruido Ambiental para el Micrófono

Aquí te presento una solución completa que incluye supresión de ruido ambiental utilizando la API Web Audio. Este código implementa un filtro de ruido básico y un indicador visual del audio:

html
Copy
Download
Run
<!DOCTYPE html>
<html lang="es">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Webcam con Supresor de Ruido</title>
    <style>
        body {
            font-family: Arial, sans-serif;
            display: flex;
            flex-direction: column;
            align-items: center;
            padding: 20px;
            background-color: #f5f5f5;
        }
        #videoElement {
            width: 100%;
            max-width: 640px;
            background-color: #333;
            margin: 20px 0;
            border-radius: 8px;
            box-shadow: 0 4px 8px rgba(0,0,0,0.2);
        }
        .controls {
            display: flex;
            gap: 10px;
            margin-bottom: 20px;
        }
        button {
            padding: 10px 20px;
            background-color: #4285F4;
            color: white;
            border: none;
            border-radius: 4px;
            cursor: pointer;
            font-size: 16px;
            transition: background-color 0.3s;
        }
        button:hover {
            background-color: #3367D6;
        }
        button:disabled {
            background-color: #9E9E9E;
            cursor: not-allowed;
        }
        #errorMsg {
            color: #D32F2F;
            margin-top: 20px;
            text-align: center;
        }
        .audio-panel {
            width: 100%;
            max-width: 640px;
            background-color: white;
            padding: 15px;
            border-radius: 8px;
            box-shadow: 0 2px 4px rgba(0,0,0,0.1);
            margin-bottom: 20px;
        }
        .meter {
            height: 20px;
            background: #E0E0E0;
            border-radius: 10px;
            overflow: hidden;
            margin-top: 10px;
        }
        .level {
            height: 100%;
            width: 0%;
            background: linear-gradient(to right, #4CAF50, #FFEB3B, #F44336);
            transition: width 0.05s;
        }
        .controls-row {
            display: flex;
            justify-content: space-between;
            margin-top: 10px;
        }
        label {
            display: flex;
            align-items: center;
            gap: 5px;
            cursor: pointer;
        }
        h2 {
            color: #4285F4;
            margin-top: 0;
        }
    </style>
</head>
<body>
    <h1>Webcam con Supresor de Ruido</h1>
    <video id="videoElement" autoplay playsinline></video>
    
    <div class="audio-panel">
        <h2>Control de Audio</h2>
        <div>Nivel de micrófono:</div>
        <div class="meter">
            <div class="level" id="audioLevel"></div>
        </div>
        
        <div class="controls-row">
            <label>
                <input type="checkbox" id="noiseSuppression" checked>
                Supresión de ruido
            </label>
            <label>
                <input type="range" id="gainControl" min="0" max="200" value="100">
                Volumen: <span id="gainValue">100%</span>
            </label>
        </div>
    </div>
    
    <div class="controls">
        <button id="startButton">Iniciar</button>
        <button id="stopButton" disabled>Detener</button>
    </div>
    
    <div id="errorMsg"></div>

    <script>
        // Elementos del DOM
        const videoElement = document.getElementById('videoElement');
        const startButton = document.getElementById('startButton');
        const stopButton = document.getElementById('stopButton');
        const errorMsg = document.getElementById('errorMsg');
        const audioLevel = document.getElementById('audioLevel');
        const noiseSuppression = document.getElementById('noiseSuppression');
        const gainControl = document.getElementById('gainControl');
        const gainValue = document.getElementById('gainValue');
        
        // Objetos para el procesamiento de audio
        let stream = null;
        let audioContext = null;
        let analyser = null;
        let microphone = null;
        let noiseSuppressor = null;
        let gainNode = null;
        let animationId = null;

        // Iniciar captura
        async function startCapture() {
            try {
                // Solicitar acceso a dispositivos
                stream = await navigator.mediaDevices.getUserMedia({
                    video: true,
                    audio: {
                        noiseSuppression: true,  // Habilitar supresión de ruido del navegador
                        echoCancellation: true,
                        autoGainControl: true
                    }
                });
                
                // Configurar video
                videoElement.srcObject = stream;
                
                // Configurar procesamiento de audio
                setupAudioProcessing(stream);
                
                // Actualizar UI
                startButton.disabled = true;
                stopButton.disabled = false;
                errorMsg.textContent = '';
            } catch (err) {
                console.error("Error:", err);
                errorMsg.textContent = `Error: ${err.message}`;
            }
        }

        // Configurar procesamiento de audio
        function setupAudioProcessing(stream) {
            // Crear contexto de audio
            audioContext = new (window.AudioContext || window.webkitAudioContext)();
            
            // Crear nodos de procesamiento
            analyser = audioContext.createAnalyser();
            analyser.fftSize = 64;
            
            // Nodo de ganancia (control de volumen)
            gainNode = audioContext.createGain();
            updateGain();
            
            // Conectar el flujo de audio
            microphone = audioContext.createMediaStreamSource(stream);
            
            // Configurar supresión de ruido (filtro paso alto)
            if (noiseSuppression.checked) {
                setupNoiseSuppression();
            } else {
                microphone.connect(gainNode);
            }
            
            gainNode.connect(analyser);
            analyser.connect(audioContext.destination);
            
            // Iniciar visualización
            updateAudioLevel();
        }

        // Configurar supresión de ruido
        function setupNoiseSuppression() {
            if (noiseSuppressor) {
                noiseSuppressor.disconnect();
            }
            
            // Crear filtro paso alto para reducir ruido de baja frecuencia
            noiseSuppressor = audioContext.createBiquadFilter();
            noiseSuppressor.type = "highpass";
            noiseSuppressor.frequency.value = 150; // Frecuencia de corte en Hz
            
            // Conectar los nodos
            microphone.disconnect();
            microphone.connect(noiseSuppressor);
            noiseSuppressor.connect(gainNode);
        }

        // Actualizar control de ganancia
        function updateGain() {
            if (gainNode) {
                // Convertir valor de 0-200 a 0-2 (rango de ganancia)
                const gain = gainControl.value / 100;
                gainNode.gain.value = gain;
                gainValue.textContent = `${gainControl.value}%`;
            }
        }

        // Actualizar visualización de nivel de audio
        function updateAudioLevel() {
            const dataArray = new Uint8Array(analyser.frequencyBinCount);
            analyser.getByteFrequencyData(dataArray);
            
            // Calcular nivel promedio (excluyendo frecuencias muy bajas)
            let sum = 0;
            let count = 0;
            for (let i = 3; i < dataArray.length; i++) { // Ignorar las primeras frecuencias bajas
                sum += dataArray[i];
                count++;
            }
            const average = count > 0 ? sum / count : 0;
            
            // Actualizar medidor
            audioLevel.style.width = `${average}%`;
            
            // Cambiar color según nivel (verde -> amarillo -> rojo)
            if (average < 30) {
                audioLevel.style.backgroundColor = "#4CAF50";
            } else if (average < 70) {
                audioLevel.style.backgroundColor = "#FFEB3B";
            } else {
                audioLevel.style.backgroundColor = "#F44336";
            }
            
            // Continuar animación
            animationId = requestAnimationFrame(updateAudioLevel);
        }

        // Detener captura
        function stopCapture() {
            if (stream) {
                // Detener pistas
                stream.getTracks().forEach(track => track.stop());
                videoElement.srcObject = null;
                
                // Detener procesamiento de audio
                if (animationId) {
                    cancelAnimationFrame(animationId);
                    animationId = null;
                }
                if (audioContext) {
                    audioContext.close();
                    audioContext = null;
                }
                
                // Resetear UI
                audioLevel.style.width = "0%";
                startButton.disabled = false;
                stopButton.disabled = true;
            }
        }

        // Event listeners
        startButton.addEventListener('click', startCapture);
        stopButton.addEventListener('click', stopCapture);
        noiseSuppression.addEventListener('change', () => {
            if (noiseSuppression.checked && microphone && gainNode) {
                setupNoiseSuppression();
            } else if (microphone && gainNode) {
                microphone.disconnect();
                microphone.connect(gainNode);
            }
        });
        gainControl.addEventListener('input', updateGain);

        // Limpiar al salir
        window.addEventListener('beforeunload', stopCapture);
    </script>
</body>
</html>

Características de la supresión de ruido:

  1. Doble capa de supresión:

    • Usa la supresión de ruido nativa del navegador (noiseSuppression: true)

    • Implementa un filtro paso alto adicional para eliminar frecuencias bajas (ruido ambiental típico)

  2. Controles ajustables:

    • Interruptor para activar/desactivar la supresión de ruido

    • Control deslizante para ajustar la ganancia del micrófono

  3. Visualización mejorada:

    • Medidor de nivel de audio con colores que indican intensidad

    • Filtrado de frecuencias muy bajas en la visualización

  4. Procesamiento en tiempo real:

    • Todo el procesamiento de audio ocurre en el contexto Web Audio

    • No introduce latencia significativa

Cómo probar la supresión de ruido:

  1. Activa la cámara y micrófono

  2. Habla normalmente y observa el medidor

  3. Activa/desactiva la casilla de supresión de ruido para comparar

  4. Ajusta el control de volumen según necesites

Este código funciona en la mayoría de navegadores modernos (Chrome, Firefox, Edge) y aprovecha al máximo las capacidades de procesamiento de audio del navegador.

Comentarios

Entradas más populares de este blog

b-Web Speech API

captura video con audio del sistema (como música o sonidos del navegador) pero sin usar el micrófono

EL audio lo envia el navegador-Transcripción de Voz con Whisper