What are the different events that the video tag generates?

Grabar video HTML5: Guía completa con getUserMedia

hace 10 años

★★★★★Valoración: 4.7 (2628 votos)

Durante mucho tiempo, la capacidad de capturar audio y video en la web fue un desafío, considerado casi un “Santo Grial” para los desarrolladores. En el pasado, dependíamos de complementos de navegador como Flash o Silverlight para lograrlo. Afortunadamente, con la evolución de HTML5, el panorama cambió drásticamente.

How to record an HTML5 video?
CAPTURE AUDIO AND VIDEO IN HTML5 , Introduction. , The road to getUserMedia() Round 1: HTML Media Capture. Round 2: device element. Round 3: WebRTC. , Getting started. Feature detection. Gaining access to an input device. Setting media constraints (resolution, height, width) Selecting a media source. Security. Providing fallback.

Puede que no sea inmediatamente obvio, pero el auge de HTML5 trajo consigo un acceso mucho mayor al hardware de los dispositivos. Piénsese en la geolocalización (GPS), la API de Orientation (acelerómetro), WebGL (GPU) y la API de Web Audio (hardware de audio). Estas funciones son increíblemente poderosas y exponen APIs de JavaScript de alto nivel que se construyen sobre las capacidades de hardware subyacentes del sistema. En este contexto, surge la API GetUserMedia, que permite a las aplicaciones web acceder a la cámara y al micrófono de un usuario.

Índice de Contenido

El camino hacia getUserMedia()

La historia de cómo llegamos a la API getUserMedia() es bastante interesante y refleja la evolución de las APIs web. En los años previos a su estandarización, surgieron diversas variantes de las "APIs de captura de contenido multimedia". La necesidad de acceder a los dispositivos nativos desde la web era evidente para muchos, pero esto llevó a una proliferación de propuestas y especificaciones, creando un panorama confuso. Ante esta situación, el W3C decidió formar un grupo de trabajo, el Grupo de Trabajo de Política de APIs de Dispositivos (DAP), con el objetivo de consolidar y estandarizar estas propuestas.

Para entender el contexto, podemos resumir brevemente la evolución de las APIs de captura de contenido multimedia en los años previos a la adopción generalizada de getUserMedia:

Ronda 1: Captura de contenido multimedia HTML

La Captura de contenido multimedia HTML fue el primer intento del DAP para estandarizar la captura de contenido multimedia en la web. Su enfoque principal fue reutilizar el elemento <input type="file">, sobrecargándolo y agregando nuevos valores para el parámetro accept.

Por ejemplo, si se deseaba permitir a los usuarios tomar una foto con la cámara web, se podía lograr utilizando capture=camera:

<input type="file" accept="image/*;capture=camera"> 

De manera similar, la grabación de audio o video se podía realizar con los siguientes inputs:

<input type="file" accept="video/*;capture=camcorder"> <input type="file" accept="audio/*;capture=microphone"> 

Esta aproximación tenía la ventaja de la sencillez y la reutilización del elemento <input type="file">, lo cual semánticamente tenía sentido. Sin embargo, la principal limitación de esta "API" era su incapacidad para realizar efectos en tiempo real. La Captura de contenido multimedia HTML solo permitía grabar un archivo multimedia o tomar una instantánea en un momento dado, pero no procesar la transmisión de video en vivo para aplicar filtros WebGL o renderizarla en un <canvas>.

Soporte inicial:

  • Navegador de Android 3.0: Fue una de las primeras implementaciones.
  • Chrome para Android (0.16)
  • Firefox para dispositivos móviles 10.0
  • Safari y Chrome para iOS6 (soporte parcial)

Ronda 2: Elemento <device>

Muchos desarrolladores consideraron que la Captura de contenido multimedia HTML era demasiado limitada, lo que impulsó la creación de una nueva especificación que admitiera cualquier tipo de dispositivo (preparándose para el futuro). El diseño propuesto introdujo un nuevo elemento HTML, el elemento <device>, que se convirtió en el precursor directo de getUserMedia().

