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:
<!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:
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)
Controles ajustables:
Interruptor para activar/desactivar la supresión de ruido
Control deslizante para ajustar la ganancia del micrófono
Visualización mejorada:
Medidor de nivel de audio con colores que indican intensidad
Filtrado de frecuencias muy bajas en la visualización
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:
Activa la cámara y micrófono
Habla normalmente y observa el medidor
Activa/desactiva la casilla de supresión de ruido para comparar
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
Publicar un comentario