Wideo online z Wowza i Amazon Elastic Transcoder

Opublikowany: 2022-03-11

Sukces i przyjęcie dowolnej aplikacji internetowej w dzisiejszych czasach w dużym stopniu zależy od jej wydajności, elastyczności i łatwości użytkowania.

Zwłaszcza w dzisiejszym świecie ADHD użytkownicy szybko stracą cierpliwość do aplikacji, jeśli jej ładowanie strony trwa zbyt długo. W przypadku aplikacji internetowych, które muszą obsługiwać przetwarzanie wideo — które z natury wymaga dużych mocy obliczeniowych i operacji we/wy — to wyzwanie jest szczególnie dotkliwe. Użytkownicy stają się jednak coraz bardziej wymagający, chcąc, aby ich filmy były wysokiej jakości i szybko się ładowały, nawet jeśli działają na smartfonie lub tablecie.

Użytkownicy tracą też tolerancję na aplikacje internetowe, które nie działają w preferowanej przez nich przeglądarce lub urządzeniu albo nie obsługują formatu danych, który muszą być załadowane lub wyeksportowane. Różnorodność formatów wideo, które muszą być obsługiwane, sprawia zatem, że włączenie obsługi wideo do aplikacji internetowej jest szczególnie trudne.

Ten post opisuje, w jaki sposób skutecznie wykorzystałem technologie open source i usługi oparte na chmurze, aby włączyć funkcje wideo do aplikacji internetowej opartej na PHP.

Przetwarzanie wideo online w PHP z Wowza i Amazon Elastic Transcoder

Przypadek użycia

Byłem częścią zespołu, który musiał stworzyć witrynę podobną do YouTube, na której zarejestrowani użytkownicy mogli przesyłać i udostępniać swoje filmy.

System musiał umożliwić zarejestrowanym użytkownikom przesyłanie filmów w różnych obsługiwanych formatach, które następnie byłyby konwertowane do wspólnego formatu (MP4). Musieliśmy również wygenerować zestaw miniatur i kolaż obrazów, który miał być używany w odtwarzaczu wideo do wyświetlania klatek na pasku postępu wideo.

Sprawę dodatkowo komplikował fakt, że wymagania klienta uniemożliwiały nam korzystanie z jakiegokolwiek dostępnego CDN lub API transkodowania, więc musieliśmy opracować nasze rozwiązanie od podstaw.

Przesyłanie wideo

Ponieważ sam proces przesyłania nie musiał być specyficzny dla wideo (potrzebowaliśmy tylko łatwej w użyciu funkcji przesyłania plików), sensowne było korzystanie z istniejącego rozwiązania typu open source zamiast rozwijania własnego. Wybraliśmy jQuery-File-Upload, przede wszystkim dlatego, że obsługuje dwie funkcje, które były kluczowe w naszym przypadku; mianowicie pasek postępu przesyłania i przesyłanie fragmentaryczne.

Przesyłanie fragmentaryczne umożliwiło użytkownikowi przesłanie pliku wideo o praktycznie dowolnym rozmiarze (szczególnie ważne, aby obsługiwać pliki wideo w rozdzielczości HD). Dzięki takiemu podejściu plik jest podzielony na wiele „fragmentów” w interfejsie użytkownika, które wywołują akcję przesyłania z każdą porcją danych (wraz z metadanymi dla każdej porcji, takimi jak numer porcji i całkowity rozmiar pliku). Cały plik wideo jest następnie ponownie składany na zapleczu. Nawiasem mówiąc, uwzględnienie numeru porcji w metadanych okazało się szczególnie ważne, ponieważ niektóre przeglądarki (takie jak Mobile Safari) mają tendencję do przesyłania porcji w losowej kolejności.

Przetwarzanie wideo online

Przetwarzanie wideo może być tak proste, jak przechwytywanie klatek jako nieruchomych obrazów, lub może obejmować bardziej złożone operacje, takie jak ulepszanie obrazu, stabilizacja strumienia wideo i tak dalej. W naszym przypadku jedynymi wymaganiami dotyczącymi przetwarzania wideo były (a) wyodrębnienie kodeków wideo i innych kluczowych metadanych oraz (b) wygenerowanie zestawu miniatur i kolażu obrazów (do wykorzystania w odtwarzaczu wideo do wyświetlania klatek w postępie wideo bar).

FFmpeg – powszechnie używana, swobodnie dystrybuowana biblioteka typu open source – była niezwykle pomocna w spełnieniu tych wymagań. FFmpeg zapewnia kompletne, wieloplatformowe rozwiązanie do nagrywania, konwertowania i przesyłania strumieniowego plików audio i wideo. Może być również używany do konwertowania filmów i wykonywania prostej edycji (np. przycinanie, wycinanie, dodawanie znaku wodnego itp.).

