Exemple vidéo : Video Jukebox

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

L’exemple suivant crée un jukebox vidéo simple qui charge dynamiquement une liste de fichiers vidéos à lire en séquence. Vous pouvez ainsi créer une application qui permet à l’utilisateur de parcourir une série de didacticiels, ou encore qui permet de définir des publicités à afficher avant la vidéo demandée par l’utilisateur. Cet exemple illustre les fonctions suivantes d’ActionScript 3.0 :

  • Actualisation de la position de la tête de lecture en fonction de la progression dans le fichier vidéo

  • Détection et analyse des métadonnées d’un fichier vidéo

  • Gestion de codes spécifiques dans un flux Internet

  • Chargement, lecture, mise en pause et arrêt d’un fichier FLV chargé dynamiquement

  • Redimensionnement d’un objet vidéo dans la liste d’affichage en fonction des métadonnées du flux reçu

Pour obtenir les fichiers d’application de cet exemple, voir www.adobe.com/go/learn_programmingAS3samples_flash_fr. Les fichiers de l’application Video Jukebox se trouvent dans le dossier Samples/VideoJukebox. L’application se compose des fichiers suivants :

Fichier

Description

VideoJukebox.fla

ou

VideoJukebox.mxml

Le fichier d’application principal pour Flex (MXML) ou Flash (FLA).

VideoJukebox.as

Classe comportant les principales fonctionnalités de l’application.

playlist.xml

Fichier comportant la liste des fichiers vidéo à charger dans le jukebox.

Chargement l’une liste de lecture vidéo externe

Le fichier externe playlist.xml contient la liste des vidéos à charger et leur ordre de lecture. Pour charger ce fichier XML, utilisez un objet URLLoader et un objet URLRequest, comme dans le code ci-dessous :

uldr = new URLLoader(); 
uldr.addEventListener(Event.COMPLETE, xmlCompleteHandler); 
uldr.load(new URLRequest(PLAYLIST_XML_URL));

Ce code est placé dans le constructeur de la classe VideoJukebox, si bien que le fichier est chargé avant l’exécution de la suite du code. Dès que le chargement du fichier XML est terminé, la méthode xmlCompleteHandler() est appelée et analyse le fichier externe dans un objet XML, comme dans le code suivant :

private function xmlCompleteHandler(event:Event):void 
{ 
    playlist = XML(event.target.data); 
    videosXML = playlist.video; 
    main(); 
}

L’objet XML playlist contient les données XML brutes du fichier externe, alors que videosXML est un objet XMLList qui ne contient que les nœuds vidéo. Le fragment de code suivant est un exemple de contenu du fichier playlist.xml :

<videos> 
    <video url="video/caption_video.flv" /> 
    <video url="video/cuepoints.flv" /> 
    <video url="video/water.flv" /> 
</videos>

Enfin, la méthode xmlCompleteHandler() appelle la méthode main() qui définit les diverses occurrences de composants dans la liste d’affichage, ainsi que les objets NetConnection et NetStream qui permettent de charger les fichiers FLV externes.

Création de l’interface utilisateur

Pour créer l’interface utilisateur, faites glisser cinq occurrences de l’objet Button sur la liste d’affichage et donnez-leur les noms d’occurrence suivants : playButton, pauseButton, stopButton, backButton et forwardButton.

Pour chacune de ces occurrences de Button, affectez un gestionnaire pour l’événement click, comme dans le fragment de code suivant :

playButton.addEventListener(MouseEvent.CLICK, buttonClickHandler); 
pauseButton.addEventListener(MouseEvent.CLICK, buttonClickHandler); 
stopButton.addEventListener(MouseEvent.CLICK, buttonClickHandler); 
backButton.addEventListener(MouseEvent.CLICK, buttonClickHandler); 
forwardButton.addEventListener(MouseEvent.CLICK, buttonClickHandler);

La méthode buttonClickHandler() utilise une instruction switch pour déterminer l’occurrence de bouton sur laquelle l’utilisateur a cliqué, comme dans le code suivant :

private function buttonClickHandler(event:MouseEvent):void 
{ 
    switch (event.currentTarget) 
    { 
        case playButton: 
            ns.resume(); 
            break; 
        case pauseButton: 
            ns.togglePause(); 
            break; 
        case stopButton: 
            ns.pause(); 
            ns.seek(0); 
            break; 
        case backButton: 
            playPreviousVideo(); 
            break; 
        case forwardButton: 
            playNextVideo(); 
            break; 
    } 
}

Ajoutez ensuite une occurrence de Slider à la liste d’affichage, et donnez à cette occurrence le nom volumeSlider. Le code ci-dessous définit la propriété liveDragging de l’occurrence de Slider sur true et définit un écouteur d’événement pour l’événement change de cette occurrence :

volumeSlider.value = volumeTransform.volume; 
volumeSlider.minimum = 0; 
volumeSlider.maximum = 1; 
volumeSlider.snapInterval = 0.1; 
volumeSlider.tickInterval = volumeSlider.snapInterval; 
volumeSlider.liveDragging = true; 
volumeSlider.addEventListener(SliderEvent.CHANGE, volumeChangeHandler);

Ajoutez ensuite une occurrence de ProgressBar à la liste d’affichage, et donnez à cette occurrence le nom positionBar. Donnez à sa propriété mode la valeur « manual », comme ci-dessous :

positionBar.mode = ProgressBarMode.MANUAL;

Enfin, ajoutez une occurrence de l’objet Label à la liste d’affichage, et donnez à cette occurrence le nom positionLabel. La valeur de cette occurrence de l’objet Label sera définie par l’occurrence de timer.

Détection des métadonnées d’un objet vidéo