Opera fue uno de los primeros navegadores en implementar versiones iniciales de captura de video basadas en el elemento <device>. Poco después, el WhatWG (el grupo de trabajo detrás del estándar HTML) decidió descartar la etiqueta <device> en favor de una API de JavaScript más prometedora llamada navigator.getUserMedia(). Una semana después, Opera lanzó nuevas versiones de su navegador que incluían soporte para la especificación actualizada de getUserMedia(). Más adelante, Microsoft también se unió a esta iniciativa y lanzó un "Lab" para IE9 que admitía la nueva especificación.

Así es como se habría utilizado el elemento <device>:

<device type="media" onchange="update(this.data)"></device> <video autoplay></video> <script> function update(stream) { document.querySelector('video').src = stream.url; } </script> 

Soporte:

Desafortunadamente, ningún navegador lanzado al público incluyó el elemento <device>. Aunque la idea del elemento <device> tenía algunos aspectos positivos, como su naturaleza semántica y su potencial extensibilidad para admitir más tipos de dispositivos, finalmente fue reemplazada por un enfoque basado en JavaScript.

Ronda 3: WebRTC

El elemento <device> finalmente desapareció, pero la necesidad de una API de captura de contenido multimedia seguía siendo fundamental. El ritmo para encontrar una solución adecuada se aceleró gracias al auge del proyecto WebRTC (Web Real Time Communications). El grupo de trabajo de WebRTC del W3C supervisa esta especificación, con implementaciones de empresas como Google, Opera y Mozilla.

getUserMedia() está intrínsecamente ligada a WebRTC, ya que actúa como la puerta de entrada a este conjunto de APIs. Proporciona los medios para acceder a la transmisión local de la cámara o el micrófono del usuario, que luego pueden ser utilizados por las APIs de WebRTC para establecer comunicaciones de video y audio en tiempo real.

Soporte:

getUserMedia() comenzó a ser compatible a partir de Chrome 21, Opera 18 y Firefox 17, marcando un punto de inflexión en la accesibilidad a los dispositivos multimedia en la web.

Cómo empezar con getUserMedia()

Con navigator.mediaDevices.getUserMedia(), finalmente podemos acceder a la entrada de la cámara web y del micrófono sin necesidad de complementos externos. Acceder a la cámara se reduce a una simple llamada, integrándose directamente en el navegador.

Detección de características

La detección de la API es tan sencilla como verificar la existencia de navigator.mediaDevices.getUserMedia:

