Online-Video mit Wowza und Amazon Elastic Transcoder

Veröffentlicht: 2022-03-11

Der Erfolg und die Akzeptanz einer jeden Web-App hängt heute stark von ihrer Leistung, Flexibilität und Benutzerfreundlichkeit ab.

Gerade in der heutigen ADHS-Welt verlieren Nutzer schnell die Geduld mit einer App, wenn das Laden der Seite zu lange dauert. Für Webanwendungen, die die Videoverarbeitung unterstützen müssen – was von Natur aus rechen- und I/O-intensiv ist – ist diese Herausforderung besonders akut. Die Benutzer werden dennoch immer anspruchsvoller und möchten, dass ihre Videos von hoher Qualität sind und schnell geladen werden, selbst wenn sie auf einem Smartphone oder Tablet laufen.

Benutzer verlieren auch die Toleranz für Web-Apps, die nicht auf ihrem bevorzugten Browser oder Gerät funktionieren oder die das Datenformat, das sie laden oder exportieren müssen, nicht unterstützen. Die Vielfalt der zu unterstützenden Videoformate macht es daher auch zu einer besonderen Herausforderung, die Videounterstützung in eine Web-App einzubinden.

Dieser Beitrag beschreibt, wie ich Open-Source-Technologien und Cloud-basierte Dienste effektiv genutzt habe, um Videofunktionen in eine PHP-basierte Web-App zu integrieren.

Online-Videoverarbeitung in PHP mit Wowza und Amazon Elastic Transcoder

Anwendungsfall

Ich war Teil eines Teams, das eine YouTube-ähnliche Website entwickeln musste, auf der registrierte Benutzer ihre Videos hochladen und teilen konnten.

Das System musste es registrierten Benutzern ermöglichen, ihre Videos in einer Vielzahl von unterstützten Formaten hochzuladen, die dann in ein gemeinsames Format (MP4) konvertiert würden. Wir mussten auch eine Reihe von Miniaturansichten und eine Bildcollage generieren, die im Videoplayer zum Anzeigen der Frames auf einem Videofortschrittsbalken verwendet werden.

Die Dinge wurden noch komplizierter durch die Tatsache, dass Kundenanforderungen uns daran hinderten, verfügbare CDN- oder Transcodierungs-APIs zu verwenden, sodass wir unsere Lösung von Grund auf neu entwickeln mussten.

Video-Upload

Da der Upload-Prozess selbst nicht videospezifisch sein musste (wir brauchten lediglich eine benutzerfreundliche Funktion zum Hochladen von Dateien), war es sinnvoll, eine vorhandene Open-Source-Lösung zu verwenden, anstatt eine eigene zu entwickeln. Wir haben jQuery-File-Upload ausgewählt, hauptsächlich weil es zwei Funktionen unterstützt, die in unserem Fall wesentlich waren; nämlich ein Upload-Fortschrittsbalken und aufgeteilte Uploads.

Das Chunked-Upload ermöglichte es uns, einem Benutzer das Hochladen einer Videodatei praktisch jeder Größe zu ermöglichen (besonders wichtig, um Videodateien in HD-Auflösung zu unterstützen). Bei diesem Ansatz wird die Datei am Front-End in mehrere „Blöcke“ unterteilt, die eine Upload-Aktion mit jedem Datenblock aufruft (zusammen mit den Metadaten für jeden Block, wie z. B. Blocknummer und Gesamtdateigröße). Die komplette Videodatei wird dann im Backend wieder zusammengesetzt. Die Aufnahme der Chunk-Nummer in die Metadaten erwies sich übrigens als besonders wichtig, da einige Browser (zB Mobile Safari) dazu neigen, die Chunks in zufälliger Reihenfolge zu übertragen.

Online-Videobearbeitung

Die Videoverarbeitung kann so einfach sein wie das Erfassen von Frames als Standbilder oder komplexere Vorgänge wie Bildverbesserung, Stabilisieren des Videostreams usw. umfassen. In unserem Fall bestanden die einzigen Anforderungen an die Videoverarbeitung darin, (a) Videocodecs und andere wichtige Metadaten zu extrahieren und (b) eine Reihe von Miniaturansichten und eine Bildcollage zu generieren (die im Videoplayer verwendet werden soll, um die Frames in einem Videofortschritt anzuzeigen Bar).

