Accediendo a la cámara y el micrófono de un dispositivo con JavaScript

- 👤 Andrés Cruz

🇺🇸 In english

Accediendo a la cámara y el micrófono de un dispositivo con JavaScript

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.

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 + audio

Lo 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 tipo LocalMediaStream que 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:
ErrorDescripción
PERMISSION_DENIEDEl usuario denegó el permiso para usar el dispositivo multimedia requerido para esta operación.
NOT_SUPPORTED_ERRORUn constraint especificado no es soportado por el navegador.
MANDATORY_UNSATISFIED_ERRORNo se encontraron fuentes multimedia del tipo especificado en el constraints.
NO_DEVICES_FOUNDNo 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 getUserMedia en 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.
  • 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

  1. ¿Por qué no funciona mi cámara si abro el archivo directamente?
    1. Porque file:// no tiene permisos. Usa un servidor local o HTTPS.
  2. ¿Puedo capturar fotos sin plugins?
    1. Sí. Solo necesitas <video> + <canvas>.
  3. ¿Cómo capturo también el micrófono?
    1. Incluye { audio: true } en tus constraints.
  4. ¿Es necesario usar srcObject?
    1. Sí, es el método moderno recomendado.
  5. ¿Qué pasa si el usuario niega los permisos?
    1. 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!

| 👤 Andrés Cruz

🇺🇸 In english