if (navigator.mediaDevices?.getUserMedia) { // ¡Disponible! } else { alert("navigator.mediaDevices.getUserMedia() no es compatible"); } 

Obtener acceso a un dispositivo de entrada

Para utilizar la cámara web o el micrófono, es necesario solicitar permiso al usuario. El primer parámetro de navigator.mediaDevices.getUserMedia() es un objeto que especifica los detalles y requisitos de cada tipo de contenido multimedia al que se desea acceder. Por ejemplo, para acceder a la cámara web, el primer parámetro debe ser {video: true}. Para usar tanto el micrófono como la cámara, se pasa {video: true, audio: true}:

<video autoplay></video> <script> navigator.mediaDevices .getUserMedia({ video: true, audio: true }) .then((localMediaStream) => { const video = document.querySelector("video"); video.srcObject = localMediaStream; }) .catch((error) => { console.log("¡Rechazado!", error); }); </script> 

En este código, la captura de contenido multimedia se integra perfectamente con los elementos <audio> y <video> de HTML5. En lugar de configurar el atributo src o incluir elementos <source> en el elemento <video>, configuramos la propiedad srcObject con el objeto LocalMediaStream que representa la transmisión de la cámara web.

Además, se utiliza el atributo autoplay en el elemento <video> para que el video comience a reproducirse automáticamente. También se puede agregar el atributo controls para proporcionar controles de reproducción al usuario.

Cómo establecer restricciones de contenido multimedia (resolución, altura y ancho)

El primer parámetro de getUserMedia() también permite especificar requisitos o restricciones adicionales en la transmisión de contenido multimedia. Por ejemplo, en lugar de simplemente solicitar acceso básico al video ({video: true}), se puede exigir que la transmisión sea en alta definición (HD):

const hdConstraints = { video: { width: { exact: 1280 }, height: { exact: 720 } }, }; const stream = await navigator.mediaDevices.getUserMedia(hdConstraints); const vgaConstraints = { video: { width: { exact: 640 }, height: { exact: 360 } }, }; const stream = await navigator.mediaDevices.getUserMedia(hdConstraints); 

En estos ejemplos, se definen restricciones para la resolución de video, solicitando resoluciones exactas de 1280x720 (HD) y 640x360 (VGA). Para obtener una lista completa de los parámetros de configuración y restricciones disponibles, se puede consultar la API de restricciones (MediaTrackConstraints) en MDN.

Cómo seleccionar una fuente de contenido multimedia

El método enumerateDevices() de la interfaz MediaDevices permite solicitar una lista de los dispositivos de entrada y salida de contenido multimedia disponibles, como micrófonos, cámaras, auriculares, etc. Este método devuelve una promesa que se resuelve con un array de objetos MediaDeviceInfo, cada uno describiendo un dispositivo.

El siguiente ejemplo muestra cómo seleccionar el último micrófono y la última cámara encontrados como fuentes para la transmisión de contenido multimedia:

if (!navigator.mediaDevices?.enumerateDevices) { console.log("enumerateDevices() no es compatible."); } else { // Listar cámaras y micrófonos. navigator.mediaDevices .enumerateDevices() .then((devices) => { let audioSource = null; let videoSource = null; devices.forEach((device) => { if (device.kind === "audioinput") { audioSource = device.deviceId; } else if (device.kind === "videoinput") { videoSource = device.deviceId; } }); sourceSelected(audioSource, videoSource); }) .catch((err) => { console.error(`${err.name}: ${err.message}`); }); } async function sourceSelected(audioSource, videoSource) { const constraints = { audio: { deviceId: audioSource }, video: { deviceId: videoSource }, }; const stream = await navigator.mediaDevices.getUserMedia(constraints); } 

En este código, se itera sobre la lista de dispositivos obtenida con enumerateDevices(). Se identifican los dispositivos de tipo "audioinput" (micrófonos) y "videoinput" (cámaras) y se almacenan sus deviceId. Luego, se llama a la función sourceSelected, que utiliza estos deviceId para configurar las restricciones en getUserMedia(), seleccionando así las fuentes de audio y video específicas.

Seguridad y permisos

Un aspecto crucial de getUserMedia() es la seguridad. Los navegadores implementan un diálogo de permisos que se muestra al usuario la primera vez que una página web llama a navigator.mediaDevices.getUserMedia(). Este diálogo pregunta al usuario si desea otorgar o rechazar el acceso a su cámara y/o micrófono.

Este mecanismo de permisos es fundamental para proteger la privacidad del usuario, asegurando que ninguna página web pueda acceder a la cámara o al micrófono sin su consentimiento explícito.

Diálogo de permisos en Chrome:

[Aquí iría una descripción de la imagen del diálogo de permisos de Chrome, si se incluyera una imagen]

Proporcionar alternativas (Fallback)

Para los usuarios que utilizan navegadores que no son compatibles con navigator.mediaDevices.getUserMedia(), o en caso de que la llamada a la API falle por alguna razón, es importante proporcionar una alternativa o fallback. Una opción común es recurrir a un archivo de video existente.

Por ejemplo, se podría mostrar un mensaje indicando que la grabación de video no es compatible en su navegador y ofrecer la opción de cargar un archivo de video pregrabado.

Conclusión

La API getUserMedia() representa un avance significativo en el desarrollo web, abriendo un mundo de posibilidades para la creación de experiencias interactivas y multimedia directamente en el navegador. Desde videoconferencias y aplicaciones de realidad aumentada hasta herramientas de creación de contenido y juegos interactivos, getUserMedia() permite a los desarrolladores aprovechar el poder de la cámara y el micrófono de los usuarios de manera segura y sencilla.

A pesar de su relativa complejidad histórica y las diferentes iteraciones que llevaron a su estandarización, getUserMedia() se ha consolidado como una API fundamental para la captura de contenido multimedia en la web moderna, democratizando el acceso a estas funcionalidades y eliminando la dependencia de complementos externos.

Subir