FFmpeg – eine weit verbreitete, frei verfügbare Open-Source-Bibliothek – war äußerst hilfreich, um diese Anforderungen zu erfüllen. FFmpeg bietet eine vollständige, plattformübergreifende Lösung zum Aufzeichnen, Konvertieren und Streamen von Audio- und Videodateien. Es kann auch verwendet werden, um Videos zu konvertieren und einfache Bearbeitungen durchzuführen (z. B. Trimmen, Schneiden, Hinzufügen eines Wasserzeichens usw.).

Für unsere Zwecke konnten wir FFmpeg verwenden, um das Video in zehn Abschnitte aufzuteilen und dann ein Miniaturbild für jeden Abschnitt aufzunehmen, um die erforderliche Funktionalität bereitzustellen.

Leider gibt es für die FFmpeg-Bibliothek keine PHP-Sprachbindungen. Daher besteht die einzige Möglichkeit, FFmpeg von PHP aus zu nutzen, darin, die Binärdatei über die Befehlszeile mit Systembefehlen aufzurufen. Grundsätzlich gibt es zwei Möglichkeiten, FFmpeg in PHP zu verwenden:

  • libav. Libav ist ein freies Softwareprojekt, das 2011 von FFmpeg abgezweigt wurde und Bibliotheken und Programme für den Umgang mit Multimediadaten erstellt. Unter Ubuntu lässt sich dies beispielsweise mit dem Befehl sudo apt-get install libav-tools . libav-Befehle sind mit FFmpeg und avconv kompatibel. PHP muss Befehlszeilenzugriff auf ffmpeg/avconv , um dies programmgesteuert zu verwenden.
  • PHP-FFMpeg. PHP-FFMpeg ist ein objektorientierter PHP-Treiber für die FFMpeg-Binärdatei. Sie können darauf zugreifen, indem Sie einfach das composer update "php-ffmpeg/php-ffmpeg" ausführen.

Wir haben PHP-FFMpeg verwendet, da es einen einfachen Zugriff auf die FFmpeg-Funktionalität bietet, an der wir interessiert waren. Mit der FFProbe -Klasse aus diesem Paket können Sie beispielsweise wie folgt Informationen über Codecs oder die Länge einer bestimmten Videodatei erhalten:

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

FFmpeg macht es auch einfach, jeden Videoframe zu speichern:

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

Ausführlicherer Beispielcode ist hier verfügbar.

Ein Hinweis zur Vorsicht: Aufgrund einiger Patentgesetze können nicht alle Codecs von FFmpeg verarbeitet werden und einige Formate werden nicht richtig (oder vollständig) unterstützt. Ich erinnere mich, dass ich vor ein paar Jahren zum Beispiel mit dem .3gp -Format zu kämpfen hatte, als die Unterstützung von Feature-Phones ein Muss war.

Warteschlange

Nachdem wir die Codecs und andere Metadaten eines Videos erhalten haben, schieben wir das Video in eine FIFO-Konvertierungswarteschlange (first in first out). Die Warteschlange wurde mithilfe eines einfachen Cron-Skripts implementiert, das bei jeder Ausführung eine bestimmte Anzahl unverarbeiteter Videos auswählt und an ein Konvertierungsdienstprogramm weiterleitet (Beispiel-Quellcode hier verfügbar).

Das Konvertierungsprogramm ruft FFMpeg auf, um die Konvertierung durchzuführen, und markiert jedes Video als verarbeitet.

Wir haben auch einen einfachen Mechanismus zur Schätzung der Wartezeit entwickelt, der die durchschnittliche Zeit zum Konvertieren von 1 Minute Video berechnet. Anhand dieses Durchschnittswerts können wir die geschätzte verbleibende Verarbeitungszeit nach dem Hochladen eines Videos berechnen und dem Benutzer anzeigen, basierend darauf, wie viele Minuten des Videos noch verarbeitet werden müssen.

Konvertierung von Videoformaten

Für Standbilder haben sich bestimmte allgemein anerkannte Formate (zB JPEG und GIF) herausgebildet, die grundsätzlich von allen Geräten und Bildbearbeitungsprogrammen unterstützt werden. Während einige Videoformate weiter verbreitet sind als andere, hat sich für Videos noch kein solches universell unterstütztes Format herausgebildet.

In unserem Fall mussten die konvertierten Videos nicht nur von einer Vielzahl von Formaten in ein einziges gemeinsames Format (MPEG-4) konvertiert werden, sondern auch für das Streaming auf Mobilgeräte optimiert werden.

