Esempio video: Video Jukebox

Flash Player 9 e versioni successive, Adobe AIR 1.0 e versioni successive

L'esempio seguente crea un semplice video jukebox che carica in modo dinamico un elenco di video da riprodurre in sequenza. Viene pertanto creata un'applicazione che consente a un utente di sfogliare tra una serie di esercitazioni video o che specifica quali annunci pubblicitari devono essere riprodotti prima di distribuire il video richiesto dall'utente. L'esempio seguente dimostra le seguenti caratteristiche di ActionScript 3.0:

  • Aggiornamento di un indicatore di riproduzione in base all'avanzamento della riproduzione di un video

  • Ascolto e analisi dei metadati di un video

  • Gestione di codici specifici in uno streaming di rete

  • Caricamento, riproduzione, pausa e interruzione di un file FLV caricato dinamicamente

  • Ridimensionamento di un oggetto video nell'elenco di visualizzazione in base ai metadati dello streaming di rete

Per ottenere i file dell'applicazione per questo esempio, visitate la pagina www.adobe.com/go/learn_programmingAS3samples_flash_it. I file dell'applicazione Video Jukebox sono disponibili nella cartella Samples/VideoJukebox. L'applicazione è composta dai seguenti file:

File

Descrizione

VideoJukebox.fla

o

VideoJukebox.mxml

File principale dell'applicazione per Flex (MXML) o Flash (FLA).

VideoJukebox.as

La classe che fornisce la funzionalità principale dell'applicazione.

playlist.xml

Un file che elenca i file video che vengono caricati nel video jukebox.

Caricamento di un file di playlist video esterno

Il file playlist.xml esterno specifica quali video caricare e l'ordine in cui devono essere riprodotti. Per poter caricare il file XML, è necessario utilizzare un oggetto URLLoader e un oggetto URLRequest, come mostrato nel codice seguente:

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

Questo codice viene collocato nella funzione di costruzione della classe VideoJukebox in modo che il file venga caricato prima che venga eseguito qualunque altro codice. Non appena è terminato il caricamento del file XML, viene chiamato il metodo xmlCompleteHandler() che analizza il file esterno in un oggetto XML, come mostrato nel codice seguente:

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

L'oggetto XML playlist contiene i dati XML originari del file esterno, mentre videosXML è un oggetto XMLList che contiene solo i nodi video. Lo snippet di codice seguente contiene un esempio di un file playlist.xml:

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

Infine, il metodo xmlCompleteHandler() chiama il metodo main() che imposta le istanze dei vari componenti nell'elenco di visualizzazione, oltre agli oggetti NetConnection e NetStream che vengono utilizzati per caricare i file FLV esterni.

Creazione dell'interfaccia utente

Per creare l'interfaccia utente dovete trascinare cinque istanze Button nell'elenco di visualizzazione e assegnare a esse i seguenti nomi di istanza: playButton, pauseButton, stopButton, backButton e forwardButton.

Per ognuna di queste istanze Button, è necessario assegnare un gestore per l'evento click, come mostrato nello snippet di codice seguente:

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);

Il metodo buttonClickHandler() utilizza un'istruzione switch per determinare su quale istanza Button è stato fatto clic, come mostrato nel codice seguente:

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; 
    } 
}

Quindi, aggiungete un'istanza Slider all'elenco di visualizzazione e assegnatele il nome di istanza volumeSlider. Il codice seguente imposta la proprietà liveDragging dell'istanza Slider su true e definisce per quest'ultima un listener di eventi per l'evento change:

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);

Aggiungete un'istanza ProgressBar all'elenco di visualizzazione e assegnatele il nome di istanza positionBar. Impostatene la proprietà mode su manual, come mostrato nello snippet di codice seguente:

positionBar.mode = ProgressBarMode.MANUAL;

Infine, aggiungete un'istanza Label all'elenco di visualizzazione e assegnatele il nome di istanza positionLabel. Il valore di questa istanza Label viene impostata dall'istanza Timer