Dla naszych celów byliśmy w stanie użyć FFmpeg, aby podzielić wideo na dziesięć sekcji, a następnie przechwycić miniaturę dla każdej sekcji, aby zapewnić potrzebną funkcjonalność.

Niestety, nie ma powiązań języka PHP dla biblioteki FFmpeg. W rezultacie jedynym sposobem wykorzystania FFmpeg z PHP jest wywołanie pliku binarnego z wiersza poleceń za pomocą poleceń systemowych. Istnieją zasadniczo dwa sposoby użycia FFmpeg w PHP:

  • libav. Libav to projekt wolnego oprogramowania, wywodzący się z FFmpeg w 2011 roku, który tworzy biblioteki i programy do obsługi danych multimedialnych. Na przykład w Ubuntu można to zainstalować za pomocą polecenia sudo apt-get install libav-tools . Polecenia libav są kompatybilne z FFmpeg i avconv. PHP musi mieć dostęp z wiersza poleceń do ffmpeg/avconv , aby używać tego programowo.
  • PHP-FFMpeg. PHP-FFMpeg to zorientowany obiektowo sterownik PHP dla pliku binarnego FFMpeg. Dostęp do niego można uzyskać, wykonując po prostu composer update "php-ffmpeg/php-ffmpeg" .

Użyliśmy PHP-FFMpeg, ponieważ zapewnia łatwy dostęp do interesującej nas funkcjonalności FFmpeg. Na przykład klasa FFProbe z tego pakietu umożliwia otrzymywanie informacji o kodekach lub długości konkretnego pliku wideo w następujący sposób:

 $ffprobe = FFMpeg\FFProbe::create(); $ffprobe ->format('/path/to/video/mp4') // extracts file informations ->get('duration');

FFmpeg ułatwia również zapisanie dowolnej klatki wideo:

 $ffmpeg = FFMpeg\FFMpeg::create(); $video = $ffmpeg->open('video.mpg'); $video ->frame(FFMpeg\Coordinate\TimeCode::fromSeconds(10)) ->save('frame.jpg');

Bardziej szczegółowy przykładowy kod jest dostępny tutaj.

Jedna uwaga: ze względu na niektóre prawa patentowe, nie wszystkie kodeki mogą być przetwarzane przez FFmpeg, a niektóre formaty nie są właściwie (lub w pełni) obsługiwane. Pamiętam, że kilka lat temu zmagałem się na przykład z formatem .3gp , kiedy obsługa telefonów z internetem była koniecznością.

Kolejkowanie

Po uzyskaniu kodeków wideo i innych metadanych przesyłamy wideo do kolejki konwersji FIFO (pierwsze weszło, pierwsze wyszło). Kolejka została zaimplementowana za pomocą prostego skryptu cron, który przy każdym uruchomieniu wybiera określoną liczbę nieprzetworzonych filmów i przekazuje je do narzędzia do konwersji (przykładowy kod źródłowy dostępny tutaj).

Narzędzie do konwersji wywołuje FFMpeg w celu przeprowadzenia konwersji i oznacza każde wideo jako przetworzone.

Opracowaliśmy również prosty mechanizm szacowania czasu oczekiwania, który oblicza średni czas konwersji 1 minuty wideo. Korzystając z tej średniej, jesteśmy w stanie obliczyć i wyświetlić użytkownikowi szacowany pozostały czas przetwarzania po zakończeniu przesyłania filmu w oparciu o liczbę minut filmu do przetworzenia.

Konwersja formatu wideo

Niektóre powszechnie rozpoznawane formaty (takie jak JPEG i GIF) pojawiły się w przypadku obrazów nieruchomych, które są zasadniczo obsługiwane przez wszystkie urządzenia i oprogramowanie do przetwarzania obrazu. Chociaż niektóre formaty wideo są bardziej popularne niż inne, nie pojawił się jeszcze taki powszechnie obsługiwany format dla filmów.

W naszym przypadku, oprócz konieczności konwersji z różnych formatów do jednego, popularnego formatu (MPEG-4), potrzebowaliśmy zoptymalizowania konwertowanych filmów do przesyłania strumieniowego na urządzenia mobilne.

W przypadku konwersji formatu wideo (przynajmniej dla naszych krótkoterminowych potrzeb) najlepszą dostępną opcją było użycie opartego na chmurze Amazon Elastic Transcoder . Oprócz ogólnej łatwości użytkowania usługa transkodera zajmuje się optymalizacją i wszystkimi ustawieniami kodowania. Na szczęście dostępny jest pakiet AWS SDK dla PHP, który upraszcza wywoływanie usługi z naszego kodu PHP.

