Récupérer et sauvegarder un cliché avec la Webcam.

Janvier 2018


introduction

Nous allons voir comment mettre en marche la webcam prendre un photo puis la sauvegarder. Pour ce faire nous utiliseront les api intégré aux navigateur, mediaDevices pour la caméra, vidéo pour l'affichage, canvas pour récupérer une image, toBlob, toDataUrl pour enregistrer l'image, FormData pour l'envoi de l'image.

mise en marche de la camera

mediaDevices

L'api mediaDevices renvoie un objet MediaDevices qui permet d'accéder à des périphériques d'entrée tels que des caméras et des microphones, ainsi qu'à un partage d'écran.elle est en lecture seule et est constitué de deux méthodes getUserMedia() et enumerateDevices() dans notre cas nous utiliserons getUserMedia()

getUserMedia ()

getUserMedia () met en marche une caméra ou un partage d'écran et / ou un microphone Avec l'autorisation de l'utilisateur et fournit un Stream de media appelé MediaStream contenant une piste vidéo et / ou une piste audio.


L'ouverture ce fait en précisant comme paramètre de la fonction un objet avec deux clee la première désigne l'audio pour laquel on donne comme valeur true ou false pour dire si l'audio est actif ou non la deuxième clee désigne la vidéo pour laquel on précise soit true soit false soit un objet dans lequel on précise les options d'affichage de la vidéo dans ce cas la valeur est automatiquement a true.

Le retour de cette appel est une instance de promise (promesse) qui attend que l'utilisateur ai donné son accord pour l'utilisation de la webcam. si c'est le cas la promise reçoit un objet MediaStream et on exécute then qui s’occupera de diriger le flux vers une balise video.

Si il y a une erreur ou que l'utilisateur a refusé l'utilisation de la webcam on exécute catch afin de gérer l’erreur.

MediaStream

L'API est basée sur la manipulation d'un objet MediaStream représentant un flux de données audio et ou vidéo. C'est l'objet MediaStream qui fait le lien avec la webcam et ou le microphone.

Le src (chemin) de la balise vidéo est appelé srcObject et fait le lien entre la balise et l'objet MediaStream.

getTracks()

getTracks() est une méthode de l'objet MediaStream renvoyant un tableau listant toutes les sources (pistes) composant le stream. Dans notre cas il y a une seul source (pistes) celle de la caméra. En considérant que la webcam est pourvu d'un micro Si le son était actif il y aurait eu deux source (pistes) constituant le stream celle pour la webcam et celle pour le microphone.

Chaque source (piste) du tableau est représenté par un objet permettant le contrôle et la récupération d'information de la source (piste) par l'intermédiaire de méthodes et d'attributs.

pour plus d'information sur les méthodes et attributs un lien vers mdn


L'attribut label vas permettre de récupérer le nom de la camera.On récupère donc la piste du stream a l'index 0 du tableau et on récupère l'attribut label. afin d'afficher le nom de la webcam.

Le code

function ouvrir_camera() {

  navigator.mediaDevices.getUserMedia({ audio: false, video: { width: 400 } }).then(function(mediaStream) {
   
   var video = document.getElementById('sourcevid');
   video.srcObject = mediaStream;
   
   var tracks = mediaStream.getTracks();
   
   document.getElementById("message").innerHTML="message: "+tracks[0].label+" connecté"
   
   console.log(tracks[0].label)
   
   video.onloadedmetadata = function(e) {
    video.play();
   };
    
  }).catch(function(err) { console.log(err.name + ": " + err.message);

  document.getElementById("message").innerHTML="message: connection refusé"});
 
 }

recuperation d'un cliché

canvas drawImage()

la récupération d'un cliché a partir d'une balise vidéo vers un canvas ce fait avec la méthode drawImage de canvas en précisant dans les paramètres la balise vidéo concerné par le cliché. Pour ce faire on vas créé un canvas qui récupère le cliché puis le convertis en donné blob.

Le code

function photo(){
  
  var vivi = document.getElementById('sourcevid');
  var canvas1 = document.getElementById('cvs')
  var ctx =canvas1.getContext('2d');
  canvas1.height=vivi.videoHeight
  canvas1.width=vivi.videoWidth
  ctx.drawImage(vivi, 0,0, vivi.videoWidth, vivi.videoHeight);
 }

sauvegarde local de l'image

