LeasySudoku

Photographie


Accueil   Articles   Flex - Manipuler la webcam d'un utilisateur

Flex - Manipuler la webcam d'un utilisateur

Convertir en PDF Version imprimable Suggérer par mail
Appréciation :       8 vote(s)
Faible Meilleur
Social BookmarkingApple News MQCD Blinklist Blogmarks Bookmarks del.icio.us Digg Facebook Furl Google Bookmark! Windows Live Favorites ma.gnolia Netvouz Reddit Simpy Spurl StumbleUpon Taggly Wikio Yahoo MyWeb
Écrit par Nicolas PIED
Publié le 29-05-2008 - 4881 hits
Avec l’arrivée de la vidéo sur Internet, les services et les solutions applicatives dans ces domaines ne sont largement développés. Il n’est pas rare aujourd’hui de croiser de la VoD (Video On Demand) en naviguant sur des sites. En réalité, la plupart des sites à contenu en proposent.

Le serveur Adobe Flash Media Server ainsi que son alternative open source Red5 permettent de manipuler ce genre de contenu. Mais ces derniers peuvent aussi gérer le flux en provenance de Webcams ; ce qui permet de nouvelles interactions avec les utilisateurs. Cet article reste donc dans l’actualité du Web 2.0, puisqu’il est basé sur Adobe Flex 3 / AMFPHP et qu’il consiste à vous présenter les grandes méthodes pour :
  • Afficher une Webcam
  • Capturer une image d’une Webcam
  • Envoyer une image capturée à un serveur Web via AMF
Le code source des exemples ainsi qu’une démonstration en ligne sont accessible dans la partie « Conclusion & Références » de cet d’article.

Afficher une WebCam en utilisant Flex 3

L’affichage d’une WebCam se réalise très simplement sous Flex étant donné que son SDK présente déjà toutes les classes nécessaires. On trouvera en outre la classe « Camera » et le contrôle MXML « mx:VideoDisplay » qui vont permettre de répondre à ce premier besoin à l’aide de quelques lignes de code seulement.

Interface graphique et principaux contrôles MXML

Dans un premier temps, le code MXML permettant de construire l’interface graphique va être présenté ; ceci afin d’avoir un aperçu des principaux contrôles utilisés :

<mx:HBox>
    <mx:Panel title="Votre webcam">
        <mx:VideoDisplay
            id="videoCamera"
            creationComplete="loadCamera();"
            width="320"
            height="240"
            borderThickness="1"
            borderColor="#FFFFFF"  
            borderStyle="solid" 
            cornerRadius="0"/>
    </mx:Panel>
    <mx:Panel title="Votre photo" id="pnSnapShot">
        <mx:Image 
            id="imageSnaphot" 
            source="folder_photos.png" 
            scaleContent="false" 
            autoLoad="true" 
            width="320" 
            height="240">
        </mx:Image>
    </mx:Panel>
</mx:HBox>
    
<mx:HBox>
    <mx:Button 
        id="btnSnapShot"
        label="Prendre une photo" 
        click="takeSnapshot();"
        enabled="false" 
        icon="@Embed(source='photo.png')"/>
</mx:HBox>
  • mx:VideoDisplay : ce contrôle sera celui utilisé pour l’affichage du flux en provenance de la WebCam de l’utilisateur. On pourra remarquer un appel à la fonction « loadCamera » qui permettra d’attacher le flux de la WebCam au contrôle une fois sa création terminée.
  • mx:Image : contrairement à ce que l’on pourrait croire, ce contrôle (qui a pour but d’afficher des images) n’est pas celui qui sera utilisé pour afficher une image capturée de la WebCam. Elle est uniquement utilisée ici à des fins d’embellissement de l’interface graphique et disparaîtra sitôt la première capture effectuée.
  • mx:Panel : ce contrôle sera chargé de recevoir l’image capturée de la WebCam. En attendant la première capture de l’utilisateur, il est utilisé pour afficher le contrôle « mx:Image » décrit précédemment.
  • mx:Button : ce bouton va permettre de capturer une image provenant de la WebCam grâce à la fonction « takeSnapshot ».

D’un point de vue fonctionnel, les points importants à retenir sont :

  • 3 contrôles MXML (« mx:VideoDisplay », « mx:Panel » et « mx:Button »)
  • 2 appels de fonctions (« loadCamera » et « takeSnapshot »)

