Utilisation de caméras

Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures

La source des données vidéo peut être une caméra connectée à l’ordinateur de l’utilisateur, et il est possible de gérer en ActionScript l’affichage et la manipulation de ces données. La classe Camera est le mécanisme intégré à ActionScript permettant d’utiliser un ordinateur ou une caméra.

Sur les périphériques mobiles, vous pouvez également utiliser la classe CameraUI . La classe CameraUI ouvre une application de caméra indépendante pour permettre à l’utilisateur de capturer un cliché ou d’enregistrer une vidéo. Lorsque l’utilisateur a terminé, votre application peut accéder à l’image ou à la vidéo via un objet MediaPromise .

Présentation de la classe Camera

L’objet Camera permet d’établir une connexion avec la caméra locale de l’utilisateur et de diffuser le signal vidéo soit localement (à destination de l’utilisateur lui-même) ou à destination d’un serveur tel que Flash Media Server.

La classe Camera permet d’accéder aux informations suivantes sur la caméra de l’utilisateur :

  • Quelles caméras installées sur l’ordinateur ou le périphérique de l’utilisateur sont-elles disponibles ?

  • Installation d’une caméra ou non

  • Si Flash Player est autorisé ou non à accéder à la caméra de l’utilisateur

  • Caméra active

  • Largeur et hauteur de la vidéo en cours de capture, en pixels

La classe Camera fournit les méthodes et les propriétés qui permettent d’utiliser les objets Camera. Par exemple, la propriété statique Camera.names contient le tableau des noms des caméras actuellement installées sur l’ordinateur. Par ailleurs, la propriété name permet d’afficher le nom de la caméra active.

Remarque : si vous diffusez en continu la vidéo émanant d’une caméra via le réseau, vous devez toujours traiter les interruptions du réseau. Ces interruptions se produisent pour diverses raisons, en particulier sur les périphériques mobiles.

Affichage du contenu de la caméra

La connexion à une caméra peut nécessiter moins de code que l’utilisation des classes NetConnection et NetStream pour charger un fichier vidéo. Par contre, l’utilisation de la classe Camera peut parfois s’avérer délicate, car avec Flash Player, il est nécessaire d’avoir l’autorisation de l’utilisateur pour se connecter à sa caméra et la rendre accessible par code.

Le code suivant montre comment utiliser la classe Camera pour établir une connexion avec la caméra de l’utilisateur :

var cam:Camera = Camera.getCamera(); 
var vid:Video = new Video(); 
vid.attachCamera(cam); 
addChild(vid);
Remarque : la classe Camera ne possède pas de méthode constructeur. Pour créer une nouvelle occurrence de Camera, utilisez la méthode statique Camera.getCamera() .

Conception d’une application gérant une caméra locale

Lors de la programmation d’une application destinée à gérer la caméra de l’utilisateur, prenez les précautions suivantes :

  • Vérifiez qu’une caméra est installée sur l’ordinateur de l’utilisateur. Gérez le cas de figure dans lequel aucune caméra n’est disponible.

  • Pour Flash Player uniquement, vérifiez si l’utilisateur a autorisé l’accès à la caméra de façon explicite. Pour des raisons de sécurité, le lecteur Flash affiche la boîte de dialogue de paramétrage de Flash Player, qui permet à l’utilisateur d’autoriser ou non l’accès à sa caméra. Flash Player ne peut donc pas établir une connexion avec la caméra d’un utilisateur et diffuser un signal vidéo sans la permission de cet utilisateur. Si l’utilisateur clique sur le bouton d’autorisation, votre application peut se connecter à sa caméra. Si l’utilisateur clique sur le bouton de refus, votre application ne pourra pas établir de liaison avec sa caméra. Dans les deux cas, votre application doit gérer élégamment la réponse.

  • Pour AIR uniquement, vérifiez que la classe Camera est prise en charge par les profils de périphériques gérés par l’application.

  • Elle n’est pas prise en charge par les navigateurs mobiles.

  • Elle n’est pas prise en charge par les applications AIR mobiles qui font appel au mode de rendu par processeur graphique.

  • Sur les périphériques mobiles, il n’est possible d’activer qu’une seule caméra à la fois.

