Contrôler le panoramique, l'inclinaison et le zoom de la caméra

Les fonctionnalités de panoramique, d'inclinaison et de zoom des caméras sont enfin contrôlables sur le Web.

François Beaufort
François Beaufort

Les solutions de visioconférence en salle déploient des caméras avec des fonctionnalités de panoramique, d'inclinaison et de zoom (PTZ) afin que le logiciel puisse diriger la caméra vers les participants à la réunion. À partir de Chrome 87, les fonctionnalités de panoramique, d'inclinaison et de zoom des caméras sont disponibles pour les sites Web qui utilisent des contraintes de piste multimédia dans MediaDevices.getUserMedia() et MediaStreamTrack.applyConstraints().

Utilisation de l'API

Détection de fonctionnalités

La détection des fonctionnalités sur le matériel est différente de ce à quoi vous êtes probablement habitué. La présence des noms de contraintes "pan", "tilt" et "zoom" dans navigator.mediaDevices.getSupportedConstraints() vous indique que le navigateur est compatible avec l'API pour contrôler la PTZ de la caméra, mais pas si elle est compatible ou non. Depuis Chrome 87, il est possible de contrôler le PTZ de la caméra sur ordinateur, tandis qu'Android ne prend en charge que le zoom.

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

Demander l'accès à la caméra PTZ

Un site Web n'est autorisé à contrôler les commandes PTZ de la caméra que si l'utilisateur a explicitement accordé à la caméra l'autorisation PTZ via une invite.

Pour demander l'accès à la caméra PTZ, appelez navigator.mediaDevices.getUserMedia() avec les contraintes de la zone PTZ, comme indiqué ci-dessous. L'utilisateur sera invité à accorder l'accès à la caméra et à la caméra standards avec les autorisations PTZ.

Capture d'écran d'une invite utilisateur pour une caméra PTZ dans Chrome pour macOS.
Invite utilisateur de la caméra PTZ.

La promesse renvoyée se résout avec un objet MediaStream permettant de présenter le flux vidéo de la caméra à l'utilisateur. Si la caméra n'est pas compatible avec la fonctionnalité PTZ, l'utilisateur recevra une invite standard.

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);
}

Une autorisation d'appareil photo précédemment accordée, en particulier sans accès PTZ, n'obtient pas automatiquement l'accès PTZ si celui-ci devient disponible. même lorsque la caméra est elle-même compatible avec la fonctionnalité PTZ. L'autorisation doit être demandée à nouveau. Heureusement, vous pouvez utiliser l'API Permissions pour interroger et surveiller l'état de l'autorisation 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);
}

Pour savoir si un navigateur basé sur Chromium est compatible avec les commandes PTZ d'une caméra, accédez à la page interne about://media-internals et consultez la colonne "Pan-Tilt-Zoom" (Panorama, inclinaison et zoom) dans l'onglet "Video Capture" (Capture vidéo). "Pan-Tilt" (Panorama, inclinaison) et "Zoom" (Zoom) signifient respectivement que la caméra est compatible avec les commandes UVC "PanTilt (Absolute)" (Panorama, inclinaison (absolue)) et "Zoom (Absolute)" (Zoom (absolu)). Les commandes UVC "PanTilt (Relative)" (Pan-Tilt (Relative)) et "Zoom (Relative)" (Zoom (Relative)) ne sont pas compatibles avec les navigateurs basés sur Chromium.

Capture d'écran de la page interne de ChromeOS pour déboguer la compatibilité de la caméra PTZ.
Page interne permettant de déboguer la compatibilité avec les caméras PTZ.

Contrôler le PTZ de la caméra

Manipulez les fonctionnalités et les paramètres PTZ de l'appareil photo à l'aide de l'aperçu MediaStreamTrack de l'objet stream obtenu précédemment. MediaStreamTrack.getCapabilities() renvoie un dictionnaire contenant les fonctionnalités compatibles et les plages ou valeurs autorisées. De même, MediaStreamTrack.getSettings() renvoie les paramètres actuels.

Les fonctionnalités et les paramètres de panoramique, d'inclinaison et de zoom ne sont disponibles que si la caméra les prend en charge et que l'utilisateur a accordé à la caméra l'autorisation PTZ.

Contrôle du PTZ de la caméra

Appelez videoTrack.applyConstraints() avec les contraintes avancées PTZ appropriées pour contrôler le panoramique, l'inclinaison et le zoom de la caméra, comme illustré dans l'exemple ci-dessous. La promesse renvoyée sera résolue si l'opération réussit. Sinon, il sera refusé si :

  • l'accès à la caméra avec l'autorisation PTZ n'est pas autorisé.
  • l'appareil photo n'est pas compatible avec la contrainte PTZ.
  • la page n'est pas visible par l'utilisateur. Utilisez l'API Page Visibility pour détecter les modifications de la visibilité des pages.
// 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...
}

Il est également possible de configurer le panoramique, l'inclinaison et le zoom de la caméra en appelant navigator.mediaDevices.getUserMedia() avec certaines valeurs de contrainte idéales de la caméra PTZ. Cette option est utile lorsque les fonctionnalités PTZ de la caméra sont connues à l'avance. Notez que les contraintes obligatoires (min, max, exact) ne sont pas autorisées ici.

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

Aire de jeu

Vous pouvez tester l'API en exécutant la démo sur Glitch. N'oubliez pas de consulter le code source.

Considérations de sécurité

Les auteurs de la spécification ont conçu et implémenté cette API à l'aide du noyau, y compris le contrôle utilisateur, la transparence et l'ergonomie. La possibilité d'utiliser cette API est principalement limitée par le même modèle d'autorisation que l'API Media Capture and Streams. En réponse à une invite de l'utilisateur, le site Web n'est autorisé à contrôler le PTZ de la caméra que lorsque la page est visible par l'utilisateur.

Compatibilité du navigateur

API MediaStream

Navigateurs pris en charge

  • Chrome : 55.
  • Edge: 12
  • Firefox: 15
  • Safari : 11.

Source

API Permissions

Navigateurs pris en charge

  • Chrome : 43.
  • Edge : 79.
  • Firefox : 46.
  • Safari : 16.

Source

API Page Visibility

Navigateurs pris en charge

  • Chrome : 33.
  • Edge : 12.
  • Firefox : 18.
  • Safari : 7.

Source

MediaDevices.getUserMedia()

Navigateurs pris en charge

  • Chrome : 53.
  • Edge: 12
  • Firefox : 36.
  • Safari: 11.

Source

MediaDevices.getSupportedConstraints()

Navigateurs pris en charge

  • Chrome : 53.
  • Edge : 12.
  • Firefox : 44.
  • Safari : 11.

Source

MediaStreamTrack.applyConstraints()

Navigateurs pris en charge

  • Chrome : 59.
  • Edge: 12
  • Firefox : 43.
  • Safari : 11.

Source

MediaStreamTrack.getCapabilities()

Navigateurs pris en charge

  • Chrome : 59.
  • Edge : 12.
  • Firefox : 132.
  • Safari : 11.

Source

MediaStreamTrack.getSettings()

Navigateurs pris en charge

  • Chrome: 59
  • Edge : 12.
  • Firefox : 50.
  • Safari : 11.

Source

Liens utiles

Remerciements

Cet article a été examiné par Joe Medley et Thomas Steiner. Merci à Rijubrata Bhaumik et Eero Häkkinen d'Intel pour leur travail sur les spécifications et l'implémentation. Image principale par Christina @ wocintechchat.com sur Unsplash.