Wprowadzenie do

OSMF

To our english speaking friends. English version of this tutorial should be ready on Monday. Now you can download all the source in chapter: Źródła on the bottom. All comments are in english.

Słowem wstępu

Od kiedy pojawiły się pierwsze wzmianki o środowisku które ujednolici proces tworzenia media playerów, wiedziałem że to będzie coś czym będzie warto się zainteresować. Dlaczego zabieram się do tego dopiero teraz, skoro używać tego można było już rok temu? Ano dlatego że niedawno wydano OSMF Sprint 10 (ver. 0.93), a w tym wydaniu nastąpił tzw API Lock-down, czyli API nie powinno się już zmieniać. To znaczy że przykłady pisane do tej wersji będą w pełni zgodne z następnymi wersjami. Zatem czym jest Open Source Media Framework (codename Strobe)? W uproszczeniu jest to framework który pomaga zająć się wszystkimi rzeczami, które powinno się zrobić raz i które powinny być stosowalne w każdym innym projekcie wykorzystującym media każdego typu. Bardziej konkretnie mówiąc to OSMF jest rozszerzalny za pomocą pluginów framework do tworzenia rozbudowanych odtwarzaczy różnego typu mediów, w różnych konfiguracjach, ze wsparciem predefiniowanych jak i własnych systemów reklam oraz wiele więcej. Został stworzony by ułatwić życie przy tworzeniu media playerów oraz skrócić czas ich developementu. Każdy kto tworzy video playery na pewno zna te problemy, z którymi się spotyka przy ich tworzeniu. Zabierają one czas, którego nie ma, a każdy następny video player, choć niby podobny to trzeba jak zawsze wiele rzeczy zmieniać

Podstawy

Teraz czas pokazać jak to się je. Może najpierw trochę o podstawowych elementach jakich użyjemy w przykładowym playerze.

  • MediaElement – podstawowa klasa przechowująca informacje o medium, które chcemy odtworzyć. Wszystkie jej pochodne można dodać do MediaPlayer‚a. Oto kilka z subklas: VideoElement, AudioElement, SWFElement, ImageElement, ParallelElement oraz SerialElement.
  • VideoElement – Jak napisałem w punkcie powyżej jest to podstawowy element tego co chcemy pokazać. Przy tworzeniu nowej instancji wystarczy podać URL video jako instancje URLResource.
    var videoElement:VideoElement = new VideoElement(new URLResource(VIDEO_URL));
    
  • MediaPlayer – kontroler przez którego operujemy MediaElement’em który załadowaliśmy. Ważnymi informacjami jakie możemy odczytać z mediaPlayer’a są tzw „traits”. Są to cechy mediaElement’u takie jak: canPlay, canPause, canSeek albo canLoad. Są one pomocne przy określaniu które elementy interfejsu mają być aktywne. Nowy element przypisujemy do właściwości media. Jeśli chcemy nasłuchiwać jak zmienia się stan naszego mediaElementu to wszystkie eventListenery przypisujemy przez MediaPlayer.
    var mediaPlayer:MediaPlayer = new MediaPlayer();
    mediaPlayer.media = videoElement;
    
  • MediaContainer – Warto wspomnieć, że żadna z powyżej przedstawionych klas nie ma swojej wizualnej reprezentacji tzn nie dziedziczy po DisplayObject więc nie można jej dodać do sceny. I tutaj najwyższy czas na klasę która jest tym kontenerem, który renderuje wszystkie dodane media. MediaContainer dziedziczy po Sprite. MediaElement dodajemy przez metodę addMediaElement.
    var mediaContainer:MediaContainer = new MediaContainer();
    mediaContainer.addMediaElement(videoElement);
    addChild(mediaContainer);
    

User Interface

To tyle z takich najbardziej podstawowych elementów niezbędnych do stworzenia prostego video playera. Składając te elementy razem otrzymamy video wyświetlające podany film. Tylko nie mamy jeszcze możliwości operowania tym filmem. Cały UI musimy napisać sami gdyż jest to część niezależna od wyświetlanego video, a klasa MediaPlayer jest tylko interfejsem przez który sterujemy wyświetlanym kontentem. Dla mało wymagających jest biblioteka o nazwie ChromeLibrary która zawiera oprogramowany interfejs gotowy do wykorzystania. Można go znaleźć w ZIPie ze źródłami pod ścieżką: source/libs/ChromeLibrary/. Przykładowy player wykorzystujący ChromeLibrary jest do przejrzenia pod ścieżką: source/apps/samples/framework/OSMFPlayer. Wszystkie niezbędne informacje są w źródłach.

