captura video con audio del sistema (como música o sonidos del navegador) pero sin usar el micrófono
Aquí tienes una versión que captura video con audio del sistema (como música o sonidos del navegador) pero sin usar el micrófono:
Aquí tienes una versión que captura video con audio del sistema (como música o sonidos del navegador) pero sin usar el micrófono:
<!DOCTYPE html> <html lang="es"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Grabación de Video con Audio del Sistema</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; flex-wrap: wrap; justify-content: center; } 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; } #recordingIndicator { display: none; width: 12px; height: 12px; background-color: red; border-radius: 50%; margin-left: 5px; animation: pulse 1.5s infinite; } @keyframes pulse { 0% { opacity: 1; } 50% { opacity: 0.3; } 100% { opacity: 1; } } #timer { margin-left: 10px; font-weight: bold; } .audio-info { background-color: #e8f0fe; padding: 10px; border-radius: 5px; margin-bottom: 15px; text-align: center; } </style> </head> <body> <h1>Grabación de Video con Audio del Sistema</h1> <div class="audio-info"> <p>Esta aplicación captura video de tu cámara y audio del sistema (como música o sonidos del navegador), pero no usa el micrófono.</p> </div> <video id="videoElement" autoplay playsinline></video> <div class="controls"> <button id="startButton">Iniciar Cámara</button> <button id="stopButton" disabled>Detener Cámara</button> <button id="recordButton" disabled> Grabar <span id="recordingIndicator"></span> <span id="timer"></span> </button> <button id="downloadButton" disabled>Descargar</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 recordButton = document.getElementById('recordButton'); const downloadButton = document.getElementById('downloadButton'); const recordingIndicator = document.getElementById('recordingIndicator'); const timerElement = document.getElementById('timer'); const errorMsg = document.getElementById('errorMsg'); // Variables de estado let videoStream = null; let audioStream = null; let combinedStream = null; let mediaRecorder = null; let recordedChunks = []; let recordingStartTime = null; let timerInterval = null; // Iniciar cámara y captura de audio del sistema async function startCapture() { try { // 1. Obtener solo video de la cámara (sin audio del micrófono) videoStream = await navigator.mediaDevices.getUserMedia({ video: true, audio: false }); // 2. Intentar capturar audio del sistema (no micrófono) // Nota: Esto requiere que el usuario haya interactuado con la página primero try { audioStream = await navigator.mediaDevices.getDisplayMedia({ video: false, audio: true }); // 3. Combinar los streams combinedStream = new MediaStream([ ...videoStream.getVideoTracks(), ...audioStream.getAudioTracks() ]); // Mostrar video en el elemento videoElement.srcObject = videoStream; // Habilitar/deshabilitar botones startButton.disabled = true; stopButton.disabled = false; recordButton.disabled = false; downloadButton.disabled = true; errorMsg.textContent = ''; } catch (audioError) { console.error("Error al capturar audio del sistema:", audioError); // Continuar solo con video si no se puede obtener audio combinedStream = videoStream; videoElement.srcObject = videoStream; startButton.disabled = true; stopButton.disabled = false; recordButton.disabled = false; downloadButton.disabled = true; errorMsg.textContent = "Se inició sin audio del sistema (solo video)"; } } catch (err) { console.error("Error al acceder a la cámara:", err); errorMsg.textContent = `Error: ${err.message}`; } } // Detener captura function stopCapture() { // Detener grabación si está activa if (mediaRecorder && mediaRecorder.state === 'recording') { stopRecording(); } // Detener todas las pistas if (videoStream) { videoStream.getTracks().forEach(track => track.stop()); } if (audioStream) { audioStream.getTracks().forEach(track => track.stop()); } videoElement.srcObject = null; // Resetear estado videoStream = null; audioStream = null; combinedStream = null; // Actualizar UI startButton.disabled = false; stopButton.disabled = true; recordButton.disabled = true; downloadButton.disabled = true; recordButton.textContent = "Grabar"; recordingIndicator.style.display = "none"; timerElement.textContent = ""; errorMsg.textContent = ""; } // Iniciar grabación function startRecording() { if (!combinedStream) return; recordedChunks = []; // Configurar MediaRecorder const options = { mimeType: 'video/webm;codecs=vp9' }; mediaRecorder = new MediaRecorder(combinedStream, options); // Recoger datos de grabación mediaRecorder.ondataavailable = function(event) { if (event.data.size > 0) { recordedChunks.push(event.data); } }; // Iniciar grabación mediaRecorder.start(100); // Recoger datos cada 100ms // Actualizar UI recordButton.textContent = "Detener"; recordingIndicator.style.display = "inline-block"; downloadButton.disabled = true; // Iniciar temporizador recordingStartTime = new Date(); updateTimer(); timerInterval = setInterval(updateTimer, 1000); } // Detener grabación function stopRecording() { if (mediaRecorder && mediaRecorder.state !== 'inactive') { mediaRecorder.stop(); // Detener temporizador clearInterval(timerInterval); // Actualizar UI recordButton.textContent = "Grabar"; recordingIndicator.style.display = "none"; downloadButton.disabled = false; } } // Actualizar temporizador function updateTimer() { const elapsed = Math.floor((new Date() - recordingStartTime) / 1000); const minutes = Math.floor(elapsed / 60).toString().padStart(2, '0'); const seconds = (elapsed % 60).toString().padStart(2, '0'); timerElement.textContent = `${minutes}:${seconds}`; } // Descargar video grabado function downloadVideo() { const blob = new Blob(recordedChunks, { type: 'video/webm' }); const url = URL.createObjectURL(blob); const a = document.createElement('a'); a.style.display = 'none'; a.href = url; a.download = `grabacion-${new Date().toISOString().slice(0, 19).replace(/[:T]/g, '-')}.webm`; document.body.appendChild(a); a.click(); setTimeout(() => { document.body.removeChild(a); URL.revokeObjectURL(url); }, 100); } // Event listeners startButton.addEventListener('click', startCapture); stopButton.addEventListener('click', stopCapture); recordButton.addEventListener('click', function() { if (recordButton.textContent === "Grabar") { startRecording(); } else { stopRecording(); } }); downloadButton.addEventListener('click', downloadVideo); // Limpiar al salir window.addEventListener('beforeunload', stopCapture); </script> </body> </html>
Características clave:
Captura de video sin micrófono:
Usa
getUserMediasolo para video (audio: false)No solicita permisos de micrófono
Captura de audio del sistema:
Usa
getDisplayMediapara capturar audio del sistema (música, sonidos del navegador)El navegador mostrará un selector para compartir pestañas/ventanas con audio
Combinación de streams:
Combina el stream de video de la cámara con el audio del sistema
Si no se puede obtener audio, graba solo video
Interfaz clara:
Explica que no se usa el micrófono
Mantiene controles simples para iniciar/detener y grabar
Limitaciones importantes:
El audio del sistema solo se puede capturar después de una interacción del usuario
Algunos navegadores pueden restringir esta funcionalidad
El usuario debe seleccionar manualmente qué ventana/pestaña compartir para el audio
Comentarios
Publicar un comentario