Etablissement d’une connexion avec la caméra de l’utilisateur

Pour établir une connexion avec la caméra de l’utilisateur, la première étape consiste à créer une occurrence de l’objet Camera, en créant une variable du type Camera et en l’initialisant avec la valeur renvoyée par la méthode statique Camera.getCamera() .

L’étape suivante consiste à créer un objet Video et à lui affecter l’objet Camera.

La troisième étape consiste à ajouter cet objet Video à la liste d’affichage. Les étapes 2 et 3 sont nécessaires, car la classe Camera n’étend pas la classe DisplayObject, il est donc impossible de l’ajouter directement à la liste d’affichage. Pour afficher le signal vidéo provenant de la caméra, vous devez ensuite créer un autre objet Video et appeler la méthode attachCamera() .

Le code suivant illustre ces trois opérations :

var cam:Camera = Camera.getCamera(); 
var vid:Video = new Video(); 
vid.attachCamera(cam); 
addChild(vid);

Notez que si aucune caméra n’est installée sur l’ordinateur de l’utilisateur, l’application n’affiche rien.

Pour une application réelle, d’autres tâches sont nécessaires. Pour plus d’informations, voir Vérification de la présence de caméras et Détection de l’autorisation d’accéder à la caméra .

Vérification de la présence de caméras

Avant de tenter d’utiliser les méthodes ou propriétés d’une occurrence de Camera, il est préférable de vérifier qu’une caméra est bien installée. Il existe deux techniques pour vérifier la présence d’une ou plusieurs caméras :

  • Tester la propriété statique Camera.names , qui contient le tableau des noms des caméras disponibles. Ce tableau ne comporte en général qu’une seule chaîne au maximum, car la plupart des utilisateurs ne disposent au mieux que d’une seule caméra à la fois. Le code suivant montre comment tester la propriété Camera.names pour vérifier que l’utilisateur dispose d’au moins une caméra :

    if (Camera.names.length > 0) 
    { 
        trace("User has at least one camera installed."); 
        var cam:Camera = Camera.getCamera(); // Get default camera. 
    } 
    else 
    { 
        trace("User has no cameras installed."); 
    }
  • Vérifier la valeur renvoyée de la méthode statique Camera.getCamera() . Si aucune caméra n’est disponible ou installée, la méthode renvoie null , sinon elle renvoie une référence à un objet Camera. Le code suivant montre comment appeler la méthode Camera.getCamera() pour vérifier que l’utilisateur dispose d’au moins une caméra :

    var cam:Camera = Camera.getCamera(); 
    if (cam == null) 
    { 
        trace("User has no cameras installed."); 
    } 
    else 
    { 
        trace("User has at least 1 camera installed."); 
    }

Etant donné que la classe Camera n’étend pas la classe DisplayObject, il est impossible de l’ajouter directement à la liste d’affichage à l’aide de la méthode addChild() . Pour afficher le signal vidéo provenant de la caméra, vous devez donc créer un objet Video et appeler la méthode attachCamera() de l’occurrence de Video.

Ce fragment de code montre comment établir la connexion avec la caméra, s’il en existe une. Dans le cas contraire, Flash Player n’affiche rien :

var cam:Camera = Camera.getCamera(); 
if (cam != null) 
{ 
    var vid:Video = new Video(); 
    vid.attachCamera(cam); 
    addChild(vid); 
}

Caméras des périphériques mobiles

La classe Camera n’est pas prise en charge dans le moteur d’exécution de Flash Player sur les navigateurs mobiles.

Dans les applications AIR des périphériques mobiles, vous pouvez accéder à la ou aux caméras dont dispose le périphérique. Sur les périphériques mobiles, vous pouvez utiliser soit la caméra frontale soit la caméra arrière, mais pas les deux en même temps. (Si vous activez une deuxième caméra, la première est tout d’abord désactivée.) La caméra frontale est mise en miroir horizontalement sur iOS ; elle ne l’est pas sur Android.

