7min.

Camera stream dans un navigateur

This blog post is also available in 🇬🇧 English: Camera stream in Web.

Aujourd’hui, presque tous les téléphones ou ordinateurs portables possèdent une ou plusieurs caméra. Dans cet article, nous allons nous concentrer sur les améliorations que cet élément peut apporter dans l’utilisation de nos appareils. Nous parlerons principalement de la vidéo et garderons la partie audio pour une autre fois.

Avec HTML5 et le développement du WebRTC l’utilisation de la caméra dans le web est devenue plus simple. En effet, avant HTML5, dans un navigateur, une vidéo pouvait être lue seulement avec l’aide d’un plug-in (dépassé, n’est-ce pas ?). L’adaptation des navigateurs reste le seul point négatif dans le domaine.

Section intitulée etat-de-l-artÉtat de l’art

Dans un premier temps, l’accès à la caméra a insufflé la création de sites artistiques ou événementiels. De nombreux projets, au début du creative development, étaient basés sur la caméra. Un bon nombre d’entre eux sont maintenant dépassés à cause des modifications de la web API et de la compatibilité des navigateurs. La Media Stream API a effectivement changé la façon de recevoir les données. L’accès aux composants d’un téléphone ou d’un ordinateur a aussi évolué.

Accéder à la sortie vidéo sous-entend la modifier. Nous pouvons toujours trouver des exemples qui fonctionnent :

test 1

test 2

Grâce à la récupération de la composition des pixels d’une image au travers d’un élément canvas, cette transformation est rendue possible.

Cette première étape est importante, mais la caméra a bien plus à offrir qu’une simple retransmission.

Chaque image peut être fusionnée par différence avec la précédente, ce qui permet de récupérer la différence pixel par pixel entre deux images et donc le mouvement. Chaque pixel modifié comprenant un couple de coordonnées. Cela signifie qu’il est non seulement possible d’afficher ou de modifier un flux vidéo mais aussi d’interagir avec celui-ci.

test 3

test 4

Néanmoins, les exemples d’utilisation de la caméra dans le web étaient peu nombreux et manquaient de variété. L’étape suivante fut l’arrivée et la popularisation de la détection de visage/bouche/yeux. De nombreuses librairies se sont vite développées dans ce domaine, accompagnées par la reconnaissance du mouvement.

La détection du visage a été en grande partie popularisée avec les filtres de l’application Snapchat et le mouvement avec la Kinect.

Tout cela a amené à la création de jeux mobiles (application).

TrackingJS est une librairie permettant l’exploitation de toutes les interactions précédemment listées et même plus (détection de couleur/bordure).

test 5

Tous ces moyens d’interactions ont été le point de départ de nombreux projets dans les domaines de la publicité, des réseaux sociaux, de la sécurité (par exemple : FaceID sur iPhone X), des essais en ligne et du e-commerce

Mais la détection de mouvement semble assez incomplète. L’accès aux données de la caméra est totalement géré, cependant, il manque une analyse rapide et complète de l’image afin d’en détecter le contenu.

Un second problème réside dans le support tardif de certains navigateurs (IE et Safari). Sur mobile, Android fonctionne depuis février 2017. Le WebRTC n’était toujours pas supporté sur iOS jusqu’au 19 septembre 2017, date de la sortie d’iOS 11, à partir duquel Safari supporte le WebRTC 🎉. Firefox et Chrome iOS devraient suivre.

Stream API Support

Avec l’évolution des capacités 3D des appareils, il est possible d’utiliser les données vidéos pour en réaliser une exploitation 3D.

Section intitulée comment-recuperer-les-donneesComment récupérer les données ?

L’API Processing MediaStream, souvent appelée Media Stream API ou Stream API, est la partie de WebRTC décrivant un flux de données audio ou vidéo, les méthodes pour les manipuler, les contraintes associées au type de données, les erreurs et succès des callbacks avec les données asynchrones, et les événements déclenchés durant le processus. La sortie d’un objet MediaStream est liée à un consommateur. Elle peut être un élément média tel que <audio> ou <video>, l’API WebRTC PeerConnection ou l’API Web Audio.

Section intitulée code-de-recuperation-du-flux-videoCode de récupération du flux vidéo

const constraints = {
  audio: true,
  video: {
    width: { min: canvasWidth },
    height: { min: canvasHeight }
  }
}

if (typeof navigator.mediaDevices === 'undefined') {
        navigator.mediaDevices = {};
      }
      if (typeof navigator.mediaDevices.getUserMedia === 'undefined') {
        navigator.mediaDevices.getUserMedia = function(constraints) {
          // First get ahold of the legacy getUserMedia, if present
          var getUserMedia = navigator.webkitGetUserMedia || navigator.mozGetUserMedia;
          // Some browsers just don't implement it - return a rejected promise with an error
          // to keep a consistent interface
          if (!getUserMedia) {
            return Promise.reject(new Error('getUserMedia is not implemented in this browser'));
          }
          // Otherwise, wrap the call to the old navigator.getUserMedia with a Promise
          return new Promise(function(resolve, reject) {
            getUserMedia.call(navigator, constraints, resolve, reject);
          });
        }
      }

