Cómo controlar el desplazamiento lateral, la inclinación y el zoom de la cámara

Las funciones de desplazamiento lateral, inclinación y zoom en las cámaras finalmente se pueden controlar en la Web.

Francisco Beaufort
François Beaufort

Las soluciones de videoconferencia a escala de sala implementan cámaras con funciones de desplazamiento lateral, inclinación y zoom (PTZ) para que el software pueda apuntar la cámara a los participantes de la reunión. A partir de Chrome 87, las funciones de desplazamiento lateral, inclinación y zoom de las cámaras están disponibles para los sitios web que usan restricciones de segmentos multimedia en MediaDevices.getUserMedia() y MediaStreamTrack.applyConstraints().

Cómo usar la API

Detección de funciones

La detección de funciones para hardware es diferente de lo que probablemente estés acostumbrado. La presencia de nombres de restricciones "pan", "tilt" y "zoom" en navigator.mediaDevices.getSupportedConstraints() indica que el navegador es compatible con la API para controlar la PTZ de la cámara, pero no si el hardware de la cámara la admite. A partir de Chrome 87, se admite el control del PTZ de la cámara en computadoras, mientras que Android solo admite el zoom.

const supports = navigator.mediaDevices.getSupportedConstraints();
if (supports.pan && supports.tilt && supports.zoom) {
  // Browser supports camera PTZ.
}

Cómo solicitar acceso a la cámara PTZ

Un sitio web puede controlar el PTZ de la cámara solo si el usuario otorgó explícitamente el permiso PTZ a la cámara a través de un mensaje.

Para solicitar acceso a las PTZ de la cámara, llama a navigator.mediaDevices.getUserMedia() con las restricciones de PTZ, como se muestra a continuación. Esto le pedirá al usuario que otorgue permisos de cámara y cámara normal con permisos de PTZ.

Captura de pantalla de un mensaje del usuario de PTZ de la cámara en Chrome para macOS
Mensaje del usuario de PTZ de la cámara

La promesa que se muestra se resolverá con un objeto MediaStream que se usa para mostrarle al usuario la transmisión de video de la cámara. Si la cámara no admite PTZ, el usuario recibirá un mensaje normal en la cámara.

try {
  // User is prompted to grant both camera and PTZ access in a single call.
  // If camera doesn't support PTZ, it falls back to a regular camera prompt.
  const stream = await navigator.mediaDevices.getUserMedia({
    // Website asks to control camera PTZ as well without altering the
    // current pan, tilt, and zoom settings.
    video: { pan: true, tilt: true, zoom: true }
  });

  // Show camera video stream to user.
  document.querySelector("video").srcObject = stream;
} catch (error) {
  // User denies prompt or matching media is not available.
  console.log(error);
}

Un permiso de cámara otorgado anteriormente, específicamente uno sin acceso a PTZ, no obtiene acceso a PTZ automáticamente si está disponible. Esto es así incluso cuando la cámara admite PTZ. Se debe volver a solicitar el permiso. Por suerte, puedes usar la API de Permissions para consultar y supervisar el estado del permiso PTZ.

try {
  const panTiltZoomPermissionStatus = await navigator.permissions.query({
    name: "camera",
    panTiltZoom: true
  });

  if (panTiltZoomPermissionStatus.state == "granted") {
    // User has granted access to the website to control camera PTZ.
  }

  panTiltZoomPermissionStatus.addEventListener("change", () => {
    // User has changed PTZ permission status.
  });
} catch (error) {
  console.log(error);
}

Para saber si un navegador basado en Chromium admite PTZ para una cámara, ve a la página about://media-internals interna y consulta la columna "Pan-Tilt-Zoom" en la pestaña "Video Capture". "Inclinación lateral" y "zoom" significa que la cámara admite los controles de UVC "PanTilt (absoluto)" y "Zoom (absoluto)". Los controles de UVC "PanTilt (Relative)" y "Zoom (Relative)" no son compatibles con los navegadores basados en Chromium.

Captura de pantalla de la página interna en ChromeOS para depurar la compatibilidad con la cámara PTZ.
Página interna para depurar la compatibilidad con la cámara PTZ

Controlar el horario comercial de la cámara