Détection de l’autorisation d’accéder à la caméra

Dans le sandbox de l’application AIR, l’application peut accéder à n’importe quelle caméra sans autorisation de l’utilisateur. Sur Android, l’application doit toutefois spécifier l’autorisation CAMERA d’Android dans le descripteur d’application.

Avant que Flash Player ne puisse afficher les résultats d’une caméra, l’utilisateur doit autoriser Flash Player à accéder à la caméra de façon explicite. Lorsque la méthode attachCamera() est appelée, la boîte de dialogue Paramètres de Flash Player est affichée pour permettre à l’utilisateur d’autoriser ou refuser à Flash Player l’accès à la caméra et au microphone. Si l’utilisateur a accordé son autorisation, Flash Player affiche les résultats de la caméra dans l’occurrence de l’objet Video sur la scène. Si l’utilisateur a refusé, Flash Player ne peut pas se connecter à la caméra et l’objet Video n’affiche rien.

Pour déterminer si l’utilisateur a accordé à Flash Player l’accès à la caméra, vous pouvez écouter l’événement status de la caméra ( StatusEvent.STATUS ), comme dans le code suivant :

var cam:Camera = Camera.getCamera(); 
if (cam != null) 
{ 
    cam.addEventListener(StatusEvent.STATUS, statusHandler); 
    var vid:Video = new Video(); 
    vid.attachCamera(cam); 
    addChild(vid); 
} 
function statusHandler(event:StatusEvent):void 
{ 
    // This event gets dispatched when the user clicks the "Allow" or "Deny" 
    // button in the Flash Player Settings dialog box. 
    trace(event.code); // "Camera.Muted" or "Camera.Unmuted" 
}

La fonction statusHandler() est appelée dès que l’utilisateur clique sur Autoriser ou Refuser. Deux méthodes permettent de détecter le bouton qui a été cliqué :

  • Le paramètre event de la fonction statusHandler() possède une propriété code qui contient la chaîne « Camera.Muted » ou « Camera.Unmuted ». Si la valeur est « Camera.Muted », l’utilisateur a refusé l’autorisation et Flash Player ne peut pas accéder à la caméra. Le fragment de code suivant en est un exemple :

    function statusHandler(event:StatusEvent):void 
    { 
        switch (event.code) 
        { 
            case "Camera.Muted": 
                trace("User clicked Deny."); 
                break; 
            case "Camera.Unmuted": 
                trace("User clicked Accept."); 
                break; 
        } 
    }
  • La classe Camera contient une propriété en lecture seule appelée muted qui indique si l’utilisateur a refusé l’accès à la caméra ( true ) ou l’a autorisé ( false ) dans le panneau Confidentialité de Flash Player. Le fragment de code suivant en est un exemple :

    function statusHandler(event:StatusEvent):void 
    { 
        if (cam.muted) 
        { 
            trace("User clicked Deny."); 
        } 
        else 
        { 
            trace("User clicked Accept."); 
        } 
    }

En consultant l’événement d’état à distribuer, vous pouvez rédiger du code pour gérer l’autorisation ou le refus d’accès à la caméra et terminer proprement. Par exemple, si l’utilisateur a refusé, vous pouvez afficher un message lui expliquant qu’il doit donner son autorisation s’il veut participer à une conversation vidéo, ou au contraire veiller à supprimer l’objet Video de la liste d’affichage afin de libérer des ressources système.

Dans AIR, l’autorisation d’utilisation de la caméra n’étant pas dynamique, un objet Camera ne distribue pas d’événement d’état.

Optimisation de la qualité des vidéos de la caméra

