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 de las cámaras finalmente se pueden controlar en la Web.

François Beaufort
François Beaufort

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

Cómo usar la API

Detección de funciones

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

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

Solicita acceso PTZ a la cámara

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

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

Captura de pantalla de una solicitud del usuario de PTZ de cámara en Chrome para macOS.
Mensaje del usuario de PTZ de la cámara

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

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 cierto incluso cuando la propia cámara admite PTZ. Se debe solicitar el permiso de nuevo. 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 interna de about://media-internals y consulta el video "Pan, mueble" y "Zoom" columna en la sección "Captura de video" pestaña; "desplazamiento lateral" y "zoom" significan, respectivamente, que la cámara admite el parámetro de configuración "Desplazamiento lateral (absoluto)" y "Zoom (absoluto)" Controles de UVC. La inclinación lateral (relativa) y "Zoom (relativo)" Los controles de UVC 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 la PTZ 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 antes. MediaStreamTrack.getCapabilities() muestra un diccionario con los atributos capacidades y los rangos o valores permitidos. En consecuencia, MediaStreamTrack.getSettings() muestra la configuración actual.

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

Cómo controlar la PTZ de la cámara

Llama a videoTrack.applyConstraints() con la PTZ avanzada adecuada. restricciones 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 tiene éxito. De lo contrario, se rechazará una de las siguientes opciones:

  • la cámara con permiso PTZ no está otorgada.
  • El hardware de la cámara no admite la restricción PTZ.
  • la página no es visible para el usuario. Usa la API de Page Visibility para detectar los 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 navigator.mediaDevices.getUserMedia() con alguna restricción ideal de PTZ de cámara de salida. Esto es útil cuando las capacidades de PTZ de la cámara se conocen de antemano. Nota que las restricciones obligatorias (mínimo, máximo, exacta) no están permitidas en este caso.

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

Área de juegos

Para jugar con la API, ejecuta la demostración en Glitch. Asegúrate de consultar el código fuente.

Consideraciones de seguridad

Los autores de las especificaciones diseñaron e implementaron esta API utilizando la interfaz incluidos el control de usuario, la transparencia y la ergonomía. La capacidad de usar La API está restringida principalmente por el mismo modelo de permisos que la captura de contenido multimedia y API de Streams. En respuesta a una solicitud del usuario, el sitio web puede controlar 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 páginas

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. Agradecemos a Rijubrata Bhaumik y Eero Häkkinen de Intel por su trabajo en la y la implementación. Hero image de Christina @ wocintechchat.com en Unsplash.