Les autres données ne sont donc utilisées qu’à des fins d’ergonomie.

Fonction permettant d’afficher la Webcam

Comme indiqué précédemment, la fonction « loadCamera » permet d’afficher le flux d’une WebCam au sein du contrôle « mx:VideoDisplay ». Comme vous pouvez le constater, le code source de cette fonction est relativement simple à saisir :

private function loadCamera() : void {
    var webcam:Camera = Camera.getCamera();
    if(webcam)
        videoCamera.attachCamera(webcam);
    else
        Alert.show("Vous ne semblez pas avoir de webcam.", "Kbups.org");
}
Il consiste, dans un premier temps, à récupérer un objet de type « Camera » qui sera ensuite attaché au contrôle MXML portant l’identifiant « videoCamera ». Cette dernière action n’est réalisée que si l’utilisateur possède bien sûr une WebCam.

L’appel de fonction « Camera.getCamera() » va déclencher l’ouverture automatique d’une petite fenêtre popup demandant à l’utilisateur s’il souhaite autoriser l’accès à sa WebCam. L’image ci-dessous vous présente justement un exemple possible de cette fenêtre popup :

Permettre à l'application Flex d'accéder à la webcam
Permettre à l'application Flex d'accéder à la webcam
 

Capturer une image de la WebCam

La fonction « takeSnapshot », qui permet de capturer une image de la WebCam, est elle aussi très simple. Dans un premier temps un conteneur de type UIComponent est créé afin de recevoir l’image capturée. Ensuite, un Bitmap est instancié à partir de la source vidéo ; dans notre cas, il s’agit de l’objet « videoCamera » correspondant au contrôle MXML « VideoDisplay » qui est normalement en train d’afficher le flux de la WebCam.

La dernière étape consiste à attribuer à l’instance UIComponent l’image Bitmap nouvellement créée et à ajouter celle-ci au sein d’un contrôle MXML existant ; il s’agit ici du Panel « pnSnapShot ». Avant de réaliser cet ajout, il est nécessaire de supprimer tous les contrôles déjà présents au sein de ce conteneur afin de n’afficher qu’une capture à la fois.

private function takeSnapshot() : void {
    var snapshotHolder:UIComponent = new UIComponent();
    var snapshot:BitmapData = new BitmapData(
        videoCamera.width, 
        videoCamera.height, 
        true);
 
    var snapshotBitmap:Bitmap = new Bitmap(snapshot);
 
    snapshotHolder.addChild(snapshotBitmap);
    snapshot.draw(videoCamera);
 
    pnSnapShot.removeAllChildren();
    pnSnapShot.addChild(snapshotHolder);
}

Envoyer une image capturée à un serveur Web via AMF

Cette dernière étape va consister à envoyer l’image capturée à un serveur Web de même domaine en utilisant AMFPHP. Le fonctionnement de se dernier ne sera pas décrit dans le cadre de cet article mais seulement le service AMFPHP et le code Flex associé.

Ce principe pourrait entre autres être utilisé pour sauvegarder l’avatar d’un utilisateur.

Description du service AMFPHP

La classe de service permettant d’enregistrer une image reçue en paramètre se nomme « PictureService ». Elle doit être positionnée dans le répertoire des services d’AMFPHP (par défaut : AMFPHP_HOME/services)

Cette classe dispose d’une fonction « savePNG » qui décompresse le tableau d’octets d’une image capturée au sein d’un nouveau fichier PNG. Pour simplifier le code, le nom du fichier est arbitrairement fixé à l’heure courante.

<?php
class PictureService {
    function savePNG($bytesArray) {
        $data = $bytesArray->data;
        $data = gzuncompress($data);
        
        $file = "webcam_" . date("Y-m-d_h-i-s") . ".png";
        
        file_put_contents("pictures/" . $file, $data);
        
        return $file;
    }
}
?>

Appeler le service AMFPHP à partir de Flex

Pour dialoguer avec le service AMFPHP nouvellement crée, il faut pour cela définir un objet « mx:RemoteObject » ; ce qui va permettre à Flex d’appeler la fonction « savePNG » de la classe PHP « PictureService ». On associe à cette méthode deux fonctions : une appelée en cas de succès, l’autre en cas d’erreur.

