Capturer un flux vidéo à partir de n'importe quel élément

François Beaufort
François Beaufort

L'API Screen Capture vous permet de capturer l'intégralité de l'onglet actif. L'API Element Capture vous permet de capturer et d'enregistrer un élément HTML spécifique. Elle transforme une capture de l'intégralité de l'onglet en une capture d'une sous-arborescence DOM spécifique, ne capturant que les descendants directs de l'élément cible. En d'autres termes, il recadre et supprime à la fois le contenu occlus et occlus.

Pourquoi utiliser Element Capture ?

Tenir compte des exigences d'une application de visioconférence peut vous aider à comprendre dans quelle mesure la capture d'élément est utile. Si vous disposez d'une application de visioconférence qui vous permet d'intégrer des applications tierces dans un iFrame, vous souhaiterez peut-être parfois capturer cet iFrame sous forme de vidéo et le transmettre à des participants distants.

Capture d'écran d'un appel de visioconférence dans Chrome.
Elad utilise une application tierce lors d'un appel en visioconférence avec François.

Appeler getDisplayMedia() et laisser l'utilisateur choisir l'onglet actuel transmettra l'intégralité de l'onglet actuel. Cela est susceptible de leur transmettre la propre vidéo. Vous pouvez recadrer cette image à l'aide de la fonctionnalité Region Capture.

Cependant, que se passe-t-il si le présentateur interagit avec l'application de visioconférence et que certains contenus, tels qu'une liste déroulante, se superposent au contenu destiné à la capture ?

Capture d'écran d'une liste déroulante recouvrant le contenu destiné à la capture.
Une liste déroulante s'affiche en haut du contenu à capturer.

La capture de la région ne vous serait d'aucune utilité. Une partie de la liste déroulante peut être visible sur l'écran des participants à distance.

Capture d'écran d'une liste déroulante.
La liste déroulante d'Elad s'affiche en haut du contenu reçu par François.