Intercettazione dei metadati di un oggetto video

Quando Flash Player incontra dei metadati per ognuno dei video caricati, il gestore di callback onMetaData() viene chiamato sulla proprietà client dell'oggetto NetStream. Il codice seguente inizializza un oggetto e imposta il gestore di callback specificato:

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

Il metodo metadataHandler() ne copia i dati nella proprietà meta definita precedentemente nel codice. Ciò consente di accedere ai metadati del video corrente in qualunque momento e in qualsiasi parte dell'intera applicazione. Quindi, l'oggetto Video sullo stage viene ridimensionato affinché corrisponda alle dimensioni restituite dai metadati. Infine, l'istanza della barra di avanzamento positionBar viene spostata e ridimensionata in base alle dimensioni del video che è in corso di riproduzione. Il codice seguente contiene l'intero metodo 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; 
}

Caricamento dinamico di un video

Per caricare in modo dinamico ognuno dei video, l'applicazione utilizza un oggetto NetConnection e un oggetto NetStream. Il codice seguente crea un oggetto NetConnection e passa il valore null al metodo connect(). Specificando null, Flash Player si collega a un video sul server locale anziché collegarsi a un server quale Flash Media Server.

Il codice seguente crea sia l'istanza NetConnection che l'istanza NetStream, definisce un listener di eventi per l'evento netStatus e assegna l'oggetto client alla proprietà client:

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

Il metodo netStatusHandler() viene chiamato ogni qual volta lo stato del video viene modificato; ad esempio quando la riproduzione del video viene avviata o interrotta, quando il video è in fase di bufferizzazione o se non è possibile trovare uno streaming video. Il codice seguente elenca l'evento 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. 
    } 
}

Il codice precedente valuta la proprietà code dell'oggetto info e filtra se il codice è “NetStream.Play.Start”, “NetStream.Play.StreamNotFound” o “NetStream.Play.Stop”. Tutti gli altri codici vengono ignorati. Se lo streaming di rete è in fase di avvio, il codice avvia l'istanza Timer che aggiorna l'indicatore di riproduzione. Se non è possibile trovare lo streaming di rete oppure è fermo, l'istanza Timer viene interrotta e l'applicazione tenta di riprodurre il video successivo all'interno della playlist.

Ogni volta che viene eseguita l'istanza Timer, la barra di avanzamento positionBar aggiorna la propria posizione corrente chiamando il metodo setProgress() della classe ProgressBar e l'istanza Label positionLabel viene aggiornata con il tempo trascorso e il tempo totale del video corrente.

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. 
    } 
}

Controllo del volume del video

Potete controllare il volume del video caricato dinamicamente impostando la proprietà soundTransform sull'oggetto NetStream. L'applicazione del video jukebox consente di modificare il livello del volume modificando il valore dell'istanza Slider volumeSlider. Il codice seguente mostra come modificare il livello del volume assegnando il valore del componente Slider a un oggetto SoundTransform che è impostato sulla proprietà soundTransform dell'oggetto NetStream:

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

Controllo della riproduzione video

Il resto dell'applicazione controlla la riproduzione video quando il video raggiunge la fine dello streaming video o l'utente salta al video precedente o successivo.

Il metodo seguente recupera l'URL del video dall'elemento XMLList dell'indice attualmente selezionato:

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

Il metodo playVideo() chiama il metodo play() sull'oggetto NetStream per caricare il video attualmente selezionato:

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

Il metodo playPreviousVideo() decrementa l'indice corrente del video, chiama il metodo playVideo() per caricare il nuovo file video e imposta la barra di avanzamento come visibile:

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

L'ultimo metodo, playNextVideo(), incrementa l'indice del video e chiama il metodo playVideo(). Se il video corrente è l'ultimo della playlist, il metodo clear() viene chiamato sull'oggetto Video e la proprietà visible dell'istanza della barra di avanzamento viene impostata su false:

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