<mx:RemoteObject 
    id="myservice" 
    fault="faultHandler(event)" 
    showBusyCursor="true"
    source="PictureService" 
    destination="amfphp">
        <mx:method name="savePNG" 
            result="resultHandler(event)" 
            fault="faultHandler(event)" />
</mx:RemoteObject>

La fonction « savePicture » est appelée via l’objet « snapshot », de type BitmapData, créé au sein de la fonction « takeSnapShot » vue précédemment. Un tableau d’octets définissant l’image encodée et compressée en PNG est finalement envoyé à la méthode « savePNG » de l’objet distant « myservice ».

Si l’image est correctement réceptionnée par le serveur Web, la fonction « resultHandler » est alors exécutée. Dans le cas contraire, il s’agira de la fonction « faultHandler ».

private function savePicture(picture:BitmapData) : void {
    var pngEncoder:PNGEncoder = new PNGEncoder();
                
    var pngBytes:ByteArray = pngEncoder.encode(picture);
    pngBytes.compress();
                
    myservice.getOperation("savePNG").send(pngBytes);
}
            
private function faultHandler(fault:FaultEvent):void
{
  CursorManager.removeBusyCursor();
  Alert.show("code:\n" + 
                 fault.fault.faultCode +
                 "\n\nMessage:\n" + 
                 fault.fault.faultString + 
                 "\n\nDetail:\n" + 
                 fault.fault.faultDetail);
}
 
private function resultHandler(evt:ResultEvent):void {
    Alert.show("Nom du fichier généré : " + evt.result.toString());
}
Malgré ce que l’on pourrait croire, il reste encore une tâche à réaliser. Celle-ci consiste à configurer le service AMFPHP.

Il faut pour cela créer un fichier nommé « services-config.xml », dans le dossier « src » du projet Flex, avec pour contenu :
<?xml version="1.0" encoding="UTF-8"?>
<services-config>
    <services>
        <service id="amfphp-flashremoting-service"
             class="flex.messaging.services.RemotingService"
            messageTypes="flex.messaging.messages.RemotingMessage">
            <destination id="amfphp">
                <channels>
                    <channel ref="my-amfphp"/>
                </channels>
                <properties>
                    <source>*</source>
                </properties>
            </destination>
        </service>
    </services>
    <channels>
        <channel-definition id="my-amfphp" class="mx.messaging.channels.AMFChannel">
            <endpoint uri="http://MON_DOMAINE/amfphp/gateway.php" 
                class="flex.messaging.endpoints.AMFEndpoint"/>
        </channel-definition>
    </channels>
</services-config>
Au sein de ces quelques lignes, il vous faut remplacer la valeur « MON_DOMAINE », de la balise XML « endpoint », par le nom de domaine du serveur Web hébergeant AMFPHP.

Ce fichier doit être lié aux sources Flex lors de la compilation du projet. Il est donc nécessaire d’ajouter la ligne ci-dessous à la liste des arguments additionnels fournis au compilateur mxmlc :
-services "services-config.xml"
Sous Flex Builder, cette information peut être ajoutée dans les options de l’item « Flex Compiler » des propriétés du projet :

Insérer l'argument de compilation pour la définition du service AMFPHP
Insérer l'argument de compilation pour la définition du service AMFPHP
 

 Ceci réalisé, vous pouvez alors compiler et exécuter votre projet Flex afin de tester son bon fonctionnement.

Aperçu de l'application finale réalisée dans cet article
Aperçu de l'application finale réalisée dans cet article
 

Conclusion & Références

Cet article avait pour but de vous exposer simplement la manipulation d’une WebCam à partir de Flex. Bien que la capture soit ici réalisée à partir de la source vidéo d’une WebCam, il faut savoir que cette fonctionnalités reste tout aussi valable pour d’autres types de sources à partir de moment où il est possible de les intégrer dans le contrôle MXML « mx:VideoDisplay ».

Le code source de cet article vous est fournit ci-dessous et vous permettra de tester l’exemple complet dans Flex Builder 3.

Téléchargement

Liens relatifs à cet article

Faîtes un commentaire

Nom :
Titre :
Commentaire :

 
300 caractères restants
 
Dernière mise à jour : 29-05-2008