Przykład pracy z wideo: odtwarzacz wideo

Flash Player 9 i nowsze wersje, Adobe AIR 1.0 i nowsze wersje

Poniższy przykład tworzy prosty odtwarzacz wideo, który dynamicznie ładuje listę plików wideo do odtworzenia i umożliwia odtworzenie ich po kolei. W ten sposób możemy zbudować aplikację, która pozwoli użytkownikowi na przeglądanie serii samouczków wideo lub określi, na przykład, która reklama powinna być odtworzona przed właściwym materiałem wideo wybranym przez użytkownika. Przykład ilustruje następujące techniki w języku ActionScript 3.0:

  • Aktualizacja położenia głowicy odtwarzania na podstawie postępu odtwarzania pliku wideo.

  • Wykrywanie i analizowanie metadanych pliku wideo.

  • Obsługa konkretnych kodów w strumieniu NetStream.

  • Ładowanie, odtwarzanie, wstrzymywanie i zatrzymywania odtwarzania dynamicznie załadowanego pliku FLV.

  • Zmiana rozmiaru obiektu wideo na liście wyświetlania na podstawie metadanych strumienia NetStream.

Aby pobrać pliki tej przykładowej aplikacji, należy przejść na stronę www.adobe.com/go/learn_programmingAS3samples_flash_pl . Pliki aplikacji Video Jukebox znajdują się w folderze Samples/VideoJukebox. Aplikacja składa się z następujących plików:

File

Opis

VideoJukebox.fla

lub

VideoJukebox.mxml

Główny plik aplikacji dla środowiska Flex (MXML) lub programu Flash (FLA).

VideoJukebox.as

Klasa realizująca podstawowe funkcje aplikacji.

playlist.xml

Plik z listą plików wideo, które zostaną załadowane do odtwarzacza.

Ładowanie zewnętrznego pliku z listą odtwarzania plików wideo

Zewnętrzny plik playlist.xml file określa, które pliki wideo mają zostać załadowane, oraz w jakiej kolejności powinny być odtwarzane. Aby załadować plik XML, musimy użyć obiektu URLLoader oraz obiektu URLRequest, co ilustruje poniższy kod:

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

Ten kod znajduje się w konstruktorze klasy VideoJukebox, a zatem plik jest ładowany przed wykonaniem innych części kodu. Po zakończeniu ładowania pliku XML wywoływana jest metoda xmlCompleteHandler() , która analizuje plik zewnętrzny i przekształca go w obiekt XML, co zilustrowano poniżej:

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

Obiekt XML playlist zawiera nieprzetworzony kod XML z pliku zewnętrznego, natomiast obiekt XML videos to obiekt XMLList zawierający tylko węzły video. Poniższy urywek kodu przedstawia przykładowy plik playlist.xml:

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

Na koniec metoda xmlCompleteHandler() wywołuje metodę main() , która konfiguruje różne instancje składników na liście wyświetlania, a także obiekty NetConnection i NetStream służące do ładowania zewnętrznych plików FLV.

Tworzenie interfejsu użytkownika

Aby zbudować interfejs użytkownika, należy przeciągnąć pięć instancji klasy Button na listę wyświetlania i nadać im następujące nazwy: playButton , pauseButton , stopButton , backButton i forwardButton .

Dla każdej z tych instancji klasy Button należy przypisać funkcję obsługi zdarzenia click , co ilustruje poniższy urywak kodu:

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

Metoda buttonClickHandler() zawiera instrukcję switch określającą, który przycisk został kliknięty, co ilustruje poniższy kod:

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

Następnie należy dodać instancję klasy Slider do listy wyświetlania i nadać jej nazwę volumeSlider . Poniższy kod ustawia właściwość liveDragging instancji suwaka na true i definiuje detektor zdarzeń change dla tej instancji:

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

Należy dodać instancję klasy ProgressBar do listy wyświetlania i nadać jej nazwę positionBar . Właściwości mode tej instancji przypisujemy wartość manual, co ilustruje poniższy urywek kodu:

positionBar.mode = ProgressBarMode.MANUAL;

Na koniec należy dodać instancję klasy Label do listy wyświetlania i nadać jej nazwę positionLabel . Wartość tej instancji klasy Label będzie ustawiana przez instancję klasy Timer.

Wykrywanie metadanych obiektu wideo