Für die Videoformatkonvertierung (zumindest für unseren kurzfristigen Bedarf) war die Verwendung des Cloud-basierten Amazon Elastic Transcoder die beste verfügbare Option. Neben der allgemeinen Benutzerfreundlichkeit kümmert sich der Transcoder-Dienst um die Optimierung und alle Kodierungseinstellungen. Glücklicherweise ist ein AWS SDK für PHP verfügbar, das den Aufruf des Dienstes aus unserem PHP-Code vereinfacht.

Hinweis: Die Verwendung eines Cloud-basierten Dienstes wie Amazon Elastic Transcoder ist großartig, wenn Sie schnell loslegen möchten. Beachten Sie jedoch, dass diese Option für Ihren Kunden teuer werden kann, insbesondere wenn sein Geschäftsmodell wahrscheinlich eine umfangreiche Nutzung großer Videos erfordert. Ein weiterer zu berücksichtigender Faktor ist, dass Sie nicht unbedingt davon ausgehen sollten, dass die Videos oder das Geschäftsmodell Ihres Kunden mit den Nutzungsbedingungen kompatibel sind.

Amazon verwendet seine grundlegenden Speicher- und Rechenelemente S3 (Simple Storage Service) und EC2 (Elastic Compute Cloud) – kombiniert mit Auto Scaling und SNS (Simple Notification Service) – um die Möglichkeit zu bieten, praktisch sofort nach oben und unten zu skalieren.

Die Installation von aws-sdk ist einfach, da Amazon eine Composer-installierbare Version des Pakets verwaltet. Fügen Sie einfach ”aws/aws-sdk-php": "2.*" zu Ihrer composer.json -Datei hinzu und führen Sie ein composer update durch .

Offensichtlich ist für den Zugriff auf den Amazon Elastic Transcoder ein Amazon-Konto erforderlich, also müssen Sie dieses auch einrichten, wenn Sie (oder Ihr Kunde) noch keines haben.

Unsere Nutzung des Amazon Elastic Transcoder-Dienstes beinhaltete zunächst das Hochladen von Videodateien in einen geeigneten Bucket auf S3. Wir haben dann den Transcoder-Job für die Dekodierung und Generierung eines Thumbnails verantwortlich gemacht, der nach Abschluss eine HTTP-Anforderung an die angegebene Adresse sendet. Dies erfordert eine gewisse Konfiguration im AWS-Panel, ist aber recht einfach und Amazon bietet eine gute Dokumentation dazu, wie das geht.

Nutzen Sie gerne unser Transcoder-Bundle, das die Integration für Symfony 2 vereinfacht. Es enthält eine Nutzungsbeschreibung und bietet einen Controller für die schnelle Implementierung eines von Amazon gesendeten Benachrichtigungsdienstes, um Informationen über das verarbeitete Video zu sammeln. Ein Anwendungsbeispiel finden Sie hier.

Außerdem ist hier ein Beispiel-Controller verfügbar, der Amazon-Benachrichtigungen behandelt, der auch die Bestätigung einer Abonnementadresse implementiert. Der Dienst veröffentlicht zuerst die zu besuchende URL, um zu bestätigen, dass dies ein gültiger Benachrichtigungsempfänger ist. Alles, was dann wirklich erforderlich ist, ist das Video als verarbeitet zu markieren. Von da an können wir das transcodierte Video verwenden, das in der Cloud gespeichert ist.

Streamen

Video-Streaming ist eine Fähigkeit, die eine hohe Leistung erfordert: Die Benutzererwartungen an ununterbrochenes Streaming sind hoch und die Latenztoleranz extrem gering. Diese Herausforderung wird oft durch die Notwendigkeit verschärft, Videos gleichzeitig in Echtzeit an mehrere Clients zu streamen.

In unserem Fall mussten wir jeden Benutzer dabei unterstützen, seinen eigenen Videokanal zu erstellen und mit der Übertragung zu beginnen. Unsere Lösung bestand aus drei Komponenten:

  • Armaturenbrett. Anwendung, die als Dashboard eines Streamers dient und die Möglichkeit bietet, Videos bereitzustellen.
  • Zuschauer. Videoclient, der einen Videostream verarbeitet und anzeigt.
  • Streaming-Engine. Cloudbasierter Video-Streaming-Dienst.