Par défaut, les nouvelles occurrences de la classe Video ont une largeur de 320 pixels sur une hauteur de 240 pixels. Pour optimiser la qualité vidéo, veillez à donner à vos objets Video les mêmes dimensions que celles de l’objet Camera. Pour obtenir la largeur et la hauteur de l’objet Camera, utilisez les propriétés width et height de la classe Camera. Vous pouvez alors adapter les propriétés width et height de l’objet Video à ces dimensions, ou transmettre celles-ci à la méthode constructeur de la classe Video, comme dans le fragment de code ci-dessous :

var cam:Camera = Camera.getCamera(); 
if (cam != null) 
{ 
    var vid:Video = new Video(cam.width, cam.height); 
    vid.attachCamera(cam); 
    addChild(vid); 
}

Comme la méthode getCamera() renvoie une référence à un objet Camera (ou null si aucune caméra n’est présente), vous pouvez utiliser les méthodes et les propriétés de cet objet même si l’utilisateur refuse l’accès à la caméra. Vous pouvez ainsi définir les dimensions de l’occurrence de l’objet Video en fonction de celles de la caméra.

var vid:Video; 
var cam:Camera = Camera.getCamera(); 
 
if (cam == null) 
{ 
    trace("Unable to locate available cameras."); 
} 
else 
{ 
    trace("Found camera: " + cam.name); 
    cam.addEventListener(StatusEvent.STATUS, statusHandler); 
    vid = new Video(); 
    vid.attachCamera(cam); 
} 
function statusHandler(event:StatusEvent):void 
{ 
    if (cam.muted) 
    { 
        trace("Unable to connect to active camera."); 
    } 
    else 
    { 
        // Resize Video object to match camera settings and  
        // add the video to the display list. 
        vid.width = cam.width; 
        vid.height = cam.height; 
        addChild(vid); 
    } 
    // Remove the status event listener. 
    cam.removeEventListener(StatusEvent.STATUS, statusHandler); 
}

Pour plus d’informations sur le mode plein écran, voir la section relative au mode plein écran sous Définition des propriétés de la scène .

Gestion de l’état de la caméra

La classe Camera contient plusieurs propriétés qui permettent de suivre l’état de l’objet Camera. Par exemple, le code ci-dessous affiche plusieurs propriétés de la caméra à l’aide d’un objet Timer et d’une occurrence de champ de texte dans la liste d’affichage :

var vid:Video; 
var cam:Camera = Camera.getCamera(); 
var tf:TextField = new TextField(); 
tf.x = 300; 
tf.autoSize = TextFieldAutoSize.LEFT; 
addChild(tf); 
 
if (cam != null) 
{ 
    cam.addEventListener(StatusEvent.STATUS, statusHandler); 
    vid = new Video(); 
    vid.attachCamera(cam); 
} 
function statusHandler(event:StatusEvent):void 
{ 
    if (!cam.muted) 
    { 
        vid.width = cam.width; 
        vid.height = cam.height; 
        addChild(vid); 
        t.start(); 
    } 
    cam.removeEventListener(StatusEvent.STATUS, statusHandler); 
} 
 
var t:Timer = new Timer(100); 
t.addEventListener(TimerEvent.TIMER, timerHandler); 
function timerHandler(event:TimerEvent):void 
{ 
    tf.text = ""; 
    tf.appendText("activityLevel: " + cam.activityLevel + "\n"); 
    tf.appendText("bandwidth: " + cam.bandwidth + "\n"); 
    tf.appendText("currentFPS: " + cam.currentFPS + "\n"); 
    tf.appendText("fps: " + cam.fps + "\n"); 
    tf.appendText("keyFrameInterval: " + cam.keyFrameInterval + "\n"); 
    tf.appendText("loopback: " + cam.loopback + "\n"); 
    tf.appendText("motionLevel: " + cam.motionLevel + "\n"); 
    tf.appendText("motionTimeout: " + cam.motionTimeout + "\n"); 
    tf.appendText("quality: " + cam.quality + "\n"); 
}

Tous les 1/10 de seconde (100 millisecondes) l’événement timer de l’objet Timer est diffusé et la fonction timerHandler() actualise le contenu du champ de texte dans la liste d’affichage.