Gdy program Flash Player napotyka metadane każdego z ładowanych plików wideo, zwrotnie wywoływana jest funkcja onMetaData() właściwości client obiektu NetStream. Poniższy kod inicjuje obiekt Object i konfiguruje określoną funkcję obsługi wywołania zwrotnego:

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

Metoda metadataHandler() kopiuje dane do właściwości meta zdefiniowanej wcześniej w kodzie. Umożliwia to dostęp do metadanych bieżącego pliku wideo w dowolnym momencie, w całej aplikacji. Następnie wymiary obiektu wideo na stole montażowym są dopasowywane do wymiarów odczytanych z metadanych. Na koniec instancja paska postępu positionBar jest przemieszczana, a jej rozmiar jest aktualizowany na podstawie rozmiaru aktualnie odtwarzanego pliku wideo. Poniższy kod zawiera całą metodę 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; 
}

Dynamiczne wczytywanie wideo

Do dynamicznego ładowania poszczególnych plików wideo aplikacja używa obiektów NetConnection i NetStream. Poniższy kod tworzy obiekt NetConnection i przekazuje wartość null do metody connect() . Wartość null powoduje, że program Flash Player łączy się z serwerem lokalnym, a nie z serwerem zdalnym, takim jak Flash Media Server.

Poniższy kod tworzy instancje klas NetConnection i NetStream, definiuje detektor zdarzeń netStatus i przypisuje obiekt client klasy Object do właściwości client :

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

Metoda netStatusHandler() jest wywoływana po każdej zmianie statusu wideo. Do takich zmian zalicza się rozpoczęcie i zatrzymanie odtwarzania, buforowanie wideo lub brak możliwości znalezienia strumienia wideo. Poniższy kod analizuje listę wartości przekazanej ze zdarzeniem 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. 
    } 
}

Kod przedstawiony powyżej odczytuje właściwość code obiektu informacyjnego i filtruje kody "NetStream.Play.Start", "NetStream.Play.StreamNotFound" oraz "NetStream.Play.Stop". Wszystkie pozostałe kody będą ignorowane. Jeśli zdarzenie informuje o rozpoczęciu odtwarzania strumienia wideo, uruchamiana jest instancja klasy Timer, która aktualizuje położenie głowicy odtwarzania. Jeśli nie jest możliwe znalezienie strumienia lub odtwarzanie zostało zatrzymane, obiekt Timer jest zatrzymywany, a aplikacja próbuje odtworzyć następny plik wideo z listy odtwarzania.

Przy każdym wywołaniu obiektu Timer instancja paska postępu positionBar aktualizuje swoje bieżące położenie, wywołując metodę setProgress() klasy ProgressBar, a instancja klasy Label positionLabel jest aktualizowana poprzez wpisanie czasu od początku odtwarzania i całkowitego czasu trwania bieżącego pliku wideo.

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

Sterowanie głośnością wideo

Istnieje możliwość sterowania głośnością dynamicznie załadowanego wideo poprzez przypisywanie wartości właściwości soundTransform obiektu NetStream. Aplikacja odtwarzacza umożliwia modyfikowanie głośności poprzez zmianę wartości instancji volumeSlider . Poniższy kod ilustruje sposób zmiany głośności poprzez przypisanie wartości składnika Slider do obiektu SoundTransform we właściwości soundTransform obiektu NetStream:

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

Sterowanie odtwarzaniem wideo

Pozostały kod aplikacji steruje odtwarzaniem wideo po osiągnięciu końca strumienia wideo lub wymuszonego przez użytkownika przeskoku do poprzedniego lub następnego pliku wideo.

Poniższa metoda pobiera adres URL wideo z obiektu XMLList dla aktualnie wybranego indeksu:

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

Metoda playVideo() wywołuje metodę play() obiektu NetStream w celu załadowania aktualnie wybranego wideo:

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

Metoda playPreviousVideo() dekrementuje indeks bieżącego pliku wideo, wywołuje metodę playVideo() w celu załadowania nowego pliku wideo i sprawia, że pasek postępu staje się widoczny:

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

Ostatnia metoda, playNextVideo() , inkrementuje indeks pliku wideo i wywołuje metodę playVideo() . Jeśli bieżący plik wideo jest ostatnim na liście odtwarzania, wywoływana jest metoda clear() obiektu Video, a właściwość visible instancji paska postępu jest ustawiana na false :

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