navigator.mediaDevices
        .getUserMedia(constraints)
        .then(initSuccess)
        .catch(function(err) {
  console.log(err.name + ": " + err.message);
});

function initSuccess(requestedStream) {
  var video = document.querySelector('video');
  // Older browsers may not have srcObject
  if ("srcObject" in video) {
    video.srcObject = requestedStream;
  } else {
    // Avoid using this in new browsers, as it is going away.
    video.src = window.URL.createObjectURL(stream);
  }
  video.onloadedmetadata = function(e) {
    video.play();
  };
}

Section intitulée code-pour-l-analyse-du-flux-videoCode pour l’analyse du flux vidéo


let isReadyToDiff = false;

capture(video) {
  this.captureContext.drawImage(video, 0, 0, canvasWidth, canvasHeight);
  var captureImageData = this.captureContext.getImageData(0, 0, this.canvasWidth, this.canvasHeight );

  this.motionContext.putImageData(captureImageData, 0, 0);

  // diff current capture over previous capture, leftover from last time
  this.diffContext.globalCompositeOperation = 'difference';
  this.diffContext.drawImage( video, 0, 0, canvasWidth, canvasHeight );

  var diffImageData = this.diffContext.getImageData( 0, 0, canvasWidth, canvasHeight );

  if (isReadyToDiff) {
    let rgba = diffImageData.data;
    // pixel adjustments are done by reference directly on diffImageData
    for (let i = 0; i < rgba.length; i += 4) {
      const pixelDiff = rgba[i] * 0.6 + rgba[i + 1] * 0.6 + rgba[i + 2] * 0.6;
      if (pixelDiff >= this.pixelDiffThreshold) {
        // do what you want with the data
      }
    }
  }

  // draw current capture normally over diff, ready for next time
  this.diffContext.globalCompositeOperation = 'source-over';
  this.diffContext.drawImage( video, 0, 0, canvasWidth, canvasHeight );
  this.isReadyToDiff = true;
}

À partir de ces lignes, j’ai réalisé un prototype basé sur la détection de mouvement. J’ai recréé le jeu pour enfant 123 soleil (1️⃣ 2️⃣ 3️⃣ ☀️), dans lequel vous devez atteindre un point d’arrivée sans être repéré. Votre progression s’effectue par étapes de 3 secondes.

Voici le dépôt Github et la démo.

demo 1

demo 2

Essayer le jeu ☀️

Section intitulée usages-possiblesUsages possibles

  • Analyse des comportements utilisateurs ;
  • Jeux ;
  • Sécurité (détection de mouvement adaptable sur une Raspberry Pi) ;
  • Arrière plan interactif ;
  • Déclenchement de photos au mouvement ;
  • Essais de lunettes/chapeaux ;
  • Déverrouillage d’écran ;
  • Contrôle d’un ordinateur par les gestes.

Section intitulée et-maintenantEt maintenant ?

Stream API et WebRTC sont de plus en plus supportés et les choses s’accélèrent.

Actuellement, deux technologies font revenir l’utilisation de la caméra dans le web.

Premièrement, le deep learning, une méthode déjà utilisée par Google, IBM, Microsoft, Amazon, Adobe, Yandex et Baidu. Reconnaitre un mouvement ou un objet devient plus facile dans un environnement web grâce à de nouvelles APIs. Les possibilités de création deviennent plus nombreuses en grande partie grâce aux avancées dans le domaine de l’intelligence artificielle. Différents projets naissent de ces APIs, par exemple des jeux.

test shifumi

De nouvelles interactions avec la caméra sont alors possibles :

En second, la réalité augmentée. Actuellement, la création d’un projet d’AR se fait par le biais d’une application mobile, mais les possibilités de créer un site directement en AR sont de plus en plus présentes. L’accès au WebRTC sur iPhone en est un exemple. Tout cela va avoir un impact fort sur l’utilisation de nos téléphones et amener de nouvelles possibilités. Par exemple, à la place de l’habituelle carte pour trouver un endroit précis, nous pourrons juste regarder autour de nous et voir la direction à suivre.

L’AR s’est développée premièrement au travers d’applications.

Des développeurs du monde entier travaillent sur des librairies permettant la création de projets AR sur le web. Nous explorerons l’une d’entre elles dans un futur article : AR.js. Les sorties d’iOS 11 et d’ARKit lancent la démocratisation de la réalité augmentée.

La réalité augmentée va de pair avec l’implémentation d’éléments 3D, des outils sont aussi mis en place pour faciliter leur création.

Section intitulée conclusionConclusion

Malgré les hauts et les bas, l’usage de la caméra dans le Web a globalement une évolution positive. Récemment, de nouvelles possibilités ont accéléré les choses. De nouvelles APIs, de meilleures capacités et un support plus complet de la part des navigateurs sont en place. La seule chose manquante, c’est de nouveaux projets, alors allons-y !


Section intitulée referencesRéferences

Commentaires et discussions