Manipular las capacidades y la configuración de PTZ de la cámara con la vista previa MediaStreamTrack del objeto stream que obtuviste anteriormente MediaStreamTrack.getCapabilities() muestra un diccionario con las capacidades compatibles y los rangos o los valores permitidos. En consecuencia, MediaStreamTrack.getSettings() muestra la configuración actual.

Las funciones y la configuración de desplazamiento lateral, inclinación y zoom solo están disponibles si son compatibles con la cámara y si el usuario otorgó permiso de PTZ a la cámara.

Cómo controlar la función PTZ de la cámara

Llama a videoTrack.applyConstraints() con las restricciones avanzadas de PTZ adecuadas para controlar el desplazamiento lateral, la inclinación y el zoom de la cámara, como se muestra en el siguiente ejemplo. La promesa que se muestra se resolverá si se realiza correctamente. De lo contrario, se rechazará si se cumple alguna de las siguientes condiciones:

  • la cámara con permiso PTZ no recibe acceso.
  • el hardware de la cámara no admite la restricción de PTZ.
  • la página no es visible para el usuario. Usa la API de visibilidad de páginas para detectar cambios en la visibilidad de la página.
// Get video track capabilities and settings.
const [videoTrack] = stream.getVideoTracks();
const capabilities = videoTrack.getCapabilities();
const settings = videoTrack.getSettings();

// Let the user control the camera pan motion if the camera supports it
// and PTZ access is granted.
if ("pan" in settings) {
  const input = document.querySelector("input[type=range]");
  input.min = capabilities.pan.min;
  input.max = capabilities.pan.max;
  input.step = capabilities.pan.step;
  input.value = settings.pan;

  input.addEventListener("input", async () => {
    await videoTrack.applyConstraints({ advanced: [{ pan: input.value }] });
  });
}

if ("tilt" in settings) {
  // similar for tilt...
}
if ("zoom" in settings) {
  // similar for zoom...
}

También es posible configurar el desplazamiento lateral, la inclinación y el zoom de la cámara llamando a navigator.mediaDevices.getUserMedia() con algunos valores de restricción ideales de PTZ de cámara. Esto es útil cuando las capacidades PTZ de la cámara se conocen de antemano. Ten en cuenta que las restricciones obligatorias (mínimas, máximas y exactas) no se permiten aquí.

const stream = await navigator.mediaDevices.getUserMedia({
  // Website asks to reset known camera pan.
  video: { pan: 0, deviceId: { exact: "myCameraDeviceId" } }
});

Área de juegos

Puedes ejecutar la demostración en Glitch para jugar con la API. Asegúrate de consultar el código fuente.

Consideraciones de seguridad

Los autores de especificaciones diseñaron e implementaron esta API con un enfoque central que incluye el control de usuario, la transparencia y la ergonomía. La capacidad de usar esta API está restringida principalmente por el mismo modelo de permisos que la API de captura y transmisión de contenido multimedia. En respuesta a un mensaje del usuario, el sitio web puede controlar el PTZ de la cámara solo cuando la página es visible para el usuario.

Compatibilidad del navegador

API de MediaStream

Navegadores compatibles

  • 55
  • 12
  • 15
  • 11

Origen

API de Permissions

Navegadores compatibles

  • 43
  • 79
  • 46
  • 16

Origen

API de visibilidad de la página

Navegadores compatibles

  • 33
  • 12
  • 18
  • 7

Origen

MediaDevices.getUserMedia()

Navegadores compatibles

  • 53
  • 12
  • 36
  • 11

Origen

MediaDevices.getSupportedConstraints()

Navegadores compatibles

  • 53
  • 12
  • 44
  • 11

Origen

MediaStreamTrack.applyConstraints()

Navegadores compatibles

  • 59
  • 12
  • 43
  • 11

Origen

MediaStreamTrack.getCapabilities()

Navegadores compatibles

  • 59
  • 12
  • x
  • 11

Origen

MediaStreamTrack.getSettings()

Navegadores compatibles

  • 59
  • 12
  • 50
  • 11

Origen

Vínculos útiles

Agradecimientos

Joe Medley y Thomas Steiner revisaron este artículo. Gracias a Rijubrata Bhaumik y Eero Häkkinen de Intel por su trabajo en la especificación y la implementación. Hero image de Christina @ wocintechchat.com en Unsplash.