msSaveOrOpenBlob() toDataURL()

pour la sauvegarde de l'image on utilisera deux syntaxe un pour le navigateur Microsoft edge l'autre les autres navigateurs.

msSaveOrOpenBlob()

pour edge la syntaxe est simple on créé un blob avec msToBlob() en précisant le canvas cible puis on fait appel a msSaveOrOpenBlob avec comme paramètres le blob et le nom a donner a l'image.

msSaveOrOpenBlob permet d'ouvrir la fenêtre de téléchargement de edge.

toDataURL()

pour les autres la syntaxe est un peut plus compliqué. on fait appel a toDataURL() en précisant comme paramètre le type mime du format de l’image désiré (png jpg bmp) afin de créé un lien vers les donné, lien qui sera dirigé vers une balise a créé dynamiquement. Le nom du fichier est indiqué avec l'attribut dowload

Pour finir on créé un évènement clic dynamique avec MouseEvent sur la balise a afin d’éviter de devoir l'inséré dans la page et de cliqué sur le lien pour lancer le téléchargement.

Le code

function sauver(){
 
  if(navigator.msSaveOrOpenBlob){

            var blobObject=document.getElementById("cvs").msToBlob()

            window.navigator.msSaveOrOpenBlob(blobObject, "image.png");
        }

        else{

            var canvas = document.getElementById("cvs");
            var elem = document.createElement('a');
            elem.href = canvas.toDataURL("image/png");
            elem.download = "nom.png";
            var evt = new MouseEvent("click", { bubbles: true,cancelable: true,view: window,});
            elem.dispatchEvent(evt);
        }
 }

sauvegarde serveur de l'image

canvas toBlob()

toBlob() transforme une image provenant d'un canvas en donné binaire la méthode comprend trois paramètre le premier est une fonction qui exécutera le code pour le traitement du blob après sa création Le deuxième paramètre spécifie le mime type qui sera le format de l'image (png, jpg ou bmp) si rien n'est spécifié le format par défaut sera le png. Le troisième paramètre est une valeur comprise entre 0 et 1 et correspond a la qualité de l'image il est facultatif.

Le code

function prepare_envoi(){

 var canvas = document.getElementById('cvs');

 canvas.toBlob(function(blob){envoi(blob)}, 'image/jpeg');

 }

FormData()

FormData() permet de créé un formulaire dynamique et d'y insérer des donné dans notre cas on y insèrera le fichier blob. Ensuite on créé une connexion ajax avec l’objet XMLHttpRequest afin d'envoyé l'image ver le serveur en utilisant la méthode send() de l'objet XMLHttpRequest en précisant comme paramètre l'objet FormData.

Le code