Lorsque Flash Player détecte des métadonnées dans l’une des vidéos chargées, le gestionnaire de rappel onMetaData() est appelé pour la propriété client de l’objet NetStream. Le code suivant initialise un Object et configure le gestionnaire de rappel spécifié :

client = new Object(); 
client.onMetaData = metadataHandler;

La méthode metadataHandler() copie ses données dans la propriété meta définie par code au préalable. Vous pouvez ainsi accéder à tout moment aux métadonnées de la vidéo active, depuis n’importe quel point de l’application. L’objet Video sur la scène est ensuite redimensionné selon la taille renvoyées par les métadonnées. Enfin, l’occurrence de positionBar de la barre de progression est déplacée et redimensionnée en fonction de la taille de la vidéo en cours. Le code suivant est celui de la méthode metadataHandler() :

private function metadataHandler(metadataObj:Object):void 
{ 
    meta = metadataObj; 
    vid.width = meta.width; 
    vid.height = meta.height; 
    positionBar.move(vid.x, vid.y + vid.height); 
    positionBar.width = vid.width; 
}

Chargement dynamique d’une vidéo

Pour charger dynamiquement chacune des vidéos, l’application utilise des objets NetConnection et NetStream. Le code suivant crée un objet NetConnection et passe la valeur null à la méthode connect(). Cette valeur null signifie que Flash Player va se connecter à une vidéo sur l’ordinateur local plutôt que sur un serveur tel que Flash Media Server.

Le code suivant crée les occurrences de NetConnection et NetStream, définit un écouteur d’événement pour l’événement netStatus et affecte l’objet client à la propriété client :

nc = new NetConnection(); 
nc.connect(null); 
 
ns = new NetStream(nc); 
ns.addEventListener(NetStatusEvent.NET_STATUS, netStatusHandler); 
ns.client = client;

La méthode netStatusHandler() est appelée en cas de changement d’état de la vidéo. C’est le cas lorsque la lecture de la vidéo débute ou s’arrête, lorsque le signal est mis en mémoire tampon ou en cas d’impossibilité de trouver un flux vidéo. Le code suivant répertorie l’événement netStatusHandler() :

private function netStatusHandler(event:NetStatusEvent):void 
{ 
    try 
    { 
        switch (event.info.code) 
        { 
            case "NetStream.Play.Start": 
                t.start(); 
                break; 
            case "NetStream.Play.StreamNotFound": 
            case "NetStream.Play.Stop": 
                t.stop(); 
                playNextVideo(); 
                break; 
        } 
    }  
    catch (error:TypeError)  
    { 
        // Ignore any errors. 
    } 
}

Le code précédent évalue la propriété code de l’objet info et filtre les codes « NetStream.Play.Start », « NetStream.Play.StreamNotFound » et « NetStream.Play.Stop ». Les autres codes sont ignorés. Si le flux Internet débute, le code lance l’occurrence de Timer qui actualise la tête de lecture. Si le flux Internet est introuvable ou est interrompu, l’occurrence de Timer est arrêtée et l’application tente de lire la vidéo suivante dans la liste de lecture.

A chaque exécution de Timer, l’occurrence de la barre de progression positionBar actualise sa position en appelant la méthode setProgress() de la classe ProgressBar, et l’occurrence de Label positionLabel est actualisée avec le temps écoulé et la durée totale de la vidéo active.

private function timerHandler(event:TimerEvent):void 
{ 
    try 
    { 
        positionBar.setProgress(ns.time, meta.duration); 
        positionLabel.text = ns.time.toFixed(1) + " of " meta.duration.toFixed(1) + " seconds"; 
    }  
    catch (error:Error) 
    { 
        // Ignore this error. 
    } 
}

Contrôle du volume de la vidéo

Vous pouvez contrôler le volume audio de la vidéo chargée dynamiquement par le biais de la propriété soundTransform de l’objet NetStream. L’application Video jukebox permet de modifier le volume en changeant la valeur de l’occurrence de Slider volumeSlider. Le code suivant montre comment changer le volume en affectant la valeur du composant Slider à un objet SoundTransform qui est lui-même affecté à la propriété soundTransform de l’objet NetStream :

private function volumeChangeHandler(event:SliderEvent):void 
{ 
    volumeTransform.volume = event.value; 
    ns.soundTransform = volumeTransform; 
}

Contrôle de la lecture de la vidéo

Le reste de l’application contrôle la lecture de la vidéo lorsque la fin du flux vidéo est atteinte ou lorsque l’utilisateur change de vidéo.

La méthode suivante obtient l’adresse URL de la vidéo à partir de l’objet XMLList pour l’index sélectionné :

private function getVideo():String 
{ 
    return videosXML[idx].@url; 
}

La méthode playVideo() appelle la méthode play() de l’objet NetStream pour charger la vidéo sélectionnée :

private function playVideo():void 
{ 
    var url:String = getVideo(); 
    ns.play(url); 
}

La méthode playPreviousVideo() décrémente l’index vidéo sélectionné, appelle la méthode playVideo() pour charger le nouveau fichier vidéo et rend la barre de progression visible :

private function playPreviousVideo():void 
{ 
    if (idx > 0) 
    { 
        idx--; 
        playVideo(); 
        positionBar.visible = true; 
    } 
}

La méthode finale, playNextVideo(), incrémente l’index vidéo et rappelle la méthode playVideo(). Si la vidéo en cours est la dernière de la liste de lecture, la méthode clear() est appelée pour l’objet Video et la propriété visible de l’occurrence de la barre de progression est mise à false :

private function playNextVideo():void 
{ 
    if (idx < (videosXML.length() - 1)) 
    { 
        idx++; 
        playVideo(); 
        positionBar.visible = true; 
    } 
    else 
    { 
        idx++; 
        vid.clear(); 
        positionBar.visible = false; 
    } 
}