Uwaga: korzystanie z usługi opartej na chmurze, takiej jak Amazon Elastic Transcoder, jest świetne, jeśli chcesz szybko rozpocząć pracę. Pamiętaj jednak, że ta opcja może być kosztowna dla Twojego klienta, zwłaszcza jeśli jego model biznesowy prawdopodobnie będzie wymagał intensywnego korzystania z dużych filmów. Innym czynnikiem, który należy wziąć pod uwagę, jest to, że niekoniecznie należy zakładać, że filmy lub model biznesowy Twojego klienta będą zgodne z Warunkami korzystania z usługi.

Amazon używa swoich podstawowych elementów pamięci masowej i obliczeniowych, S3 (Simple Storage Service) i EC2 (Elastic Compute Cloud) – w połączeniu z Auto Scaling i SNS (Simple Notification Service) – aby zapewnić możliwość praktycznie natychmiastowego skalowania w górę i w dół.

Instalacja aws-sdk jest prosta, ponieważ Amazon utrzymuje wersję pakietu, którą można zainstalować w programie Composer. Po prostu dodaj ”aws/aws-sdk-php": "2.*" do swojego pliku composer.json i wykonaj composer update .

Oczywiście dostęp do Amazon Elastic Transcoder wymaga konta Amazon, więc musisz to również skonfigurować, jeśli Ty (lub Twój klient) jeszcze go nie masz.

Korzystanie przez nas z usługi Amazon Elastic Transcoder wymagało najpierw załadowania plików wideo do odpowiedniego zasobnika w S3. Następnie wykonaliśmy zadanie transkodera odpowiedzialne za dekodowanie i generowanie miniatury, która po zakończeniu wysyła żądanie HTTP na podany adres. To wymaga pewnej konfiguracji w panelu AWS, ale jest to dość proste, a Amazon zapewnia dobrą dokumentację, jak to zrobić.

Zachęcamy do skorzystania z naszego pakietu transkoderów, który pomaga uprościć integrację z Symfony 2. Zawiera opis użytkowania i oferuje kontroler do szybkiego wdrożenia usługi powiadamiania wysyłanego przez Amazon w celu zbierania informacji o przetworzonym wideo. Przykład użycia dostępny jest tutaj.

Dodatkowo dostępny jest tutaj przykładowy kontroler obsługujący powiadomienia Amazon, który realizuje również potwierdzenie adresu subskrypcji. Usługa najpierw opublikuje adres URL do odwiedzenia, aby potwierdzić, że jest to prawidłowy odbiorca powiadomień. Wszystko, co jest wtedy naprawdę wymagane, to oznaczenie wideo jako przetworzonego. Od tego momentu możemy korzystać z transkodowanego wideo przechowywanego w chmurze.

Streaming

Strumieniowe przesyłanie wideo to funkcja, która wymaga wysokiej wydajności: oczekiwania użytkowników dotyczące nieprzerwanego przesyłania strumieniowego są wysokie, a tolerancja na opóźnienia jest niezwykle niska. To wyzwanie jest często potęgowane przez potrzebę strumieniowego przesyłania wideo do wielu klientów jednocześnie w czasie rzeczywistym.

W naszym przypadku musieliśmy zapewnić każdemu użytkownikowi możliwość stworzenia własnego kanału wideo i rozpoczęcia nadawania. Nasze rozwiązanie składało się z trzech komponentów:

  • Deska rozdzielcza. Aplikacja pełniąca rolę dashboardu streamera, dająca możliwość obsługi wideo.
  • Widz. Klient wideo, który zużywa i wyświetla strumień wideo.
  • Silnik strumieniowy. Usługa przesyłania strumieniowego wideo w chmurze.

Oprócz tego, że technologia wideo na żądanie (VOD) wciąż ewoluuje, innym problemem, z którym się zmierzyliśmy, było to, że dostęp do kamery nie był dobrze obsługiwany i oferował tylko połączenie P2P. Naszym celem było również zapewnienie transmisji online dla wielu równoczesnych użytkowników. Ponadto obsługa interfejsu API getUserMedia/Stream (wcześniej wyobrażanego jako element <device> ) nie jest jeszcze spójna we współczesnych przeglądarkach. Biorąc pod uwagę te czynniki, zdecydowałem się na użycie technologii Flash, ponieważ była to naprawdę jedyny rozsądny wybór. Obie aplikacje (Dashboard i Viewer) zostały zatem zaimplementowane przy użyciu Flex i ActionScript .