Le fait que Region Capture capture certaines parties des éléments de cette manière (c'est-à-dire occlusion de contenu), pose plusieurs problèmes:

  • Cela peut empêcher l'affichage du contenu que l'utilisateur avait l'intention de partager.
  • Certains contenus peuvent être privés (comme les notifications de chat).
  • Masquer le contenu peut prêter à confusion. (Par exemple, une nouvelle mise en page de l'application pourrait amener brièvement les propres vidéos des participants à distance sur la cible capturée.)

L'API Element Capture résout tous ces problèmes en vous permettant de cibler l'élément que vous souhaitez partager.

Capture d'écran de l'élément cible sans liste déroulante affichée
François ne voit pas la liste déroulante d'Elad.

Comment utiliser la capture d'élément ?

captureTarget est un élément de votre page qui comporte le contenu que l'utilisateur souhaite capturer. Vous souhaitez que l'application Web de visioconférence capture captureTarget et le partage avec des participants à distance. Vous obtenez donc RestrictionTarget à partir de captureTarget. Une fois la piste vidéo restreinte à l'aide de ce RestrictionTarget, les images de cette piste vidéo ne se composent plus que des pixels qui font partie de captureTarget et de ses descendants DOM directs.

Si captureTarget change de taille, de forme ou d'emplacement, la piste vidéo suit le mouvement, sans nécessiter aucune autre action de la part de l'une ou l'autre des applications Web. Les contenus masqués qui apparaissent, disparaissent ou se déplacent ne nécessitent pas non plus de traitement particulier.

Revoyez ces étapes:

Commencez par autoriser l'utilisateur à capturer l'onglet actuel.

// Ask the user for permission to start capturing the current tab.
const stream = await navigator.mediaDevices.getDisplayMedia({
 preferCurrentTab: true,
});
const [track] = stream.getVideoTracks();

Définissez un RestrictionTarget en appelant RestrictionTarget.fromElement() avec un élément de votre choix en entrée.

// Associate captureTarget with a new RestrictionTarget
const captureTarget = document.querySelector("#captureTarget");
const restrictionTarget = await RestrictionTarget.fromElement(captureTarget);

Appelez ensuite restrictTo() sur la piste vidéo avec RestrictionTarget comme entrée. Une fois la dernière promesse résolue, toutes les frames suivantes sont limitées.

// Start restricting the self-capture video track using the RestrictionTarget.
await track.restrictTo(restrictionTarget);

// Enjoy! Transmit remotely.

Présentation détaillée

Détection de caractéristiques

Pour vérifier si RestrictionTarget.fromElement() est compatible, utilisez:

if ("RestrictionTarget" in self && "fromElement" in RestrictionTarget) {
  // Deriving a restriction target is supported.
}

Obtenir un RestrictionTarget

Concentrez-vous sur l'élément appelé captureTarget. Pour obtenir un RestrictionTarget à partir de celui-ci, appelez RestrictionTarget.fromElement(captureTarget). La promesse renvoyée sera résolue avec un nouvel objet RestrictionTarget en cas de réussite. Sinon, elle sera refusée si vous avez frappé un nombre déraisonnable d'objets RestrictionTarget.

const captureTarget = document.querySelector("#captureTarget");
const restrictionTarget = await RestrictionTarget.fromElement(captureTarget);

Contrairement à un élément, un objet RestrictionTarget est sérialisable. Elle peut être transmise à un autre document à l'aide de Window.postMessage(), par exemple.

Restriction

Lors de la capture d'un onglet, la piste vidéo expose restrictTo(). Lors de la capture de l'onglet actuel, il est possible d'appeler restrictTo() avec null ou toute RestrictionTarget dérivée d'un élément de l'onglet actuel.

Les appels à restrictTo(restrictionTarget) transforment la piste vidéo en capture de captureTarget, comme si elle avait été dessinée seule, indépendamment du reste du DOM. Tous les descendants de captureTarget sont également capturés. Les frères et sœurs de captureTarget sont supprimés de la capture. En conséquence, tous les frames diffusés sur la piste apparaissent comme s'ils avaient été recadrés pour respecter les contours de captureTarget, et tout contenu occulté est supprimé.

// Start restricting the self-capture video track using the RestrictionTarget.
await track.restrictTo(restrictionTarget);

Les appels à restrictTo(null) rétablissent la piste à son état d'origine.

// Stop restricting.
await track.restrictTo(null);

Si l'appel à restrictTo() aboutit, la promesse renvoyée est résolue lorsqu'il est possible de garantir que toutes les images vidéo suivantes seront limitées à captureTarget.

En cas d'échec, la promesse est refusée. Un appel au restrictTo() a échoué pour l'une des raisons suivantes:

  • Si l'restrictionTarget a été saisi dans un autre onglet que celui capturé. Notez qu'en utilisant le bouton "Partager cet onglet à la place", les utilisateurs peuvent à tout moment modifier l'onglet capturé.
  • Si restrictionTarget est dérivé d'un élément qui n'existe plus.
  • si le titre a des clones ; Consultez le problème 1509418.
  • Si la piste en cours n'est pas une piste vidéo auto-enregistrée
  • Si l'élément dont restrictionTarget a été dérivé n'est pas éligible à la restriction.

Éléments à prendre en compte pour la capture automatique

Lorsqu'une application appelle getDisplayMedia() et que l'utilisateur choisit de capturer son propre onglet, nous appelons cela une "capture personnelle".

La méthode restrictTo() est exposée sur n'importe quelle piste vidéo de capture d'onglet, et pas seulement pour l'autocapture. Cependant, la capture d'élément n'est activée que pour la capture automatique pour le moment. Il est donc conseillé de vérifier si l'utilisateur a sélectionné l'onglet actif avant d'essayer de restreindre le canal. Pour ce faire, utilisez la commande Capture Handle. Vous pouvez également demander au navigateur d'encourager l'utilisateur à effectuer une capture de son propre contenu à l'aide de preferCurrentTab.

Transparence

Les images vidéo obtenues par l'application via getDisplayMedia() n'incluent pas de canal alpha. Si une application définit une cible de capture partiellement transparente, la suppression de la version alpha peut avoir les conséquences suivantes:

  • Les couleurs peuvent changer. Les éléments cibles partiellement transparents dessinés sur un arrière-plan clair peuvent s'assombrir lorsque le canal alpha est supprimé, et ceux dessinés sur un arrière-plan sombre peuvent apparaître plus clairs.
  • Les couleurs invisibles ou imperceptibles pour l'utilisateur lorsque le canal alpha a été défini sur sa valeur maximale apparaissent une fois le canal alpha supprimé. Par exemple, des zones noires inattendues pourraient apparaître dans les images capturées si les sections transparentes avaient le code RVBA rgba(0, 0, 0, 0).
Capture d'écran du résultat d'une cible de capture transparente non rectangulaire.
Le flux vidéo cible de la capture transparente non rectangulaire (à droite) est un rectangle à fond noir contenant un cercle bleu opaque.

Cibles de capture non éligibles

Il est toujours possible de commencer à limiter un titre à n'importe quelle cible de capture valide. Toutefois, les frames ne seront pas produits dans certaines conditions, par exemple si l'élément ou un ancêtre est display:none. La logique générale est que la restriction ne s'applique qu'à un élément qui comprend une seule zone rectangulaire cohérente, bidimensionnelle et dont les pixels peuvent être déterminés de manière logique indépendamment des éléments parents ou frères.

Il est important de vous assurer que l'élément peut faire l'objet d'une restriction : il doit former son propre contexte d'empilement. Pour ce faire, vous pouvez spécifier la propriété CSS isolation en la définissant sur isolate.

<div id="captureTarget" style="isolation: isolate;"></iframe>

Notez que l'élément cible peut basculer entre les différents critères d'éligibilité et d'inéligibilité à une restriction à tout moment, par exemple si l'application modifie ses propriétés CSS. Il appartient à l'application d'utiliser des cibles de capture raisonnables et d'éviter de modifier leurs propriétés de manière inattendue. Si l'élément cible n'est plus éligible, les nouvelles images ne seront tout simplement pas émises sur la piste tant que l'élément cible ne sera à nouveau pas éligible à la restriction.

Activer la capture d'élément

L'API Element Capture est disponible dans Chrome sur ordinateur derrière l'indicateur Element Capture et peut être activée sur chrome://flags/#element-capture.

Cette fonctionnalité fait également l'objet d'une phase d'évaluation à partir de Chrome 121 sur ordinateur, qui permet aux développeurs d'activer la fonctionnalité pour les visiteurs de leurs sites afin de collecter des données auprès d'utilisateurs réels. Pour en savoir plus, consultez Premiers pas avec les phases d'évaluation.

Sécurité et confidentialité

Pour comprendre les compromis en termes de sécurité, consultez la section Considérations relatives à la confidentialité et à la sécurité de la spécification de capture d'élément.

Le navigateur Chrome dessine une bordure bleue autour des bords des onglets capturés.

Démonstration

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

Commentaires

L'équipe Chrome et la communauté des normes Web souhaitent connaître votre avis sur Element Capture.

Parlez-nous de la conception

Y a-t-il un problème avec la capture de la région qui ne fonctionne pas comme prévu ? Ou s'il manque des méthodes ou des propriétés dont vous avez besoin pour mettre en œuvre votre idée ? Vous avez une question ou un commentaire sur le modèle de sécurité ?

  • Signalez un problème de spécification dans le dépôt GitHub ou ajoutez vos commentaires à un problème existant.

Vous rencontrez un problème lors de l'implémentation ?

Avez-vous détecté un bug dans l'implémentation de Chrome ? Ou l'implémentation est-elle différente des spécifications ?

  • Signalez un bug sur la page https://new.crbug.com. Veillez à fournir autant de détails que possible et des instructions simples pour reproduire le bug. Glitch est idéal pour partager des répétitions rapidement et facilement.

Remerciements

Photo de Paul Skorupskas sur Unsplash