W moim przykładzie wykorzystuję MinimalComps autorstwa Keitha Petersa aka BIT-101. Jest to zestaw świetnych i bardzo prostych komponentów, które najlepiej sprawdzają się w aplikacjach testowych lub przykładowych. Dzięki temu do otworzenia tego przykładu nie potrzebujemy Flash’a. Wystarczy Flex SDK oraz wymagane biblioteki. Cały proces tworzenia UI jest wewnątrz funkcji createUI(). Wydaje mi się że opisywanie tej części nie jest potrzebne do zrozumienia tematu posta. Jeśli macie pytania, piszcie je w komentarzach.

Layout

OK, więc mamy już nasz film wyświetlony na scenie i gra. Współgra z nim user interface. Wygląda to tak:

Application layout

Teraz chcemy sami określić w jaki sposób ma pojawiać się video w naszym playerze. Tutaj przychodzi z pomocą layoutMetadata. Jest to właściwość typu LayoutMetadata każdego obiektu ( implementującego ILayoutTarget. LayoutMetadata zawiera całą masę różnych parametrów, które ustawią nasz kontent.

Oto lista właściwości LayoutMetadata:

  • horizontalAlign oraz verticalAlign (Przyjmują wartości stałych statycznych z klas HorizontalAlign orazVerticalAlign);
  • x, y, width oraz height;
  • percentX, percentY, percentWidth oraz percentHeight;
  • scaleMode (Przyjmuje wartości stałych statycznych z klasy ScaleMode);
  • layoutMode (Przyjmuje wartości stałych statycznych z klasy LayoutMode);
  • left, right, top oraz bottom;
  • paddingLeft, paddingRight, paddingTop oraz paddingBottom;
  • snapToPixel
  • includeInLayout
  • synthesizer

Większości z tych właściwości nie trzeba wyjaśniać. Po resztę odsyłam do Language Reference.

W swoim przykładzie dodałem opcję dynamicznego zmieniania rodzaju skalowania video (kontrolka w prawym górnym rogu). Aby ustawić sposób wyświetlania jaki chcemy to musimy zmienić parametry właściwości layoutMetadata. W przypadku MediaElement musimy utworzyć nową instancję klasy LayoutMetadata, przypisać wszystkie wartości jakie chcemy, a na końcu skorzystać z metody addMetadata. Podany przykład wyłącza skalowanie (zoom = 100%) i ustawia video pośrodku kontenera:

//Przypisanie layoutMetadata do mediaContainera (MediaContaiener)
mediaContainer.layoutMetadata.width = videoCont.width;
mediaContainer.layoutMetadata.height = videoCont.height;
mediaContainer.layoutMetadata.scaleMode = ScaleMode.NONE;

//Przypisanie layoutMetadata do videoElementu przez addMetadata (MediaElement)
var layoutMetadata:LayoutMetadata = new LayoutMetadata();
layoutMetadata.scaleMode = ScaleMode.NONE;
layoutMetadata.width = videoCont.width;
layoutMetadata.height = videoCont.height;
layoutMetadata.horizontalAlign = HorizontalAlign.CENTER;
layoutMetadata.verticalAlign = VerticalAlign.MIDDLE;
videoElement.addMetadata(LayoutMetadata.LAYOUT_NAMESPACE, layoutMetadata);

MediaElement

Teraz może trochę o klasach, które przechowują wszystkie informacje o tym, co chcemy wrzucić do media playera. Podstawową klasą jest MediaElement. Mając gotowe wszystkie elementy tj mediaPlayer oraz mediaContainer wystarczy tylko stworzyć nową instancję wybranej subklasy MediaElement‚u oraz dodać go do mediaPlayer‚a oraz mediaContainer‚a.

var myVideo:VideoElement = new VideoElement(new URLResource(VIDEO_URL))
mediaPlayer.media = myVideo
mediaContainer.addMediaElement(myVideo);

W ten sposób dodaliśmy video do mediaPlayer‚a, aby można było nim sterować, oraz do mediaContainer‚a, aby można było zobaczyć nasze video. Z tak niewielkim kawałkiem kodu dodaliśmy nowy element. Co ciekawe, równie łatwo możemy zmieniać aktualnie puszczane media. Należy tylko pamiętać aby usunąć poprzednio załadowane medium z mediaContainera używając metody removeMediaElement.

Przydałoby się również opisać po krótce resztę używanych tutaj MediaElement‚ów. Oto one:

  • AudioElement – pozwala na odtwarzanie dzwięku zarówno streamingowanego jak i progresywnie ładowanego. Można załadować MP3 oraz AAC.
  • ImageElement – dzięki niemu możemy pokazać obrazy wewnątrz naszego playera. Wspiera PNG, GIF oraz JPG.
  • SWFElement – tutaj możemy załadować dowolny swf.
  • ParallelElement – jak nazwa wskazuje, kilka elementów odtwarzanych jednocześnie. Np. zdjęcie z podkładem muzycznym albo wyciszone video z różnymi ścieżkami dźwiękowymi.
  • SerialElement – element ten wyświetla dodane elementy jeden po drugim. Np. możemy połączyć kilka video w jedno.

Należy pamiętać że wszystkie ustawienia Layoutu opisane wcześniej, tyczą się również podanych tutaj MediaElement‚ów (jeśli jest taka możliwość, bo wiadomo że nie przeskalujemy odtwarzanej mp3 do wielkości kontenera). A właśnie. wyświetlając kilka różnych typów MediaElement‚ów możemy natrafić na taki problem. Chcemy wiedzieć tylko na podstawie MediaElement‚u jakie jego cechy są dostępne (Np. odtwarzanie/pauzowanie lub przewijanie)

Traits

Najwyższy czas na koncepcję Traits. Są to cechy danego elementu opisujące co on może robić. Mamy do nich łatwy dostęp przez serię właściwości MediaElement‚u. Oto kilka z nich: canPlay, canPause, canSeek oraz canLoad. Jeśli chcemy śledzić jak się one zmieniają i reagować na te zmiany (np aby wyłączyć elementy interfejsu niedostępne dla aktualnego elementu. Wystarczy dodać eventListenery do mediaPlayer‚a. Oto kod:

mediaPlayer.addEventListener(MediaPlayerCapabilityChangeEvent.CAN_PLAY_CHANGE, onCanPlayChange);
mediaPlayer.addEventListener(MediaPlayerCapabilityChangeEvent.CAN_SEEK_CHANGE, onCanSeekChange);

private function onCanPlayChange(e:MediaPlayerCapabilityChangeEvent):void
{
    playPauseBtn.enabled = e.enabled
    stopBtn.enabled = e.enabled
}

private function onCanSeekChange(e:MediaPlayerCapabilityChangeEvent):void
{
    progressBar.enabled = e.enabled
}

W ten sposób mamy pewność że każde odtwarzane medium ma poprawne dostępne kontrolki.

Źródła

Cały projekt nie wymaga posiadania Adobe Flash Professional CS4 ani żadnego innego. Wystarczy Flex SDK. Należy pamietać, że targetem jest Flash Player 10 i takiego wymaga OSMF. Oczywiście można skompilować go we Flashu. Wystarczy podać pełną nazwę klasy w Document Class oraz pamiętać aby dodać pliki SWC do Publish Settings.

Cała przykładowa aplikacja jest objęta licencją MIT, więc możecie dowolnie z niej korzystać w dowolnym celu.

Cała aplikacja (live): link;
Cała aplikacja (źródła): link;

OSMF: osmf.org;
OSMF downloads: link;
OSMF Language Reference: link;

Podsumowanie

Open Source Media Framework jest genialną rzeczą, która zwalnia nas z ciągłego zmagania się z tymi samymi problemami, pozwalając zająć się tym co ważne przy tworzeniu media playerów. Przyjazne oraz intuicyjne API zachęca do głębszego zapoznania się z ogromnymi możliwościami OSMF. Według mnie naprawdę warto! Jeśli jest coś co chcielibyście zobaczyć w kolejnym artykule, znaleźliście jakieś nieścisłości, niepełne wyjaśnienie albo cokolwiek co was intryguje, zostawcie mi wiadomość w komentarzu. Wszelkie pomysły oraz uwagi mile widziane.

Pozdrawiam,
Michał Wróblewski