function envoi(blob){
 
 console.log(blob.type)

 var formImage = new FormData();
 formImage.append('image_a', blob, 'image_a.jpg');

 var ajax = new XMLHttpRequest();
  
 ajax.open("POST","http://adresse/reception/upload_camera.php",true);

 ajax.onreadystatechange=function(){

  if (ajax.readyState == 4 && ajax.status==200){

   document.getElementById("jaxa").innerHTML+=(ajax.responseText);
  }
 }

 ajax.onerror=function(){

  alert("la requette a échoué")
 }

 ajax.send(formImage);
 console.log("ok")

fermer la camera

stop()

Pour fermer la Webcam on récupère d'abord une référence au stream par l'intermédiaire de la balise video et son src puis on récupère la source avec getTracks() et on lui applique la méthode stop() qui a pour effet d’arrêter la Webcam puis on supprime le lien de la balise vidéo vers son objet mediaStream afin de supprimer définitivement lien entre la webcam et la balise video le garbage collector fera le reste.

Le code

function fermer(){
 
  var video = document.getElementById('sourcevid');
  var mediaStream=video.srcObject;
  console.log(mediaStream)
  var tracks = mediaStream.getTracks();
  console.log(tracks[0])
  tracks.forEach(function(track) {
   track.stop();
   document.getElementById("message").innerHTML="message: "+tracks[0].label+" déconnecté"
  });

  video.srcObject = null;
 }

exemple complet

<!DOCTYPE html> 
 <html lang="fr">
  <head>
   <title>HTML5 Camera</title> 

   <meta charset="UTF-8">

   <style type="text/css">


    button{

    width:100px;
    margin:5px;
    font-weight: bold;
    height:50px;

    }

   </style>

   <script>

    function ouvrir_camera() {

     navigator.mediaDevices.getUserMedia({ audio: false, video: { width: 400 } }).then(function(mediaStream) {

      var video = document.getElementById('sourcevid');
      video.srcObject = mediaStream;

      var tracks = mediaStream.getTracks();

      document.getElementById("message").innerHTML="message: "+tracks[0].label+" connecté"

      console.log(tracks[0].label)
      console.log(mediaStream)

      video.onloadedmetadata = function(e) {
       video.play();
      };
       
     }).catch(function(err) { console.log(err.name + ": " + err.message);

     document.getElementById("message").innerHTML="message: connection refusé"});
    }

    function photo(){

     var vivi = document.getElementById('sourcevid');
     //var canvas1 = document.createElement('canvas');
     var canvas1 = document.getElementById('cvs')
     var ctx =canvas1.getContext('2d');
     canvas1.height=vivi.videoHeight
     canvas1.width=vivi.videoWidth
     console.log(vivi.videoWidth)
     ctx.drawImage(vivi, 0,0, vivi.videoWidth, vivi.videoHeight);

     //var base64=canvas1.toDataURL("image/png"); //l'image au format base 64
     //document.getElementById('tar').value='';
     //document.getElementById('tar').value=base64;
    }

    function sauver(){

     if(navigator.msSaveOrOpenBlob){

      var blobObject=document.getElementById("cvs").msToBlob()

      window.navigator.msSaveOrOpenBlob(blobObject, "image.png");
     }

     else{

      var canvas = document.getElementById("cvs");
      var elem = document.createElement('a');
      elem.href = canvas.toDataURL("image/png");
      elem.download = "nom.png";
      var evt = new MouseEvent("click", { bubbles: true,cancelable: true,view: window,});
      elem.dispatchEvent(evt);
     }
    }

    function prepare_envoi(){

     var canvas = document.getElementById('cvs');
     canvas.toBlob(function(blob){envoi(blob)}, 'image/jpeg');
    }
    
    
    function envoi(blob){

     console.log(blob.type)

     var formImage = new FormData();
     formImage.append('image_a', blob, 'image_a.jpg');

     var ajax = new XMLHttpRequest();

     ajax.open("POST","http://scriptevol.free.fr/contenu/reception/upload_camera.php",true);

     ajax.onreadystatechange=function(){

      if (ajax.readyState == 4 && ajax.status==200){

       document.getElementById("jaxa").innerHTML+=(ajax.responseText);
      }
     }

     ajax.onerror=function(){

      alert("la requette a échoué")
     }

     ajax.send(formImage);
     console.log("ok")
    }

    
    function fermer(){

     var video = document.getElementById('sourcevid');
     var mediaStream=video.srcObject;
     console.log(mediaStream)
     var tracks = mediaStream.getTracks();
     console.log(tracks[0])
     tracks.forEach(function(track) {
      track.stop();
      document.getElementById("message").innerHTML="message: "+tracks[0].label+" déconnecté"
     });

     video.srcObject = null;
    }


   </script>
   
  </head>

   <body>
    <div style='display:inline-block'>

     <video id="sourcevid" width='400' autoplay="true"></video>

     <div id="message" style='height:20px;width:350px;margin:5px;'>message:</div>
    </div>

    <canvas id="cvs" style='display:inline-block'></canvas>

    <div>
     <button onclick='ouvrir_camera()' >ouvrir camera</button>
     <button onclick='fermer()' >fermer camera</button>
     <br>
     <button onclick='photo()' >prise de photo</button>
     <button onclick='sauver()' >sauvegarder</button>
     <button onclick='prepare_envoi()' >envoyer</button>
    </div>

    <div id="jaxa" style='width:80%;margin:5px;'>message:</div>
   </body>
 </html>
 
Publié par @karamel.
Ce document intitulé «  Récupérer et sauvegarder un cliché avec la Webcam.  » issu de CodeS-SourceS (codes-sources.commentcamarche.net) est mis à disposition sous les termes de la licence Creative Commons. Vous pouvez copier, modifier des copies de cette page, dans les conditions fixées par la licence, tant que cette note apparaît clairement.
Ajouter un commentaire

Commentaires

Commenter la réponse de Utilisateur anonyme
la poo en javascript modification et consequence
Tuto sur les balises de défilement