Neben der Tatsache, dass sich die Video-on-Demand-Technologie (VOD) immer noch weiterentwickelt, war ein weiteres Problem, mit dem wir konfrontiert waren, dass der Kamerazugriff nicht gut unterstützt wurde und nur eine P2P-Verbindung anbot. Außerdem war es unser Ziel, Online-Übertragungen für mehrere gleichzeitige Benutzer bereitzustellen. Darüber hinaus ist die Unterstützung für die getUserMedia/Stream API (früher als das <device> -Element gedacht) noch nicht in modernen Browsern konsistent. Aufgrund dieser Faktoren habe ich mich für die Verwendung der Flash-Technologie entschieden, da dies wirklich die einzig vernünftige Wahl war. Beide Anwendungen (Dashboard und Viewer) wurden daher mit Flex und ActionScript implementiert.

Für die Streaming-Engine haben wir Wowza verwendet. Obwohl es andere, nicht kommerzielle Lösungen gibt (wie Red5, das im Wesentlichen als Drop-in-Ersatz für Wowza vermarktet wird), war in unserem Fall der kommerzielle Produktsupport ein wichtiger Faktor. Außerdem bot Wowza zumindest zu der Zeit, als wir das System bauten, eine bessere Dokumentation, was ein zusätzlicher Vorteil war. (Beachten Sie, dass Sie eine kostenlose Testversion von Wowza für 30 Tage erhalten können und dass es auch eine Entwickler-Testversion gibt, die Sie bis zu 180 Tage lang verwenden können. Es gibt jedoch einige Einschränkungen; Streaming kann nur für zwei Clients funktionieren und es gibt eine Begrenzung auf die maximale Anzahl von Verbindungen.)

Wowza-Streaming-Engine

Wir haben die mit Wowza bereitgestellte LiveStream-Anwendung verwendet. Um es zu konfigurieren, lassen Sie applications/app_name leer und kopieren Sie in conf/app_name die Datei Application.xml aus dem conf Katalog. Bearbeiten Sie die Datei, um den Abschnitt <Streams> wie folgt zu konfigurieren:

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

Der Schlüsselparameter ist <StreamType>live</StreamType> , der definiert, dass dies ein Stream von einem Live-Video-Feed (z. B. einer Kamera) sein wird. Beachten Sie, dass Sie nach dem Bearbeiten und Speichern dieser Datei Wowza neu starten müssen.

Flash-Anwendungen (Flex/ActionScript).

Flash bietet ein vollständig integriertes System, um eine Kamera und ein Mikrofon mit einem Wowza-Streaming-Server zu verbinden. Dies ist besonders hilfreich, wenn Sie nur über begrenzte Erfahrung mit ActionScript verfügen.

Die gesamte Anwendung basiert im Wesentlichen auf der Interaktion zwischen den folgenden Objekten:

  • NetConnection. Die NetConnection-Klasse erstellt eine bidirektionale Verbindung zwischen einem Client und einem Server. Der Client kann eine Flash Player- oder AIR-Anwendung sein. Der Server kann ein Webserver, Flash Media Server, ein Anwendungsserver mit Flash Remoting oder der Adobe Stratus-Dienst sein.
  • Kamera. Die Camera-Klasse wird verwendet, um Videos von der Clientsystem- oder Gerätekamera aufzunehmen.
  • Mikrofon. Die Microphone-Klasse wird zum Überwachen oder Erfassen von Audio von einem Mikrofon verwendet.
  • NetStream. Die NetStream-Klasse öffnet einen unidirektionalen Streaming-Kanal über eine NetConnection.

Zuerst stellen wir mithilfe der NetConnection-Instanz eine Verbindung zum Wowza-Streaming-Server her und hängen dann den Ereignis-Listener an, der auf Änderungen des Netzwerkverbindungsstatus lauscht:

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

Hier ist ein minimalistisches Beispiel für einen Ereignis-Listener, der die Kamera und das Mikrofon mit dem Streaming-Server verbindet:

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

Der Client-Code ist sehr ähnlich, außer dass wir nur die Videoeingabe auf der Benutzerseite anzeigen. Dazu verbinden Sie den Stream mit dem Video Objekt, wie in diesem einfachen Beispiel gezeigt:

 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 }

Einpacken

Es ist zu erwarten, dass Live-Streaming und Video eine immer wichtigere Rolle in Mobil- und Webanwendungen spielen werden. Daher ist es für Webentwickler wichtig, sich mit Video-Transkodierung, -Verarbeitung und -Streaming vertraut zu machen. Heutzutage gibt es zahlreiche Tools, Bibliotheken und Dienste, um diese Fähigkeiten in Webanwendungen zu integrieren. Dieser Artikel zeigt, wie wir eine Reihe dieser Technologien genutzt und integriert haben, um erfolgreich und relativ einfach eine einfache YouTube-ähnliche Website zu erstellen.