Exemplo de vídeo: jukebox de vídeo

Flash Player 9 e posterior, Adobe AIR 1.0 e posterior

O exemplo a seguir cria uma jukebox de vídeo simples que carrega uma lista de vídeos dinamicamente para reprodução em sequência. Isso permite que você crie um aplicativo com o qual um usuário pode navegar por uma série de tutoriais em vídeo ou talvez especificar quais anúncios devem ser reproduzidos antes de reproduzir o vídeo solicitado pelo usuário. Este exemplo mostra os seguintes recursos do ActionScript 3.0:

  • Atualização de um indicador de reprodução com base no progresso da reprodução de um arquivo de vídeo

  • Monitoramento e análise dos metadados de um arquivo de vídeo

  • Manipulação de códigos específicos em um fluxo de rede

  • Carregamento, reprodução, pausa e interrupção de um FLV carregado dinamicamente

  • Redimensionamento de um objeto de vídeo na lista de exibição com base nos metadados do fluxo de rede

Para obter os arquivos de aplicativo desse exemplo, consulte www.adobe.com/go/learn_programmingAS3samples_flash_br . Os arquivos do aplicativo Jukebox de vídeo podem ser encontrados na pasta Samples/VideoJukebox. O aplicativo consiste nos seguintes arquivos:

Arquivo

Descrição

VideoJukebox.fla

ou

VideoJukebox.mxml

O arquivo principal do aplicativo para Flex (MXML) ou Flash (FLA).

VideoJukebox.as

A classe que fornece a funcionalidade principal do aplicativo.

playlist.xml

Um arquivo que lista quais arquivos de vídeo serão carregados na jukebox de vídeo.

Carregamento de um arquivo externo de lista de reprodução de vídeo

O arquivo externo playlist.xml especifica os vídeos que devem ser carregados e a ordem em que serão reproduzidos. Para carregar o arquivo XML, você precisa usar um objeto URLLoader e um objeto URLRequest, como visto neste código:

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

Este código é colocado no construtor da classe VideoJukebox para que o arquivo seja carregado antes da execução de qualquer outro código. Assim que termina o carregamento do arquivo XML, é chamado o método xmlCompleteHandler() , que analisa o arquivo externo em um objeto XML, como visto neste código:

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

O objeto XML playlist contém o XML bruto do arquivo externo, enquanto o XML do vídeo é um objeto XMLList que contém apenas os nós de vídeo. Um arquivo playlist.xml de exemplo pode ser visto no seguinte snippet:

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

Para finalizar, o método xmlCompleteHandler() chama o método main() , que configura as várias ocorrências de componente na lista de exibição, bem como os objetos NetConnection e NetStream que são usados para carregar os arquivos FLV externos.

Criação da interface de usuário

Para criar a interface de usuário, você precisa arrastar cinco ocorrências de Button até a lista de exibição e dar a elas os seguintes nomes de ocorrência: playButton , pauseButton , stopButton , backButton e forwardButton .

Para cada uma dessas ocorrências de Button, você terá de atribuir um manipulador para o evento click , como visto no seguinte snippet:

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

O método buttonClickHandler() usa uma instrução de opção para determinar qual ocorrência de Button foi clicada, como visto neste código:

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

Em seguida, adicione uma ocorrência de Slider à lista de exibição e dê a ela um nome de ocorrência de volumeSlider . O seguinte código define a propriedade liveDragging da ocorrência de Slider como true e um ouvinte de eventos para o evento change da ocorrência de Slider:

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

Adicione uma ocorrência de ProgressBar à lista de exibição e dê a ela um nome de ocorrência de positionBar . Defina a propriedade mode como manual, conforme visto no seguinte snippet:

positionBar.mode = ProgressBarMode.MANUAL;

Para terminar, adicione uma ocorrência de Label à lista de exibição e dê a ela um nome de ocorrência de positionLabel . O valor dessa ocorrência de Label será definido pela ocorrência de Timer.

Monitoramento dos metadados de um objeto de vídeo

Quando o Flash Player encontra metadados de cada um dos vídeos carregados, o manipulador de retorno de chamada onMetaData() é chamado na propriedade client do objeto NetStream. O seguinte código inicializa um Object e configura o manipulador de retorno de chamada especificado:

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

O método metadataHandler() copia seus dados para a propriedade meta definida anteriormente no código. Isso permite que você acesse os metadados do vídeo atual a qualquer momento em todo o aplicativo. Em seguida, o objeto de vídeo no Palco é redimensionado para corresponder às dimensões retornadas nos metadados. Por último, a ocorrência da barra de progresso positionBar é movida e redimensionada com base no tamanho do vídeo que está sendo reproduzido. O seguinte código contém o método metadataHandler() inteiro:

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

Carregamento dinâmico de um vídeo

Para carregar cada um dos vídeos dinamicamente, o aplicativo usa um objeto NetConnection e NetStream. O código a seguir cria um objeto NetConnection e passa null para o método connect() . Especificando null , o Flash Player se conecta a um vídeo do servidor local em vez de se conectar a um servidor, como o Flash Media Server.

O seguinte código cria ocorrências de NetConnection e de NetStream, define um ouvinte de eventos para o evento netStatus e atribui Object client à propriedade client :

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

O método netStatusHandler() é chamado sempre que o status do vídeo é alterado. Isso inclui as ocasiões em que a reprodução de um vídeo é iniciada ou interrompida, quando o vídeo é armazenado em buffer ou quando um fluxo de vídeo não é encontrado. O seguinte código lista o 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. 
    } 
}

O código anterior avalia a propriedade de código do objeto de informações e filtra se o código é “NetStream.Play.Start”, “NetStream.Play.StreamNotFound” ou “NetStream.Play.Stop”. Todos os demais códigos serão ignorados. Se o fluxo de rede estiver iniciando, o código iniciará a ocorrência de Timer que atualiza o indicador de reprodução. Se o fluxo de rede não for encontrado ou se for interrompido, a ocorrência de Timer será interrompida e o aplicativo tentará reproduzir o próximo vídeo da lista de reprodução.

Sempre que Timer é executado, a ocorrência da barra de progresso positionBar atualiza sua posição atual chamando o método setProgress() da classe ProgressBar, e a ocorrência de Label positionLabel é atualizada com o tempo decorrido e o total de tempo do vídeo atual.

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

Controle do volume do vídeo

É possível controlar o volume do vídeo carregado dinamicamente definindo a propriedade soundTransform no objeto NetStream. O aplicativo de jukebox de vídeo permite modificar o nível de volume alterando o valor da ocorrência de Slider volumeSlider . Este código mostra como alterar o nível de volume atribuindo o valor do componente Slider a um objeto SoundTransform, que é definido com a propriedade soundTransform no objeto NetStream:

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

Controle da reprodução de vídeo

O restante do aplicativo controla a reprodução de vídeos quando o vídeo chega ao final do fluxo ou quando o usuário acessa o vídeo anterior ou o próximo.

O seguinte método recupera a URL do vídeo no objeto XMLList relativo ao índice que está selecionado:

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

O método playVideo() chama o método play() no objeto NetStream para carregar o vídeo que está selecionado:

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

O método playPreviousVideo() reduz o índice de vídeos atual, chama o método playVideo() para carregar o novo arquivo de vídeo e define a barra de progresso como visível:

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

O último método, playNextVideo() , aumenta o índice de vídeos e chama o método playVideo() . Se o vídeo atual é o último da lista de reprodução, o método clear() é chamado no objeto Video, e a propriedade visible da ocorrência da barra de progresso é definida como false :

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