Do silnika strumieniowego użyliśmy Wowzy . Chociaż istnieją inne, niekomercyjne rozwiązania (takie jak Red5, który jest sprzedawany jako zasadniczo zamiennik dropinu dla Wowzy), w naszym przypadku wsparcie produktu komercyjnego było ważnym czynnikiem. Ponadto, przynajmniej w czasie, gdy budowaliśmy system, Wowza oferowała lepszą dokumentację, co było dodatkowym atutem. (Pamiętaj, że możesz pobrać wersję próbną Wowzy za darmo przez 30 dni, a także jest wersja próbna dewelopera, z której możesz korzystać do 180 dni. Istnieją jednak pewne ograniczenia; strumieniowanie może działać tylko dla dwóch klientów i są ograniczenia na maksymalną liczbę połączeń.)

Wowza Streaming Engine

Wykorzystaliśmy aplikację LiveStream dostarczoną z Wowzą. Aby to skonfigurować, pozostaw applications/app_name puste i w conf/app_name skopiuj plik Application.xml z katalogu conf . Edytuj plik, aby skonfigurować sekcję <Streams> w następujący sposób:

 <Streams> <StreamType>live</StreamType> <StorageDir>${com.wowza.wms.context.VHostConfigHome}/content</StorageDir> <KeyDir>${com.wowza.wms.context.VHostConfigHome}/keys</KeyDir> <LiveStreamPacketizers></LiveStreamPacketizers> <Properties></Properties> </Streams>

Kluczowym parametrem jest <StreamType>live</StreamType> , który określa, że ​​będzie to strumień z przekazu wideo na żywo (np. z kamery). Zauważ, że po edycji i zapisaniu tego pliku będziesz musiał ponownie uruchomić Wowzę.

Aplikacje Flash (Flex/ActionScript)

Flash zapewnia w pełni zintegrowany system do podłączenia kamery i mikrofonu do serwera strumieniowego Wowza. Jest to szczególnie przydatne, jeśli masz ograniczone doświadczenie z ActionScript.

Cała aplikacja zasadniczo opiera się na interakcji między następującymi obiektami:

  • Połączenie sieciowe. Klasa NetConnection tworzy dwukierunkowe połączenie między klientem a serwerem. Klientem może być aplikacja Flash Player lub AIR. Serwerem może być serwer WWW, Flash Media Server, serwer aplikacji z uruchomionym Flash Remoting lub usługa Adobe Stratus.
  • Kamera. Klasa Camera służy do przechwytywania wideo z systemu klienta lub kamery urządzenia.
  • Mikrofon. Klasa Microphone służy do monitorowania lub przechwytywania dźwięku z mikrofonu.
  • NetStream. Klasa NetStream otwiera jednokierunkowy kanał przesyłania strumieniowego przez NetConnection.

Najpierw łączymy się z serwerem streamingowym Wowza za pomocą instancji NetConnection, a następnie dołączamy detektor zdarzeń, który będzie nasłuchiwał zmian w stanie połączenia sieciowego:

 nc = new NetConnection(); nc.connect(serverAddress:string); nc.addEventListener( NetStatusEvent.NET_STATUS, // event type eNetStatus, // listener function false, // use capture? 0, // priority true // use weak reference? );

Oto minimalistyczny przykład detektora zdarzeń, który łączy kamerę i mikrofon z serwerem strumieniowym:

 private function eNetStatus(e:NetStatusEvent):void { switch (e.info.code) { case "NetConnection.Connect.Success": camera = Camera.getCamera(); mic = Microphone.getMicrophone(); ns = new NetStream(nc); ns.publish(streamName, "live"); ns.attachCamera(camera); ns.attachAudio(mic); break; case "NetConnection.Connect.Closed": // debug trace... display user message break; }

Kod klienta jest bardzo podobny, z wyjątkiem tego, że po stronie użytkownika wyświetlamy tylko wejście wideo. Odbywa się to poprzez połączenie strumienia z obiektem Video , jak pokazano w tym prostym przykładzie:

 if(event.info.code == "NetConnection.Connect.Success") { ns = new NetStream(nc); ns.client = nsClient; ns.addEventListener(NetStatusEvent.NET_STATUS, nsClient.onNetStatus); ns.play(streamName); video = new Video(); addChild(video); // this will display video video.attachNetStream(ns); // connect NetStream to video }

Zakończyć

Można oczekiwać, że transmisja strumieniowa na żywo i wideo będą odgrywać coraz większą rolę w aplikacjach mobilnych i internetowych. Dlatego ważne jest, aby twórcy stron internetowych zapoznali się z transkodowaniem, przetwarzaniem i przesyłaniem strumieniowym wideo. Obecnie istnieje wiele narzędzi, bibliotek i usług służących do włączania tych możliwości do aplikacji internetowych. W tym artykule pokazano, w jaki sposób wykorzystaliśmy i zintegrowaliśmy szereg tych technologii, aby z powodzeniem i stosunkowo łatwo stworzyć podstawową witrynę podobną do YouTube.