Accediendo a la cámara y el micrófono de un dispositivo con JavaScript
- 👤 Andrés Cruz
Cuando descubrí por primera vez que HTML5 permitía abrir la cámara sin plugins, pensé exactamente lo que seguramente piensas tú ahora: “esto es fascinante”. Poder acceder al video y al audio del usuario directamente desde JavaScript cambió la forma en que construimos aplicaciones web, desde lectores de códigos QR hasta videollamadas o sistemas de captura de imágenes y todo esto nos acerca más a lo que es el uso de apps nativas desde las apps web.
En esta guía voy a enseñarte, paso a paso, cómo acceder a la cámara y micrófono con JavaScript usando la API moderna, cómo mostrar el stream en un <video>, cómo capturar una foto con <canvas> y cómo resolver los errores típicos que todos hemos sufrido alguna vez.
Esta es una características fascinante que trae el API de HTML5 consigo y consiste en la posibilidad de acceder a la cámara y micrófono (con previa aprobación del usuario) de la computadora o dispositivo móvil sin la necesidad de utilizar ningún plugin; en este artículo aprenderemos cómo acceder a la cámara de un dispositivo y dirigir este flujo de datos (stream) dentro de un tag <video>; básicamente vamos a tomar una captura o imagen a través de la cámara del usuario.
Requisitos, permisos y limitaciones (HTTPS, compatibilidad, errores comunes)
Antes de meterte al código, hay tres reglas clave:
- Necesitas HTTPS
- Los navegadores no permiten abrir la cámara desde páginas servidas como file://. Créeme, la primera vez que lo probé desde un archivo suelto me volví loco: el código estaba perfecto, pero la cámara simplemente no aparecía.
- El usuario siempre debe aprobar el permiso
- Cuando llamas a getUserMedia(), el navegador mostrará un popup pidiendo acceso a la cámara y/o micrófono.
- Compatibilidad moderna
- Hoy todo se hace con navigator.mediaDevices.getUserMedia().
La versión con prefijos (navigator.webkitGetUserMedia, etc.) quedó obsoleta.
- Hoy todo se hace con navigator.mediaDevices.getUserMedia().
Cómo acceder a la cámara con JavaScript
La base de todo es navigator.mediaDevices.getUserMedia(). Este método recibe un objeto llamado constraints que especifica qué deseas activar: video, audio o ambos.
El objeto navigator.getUserMedia de HTML5
Algunas configuraciones típicas antes de comenzar y que depende de lo que quieras activar; esto es lo típico de una cámara web:
{ video: true, audio: false } // Solo video
{ video: false, audio: true } // Solo micrófono
{ video: true, audio: true } // Video + audioLo primero que debemos hacer es configurar el JavaScript; el código que accede a la cámara de la computadora o dispositivo empleando los prefijos correspondientes para mantener la compatibilidad entre los navegadores web más utilizados (Google Chrome, Mozilla Firefox e Internet Explorer):
navigator.getUserMedia = (navigator.getUserMedia ||
navigator.webkitGetUserMedia ||
navigator.mozGetUserMedia ||
navigator.msGetUserMedia);Ya creado el objeto getUserMedia en el paso anterior, lo siguiente es inicializarlo con los siguientes parámetros:
constraints: este objeto toma dos parámetros booleanos: video y audio, como podrás imaginar debemos especificar al menos uno de ellos para obtener el flujo de datos al que queremos acceder; casos posibles:{ video: true, audio: true }: Habilitamos ambas opciones; por lo tanto; el flujo de datos nos proporcionará video y audio.{ video: true, audio: false }: Habilitamos solo el video; por lo tanto; el flujo de datos nos proporcionará solo video.{ video: false, audio: true }: Habilitamos solo el audio; por lo tanto; el flujo de datos nos proporcionará solo audio.{ video: false, audio: false}: Esta opción NO es válida.successCallback: Esta función es llamada si el usuario permite el acceso a su cámara y/o micrófono y cuando el flujo de datos fue cargado; por lo tanto, esta función nos proporcionará un objeto del tipoLocalMediaStreamque contiene el flujo de datos para ser manipulado y asignado en el objeto apropiado o correspondiente, para este tutorial, será el tag<video>.errorCallback (opcional): Esta función es la negación de la anterior; es decir; si el usuario denegó el acceso o el flujo de datos no pudo ser cargado por alguna razón, se ejecutará esta función, la cual provee alguno de los siguientes códigos de errores:
| Error | Descripción |
|---|---|
| PERMISSION_DENIED | El usuario denegó el permiso para usar el dispositivo multimedia requerido para esta operación. |
| NOT_SUPPORTED_ERROR | Un constraint especificado no es soportado por el navegador. |
| MANDATORY_UNSATISFIED_ERROR | No se encontraron fuentes multimedia del tipo especificado en el constraints. |
| NO_DEVICES_FOUND | No se encontró ninguna webcam. |
Disponible en Firefox Developer.
Accediendo a la cámara y el micrófono de un dispositivo con JavaScript: Ejemplo
El código JavaScript completo del ejemplo:
navigator.getUserMedia = ( navigator.getUserMedia ||
navigator.webkitGetUserMedia ||
navigator.mozGetUserMedia ||
navigator.msGetUserMedia);
navigator.getUserMedia (
// constraints
{
video: true,
audio: false
},
// successCallback
function(localMediaStream) {
var video = document.querySelector(video);
video.src = window.URL.createObjectURL(localMediaStream);
},
// errorCallback
function(err) {
console.log("Ocurrió el siguiente error: " + err);
}
);Para resumirlo, primero asignamos el constraints, indicando que solo nos interesa el video y no el audio:
// constraints
{
video: true,
audio: false
},Si no ocurrió ningún error, asignaremos el flujo de datos devuelto en el objeto LocalMediaStream en un tag video:
// successCallback
function(localMediaStream) {
var video = document.querySelector(video);
video.src = window.URL.createObjectURL(localMediaStream);
},Por último, manejamos los errores (si lo hay):
// errorCallback
function(err) {
console.log("Ocurrió el siguiente error: " + err);
}- No podemos usar
getUserMediaen páginas que usen en sus URLs file://. - Esta API solicita permiso al usuario para acceder a la cámara y al micrófono.
Una forma resumida y más moderna del ejercicio anterior:
navigator.mediaDevices.getUserMedia({ video: true })
.then(stream => {
const video = document.querySelector("video");
video.srcObject = stream;
})
.catch(error => {
console.error("Ocurrió un error:", error);
});▶️ Mostrar el video en un elemento <video>
Tu HTML puede ser tan simple como esto:
<video autoplay playsinline></video>Y sí: en cuanto el usuario apruebe el permiso, DISFRUTA, el video aparecerá como por arte de magia… como en una app nativa.
️ Cómo acceder también al micrófono
Usar el micrófono es igual de sencillo que usar la cámara:
navigator.mediaDevices.getUserMedia({ audio: true })
.then(stream => {
console.log("Micrófono listo");
});️ Audio + video en el mismo stream
Si quieres ambos, solo mezcla constraints:
navigator.mediaDevices.getUserMedia({
video: true,
audio: true
})
.then(stream => {
const video = document.querySelector("video");
video.srcObject = stream;
});Tomar fotos desde la webcam (canvas + captura)
Este es uno de mis usos favoritos.
Para capturar una imagen desde el <video>, solo necesitas un <canvas>.
️ Vincular el <canvas> con el stream
Podemos también usar el Canvas para renderizar el vídeo:
<video autoplay playsinline></video>
<canvas id="canvas" width="640" height="480"></canvas>
<button id="capture">Tomar foto</button>Código:
const video = document.querySelector("video");
const canvas = document.getElementById("canvas");
const ctx = canvas.getContext("2d");
document.getElementById("capture").addEventListener("click", () => {
ctx.drawImage(video, 0, 0, canvas.width, canvas.height);
});Cuando implementé esto en un proyecto, ver la imagen congelada en el canvas fue como tener Photoshop integrado en la web.
Guardar o descargar la imagen
const dataURL = canvas.toDataURL("image/png");
// Puedes abrirla o descargarla
console.log(dataURL);❌ Manejo de errores y permisos denegados
Aquí es donde los errores más comunes:
- PERMISSION_DENIED
- Ocurre cuando el usuario rechaza el acceso.
Suele pasar mucho cuando el navegador ya había bloqueado permisos previamente.
- Ocurre cuando el usuario rechaza el acceso.
- NOT_SUPPORTED_ERROR
- Significa que el constraint solicitado no existe en ese dispositivo.
- Por ejemplo: pedir video en un equipo sin cámara.
- MANDATORY_UNSATISFIED_ERROR / NO_DEVICES_FOUND
- No se encontró cámara o micrófono disponible.
Consejos prácticos después de implementarlo en proyectos reales
- Nunca pruebes desde file://, no funcionará. Usa un servidor local.
- Evita usar APIs con prefijos (webkitGetUserMedia): están obsoletas.
- Siempre captura errores, sobre todo en móviles.
- Comprueba permisos anteriores: algunos navegadores recuerdan decisiones previas.
- Si necesitas grabar video, añade MediaRecorder a tu flujo (opcional).
❓ Preguntas Frecuentes
- ¿Por qué no funciona mi cámara si abro el archivo directamente?
- Porque file:// no tiene permisos. Usa un servidor local o HTTPS.
- ¿Puedo capturar fotos sin plugins?
- Sí. Solo necesitas <video> + <canvas>.
- ¿Cómo capturo también el micrófono?
- Incluye { audio: true } en tus constraints.
- ¿Es necesario usar srcObject?
- Sí, es el método moderno recomendado.
- ¿Qué pasa si el usuario niega los permisos?
- Debes capturar el error y mostrar un mensaje amigable.
Conclusión
Acceder a la cámara y micrófono con JavaScript es más fácil de lo que parece. Con la API moderna de mediaDevices.getUserMedia, puedes crear desde simples capturas de foto hasta aplicaciones completas de grabación, streaming y videollamadas.
La clave está en dominar los constraints, mostrar correctamente el stream, manejar errores reales y entender cómo funcionan los permisos. A partir de aquí, puedes construir cualquier herramienta multimedia basada en navegador.
Acepto recibir anuncios de interes sobre este Blog.
Aprende paso a paso a acceder a la cámara y micrófono con JavaScript usando la API getUserMedia. Te enseñamos a mostrar el video, capturar fotos con canvas y solucionar los errores más comunes. ¡Crea aplicaciones web interactivas hoy mismo!