Vidéo en ligne avec Wowza et Amazon Elastic Transcoder
Publié: 2022-03-11Le succès et l'adoption de toute application Web aujourd'hui dépendent fortement de ses performances, de sa flexibilité et de sa facilité d'utilisation.
Surtout dans le monde actuel du TDAH, les utilisateurs perdront rapidement patience avec une application si le chargement de sa page prend trop de temps. Pour les applications Web qui doivent prendre en charge le traitement vidéo - qui est intrinsèquement gourmand en ressources de calcul et en E/S - ce défi est particulièrement aigu. Les utilisateurs deviennent néanmoins de plus en plus exigeants, souhaitant que leurs vidéos soient de haute qualité et se chargent rapidement, même si elles fonctionnent sur un smartphone ou une tablette.
Les utilisateurs perdent également en tolérance pour les applications Web qui ne fonctionnent pas sur leur navigateur ou appareil préféré, ou qui ne prennent pas en charge le format de données qu'ils doivent charger ou exporter. La diversité des formats vidéo qui doivent être pris en charge rend donc également l'intégration de la prise en charge vidéo dans une application Web particulièrement difficile.
Cet article décrit comment j'ai efficacement exploité les technologies open source et les services basés sur le cloud pour intégrer des fonctionnalités vidéo dans une application Web basée sur PHP.
Cas d'utilisation
Je faisais partie d'une équipe qui avait besoin de développer un site Web de type YouTube, où les utilisateurs enregistrés pouvaient télécharger et partager leurs vidéos.
Le système devait permettre aux utilisateurs enregistrés de télécharger leurs vidéos dans une variété de formats pris en charge qui seraient ensuite convertis en un format commun (MP4). Nous devions également générer un ensemble de vignettes et un collage d'images à utiliser dans le lecteur vidéo pour afficher les images sur une barre de progression vidéo.
Les choses étaient encore compliquées par le fait que les exigences des clients nous empêchaient d'utiliser les CDN ou les API de transcodage disponibles, nous avons donc dû développer notre solution à partir de zéro.
Téléchargement de vidéo
Étant donné que le processus de téléchargement lui-même n'avait pas besoin d'être spécifique à la vidéo (nous avions juste besoin d'une capacité de téléchargement de fichiers facile à utiliser), il était logique d'utiliser une solution open source existante plutôt que de lancer la nôtre. Nous avons sélectionné jQuery-File-Upload, principalement parce qu'il supportait deux fonctionnalités qui étaient essentielles dans notre cas ; à savoir, une barre de progression de téléchargement et des téléchargements fragmentés.
Le téléchargement fragmenté nous a permis de permettre à un utilisateur de télécharger un fichier vidéo de pratiquement n'importe quelle taille (particulièrement important pour prendre en charge les fichiers vidéo en résolution HD). Avec cette approche, le fichier est divisé en plusieurs "morceaux" sur le front-end qui appellent une action de téléchargement avec chaque morceau de données (ainsi que les métadonnées pour chaque morceau, telles que le numéro de morceau et la taille totale du fichier). Le fichier vidéo complet est ensuite réassemblé sur le back-end. Incidemment, inclure le numéro de bloc dans les métadonnées s'est avéré particulièrement important car certains navigateurs (tels que Mobile Safari) ont tendance à transmettre les blocs dans un ordre aléatoire.
Traitement vidéo en ligne
Le traitement vidéo peut être aussi simple que la capture d'images sous forme d'images fixes, ou peut impliquer des opérations plus complexes telles que l'amélioration de l'image, la stabilisation du flux vidéo, etc. Dans notre cas, les seules exigences de traitement vidéo étaient (a) d'extraire les codecs vidéo et d'autres métadonnées clés et (b) de générer un ensemble de vignettes et un collage d'images (à utiliser dans le lecteur vidéo pour afficher les images sur une progression vidéo bar).
FFmpeg - une bibliothèque open source largement utilisée et librement distribuée - a été extrêmement utile pour répondre à ces exigences. FFmpeg fournit une solution complète et multiplateforme pour enregistrer, convertir et diffuser des fichiers audio et vidéo. Il peut également être utilisé pour convertir des vidéos et effectuer des modifications simples (par exemple, rogner, couper, ajouter un filigrane, etc.).
Pour nos besoins, nous avons pu utiliser FFmpeg pour diviser la vidéo en dix sections, puis capturer une vignette pour chaque section afin de fournir les fonctionnalités nécessaires.
Malheureusement, il n'y a pas de liaisons de langage PHP pour la bibliothèque FFmpeg. Par conséquent, la seule façon d'exploiter FFmpeg à partir de PHP est d'invoquer le binaire à partir de la ligne de commande à l'aide des commandes système. Il existe essentiellement deux façons d'utiliser FFmpeg en PHP :
- libav. Libav est un projet de logiciel libre, dérivé de FFmpeg en 2011, qui produit des bibliothèques et des programmes pour gérer les données multimédias. Sur Ubuntu, par exemple, cela peut être installé avec la commande
sudo apt-get install libav-tools
. Les commandes libav sont compatibles avec FFmpeg et avconv. PHP doit avoir un accès en ligne de commande àffmpeg/avconv
pour l'utiliser par programmation. - PHP-FFMpeg. PHP-FFMPEG est un pilote PHP orienté objet pour le binaire FFMpeg. Il est accessible en exécutant simplement
composer update "php-ffmpeg/php-ffmpeg"
.
Nous avons utilisé PHP-FFMPeg car il offre un accès facile à la fonctionnalité FFmpeg qui nous intéressait. Par exemple, la classe FFProbe
de ce package vous permet de recevoir des informations sur les codecs ou la longueur d'un fichier vidéo particulier comme suit :
$ffprobe = FFMpeg\FFProbe::create(); $ffprobe ->format('/path/to/video/mp4') // extracts file informations ->get('duration');
FFmpeg facilite également l'enregistrement de n'importe quelle image vidéo :
$ffmpeg = FFMpeg\FFMpeg::create(); $video = $ffmpeg->open('video.mpg'); $video ->frame(FFMpeg\Coordinate\TimeCode::fromSeconds(10)) ->save('frame.jpg');
Un exemple de code plus détaillé est disponible ici.
Une mise en garde : en raison de certaines lois sur les brevets, tous les codecs ne peuvent pas être traités par FFmpeg et certains formats ne sont pas correctement (ou entièrement) pris en charge. Je me souviens d'avoir lutté il y a quelques années, par exemple, avec le format .3gp
lorsque la prise en charge des téléphones polyvalents était indispensable.
File d'attente
Après avoir obtenu les codecs d'une vidéo et d'autres métadonnées, nous poussons la vidéo vers une file d'attente de conversion FIFO (premier entré, premier sorti). La file d'attente a été implémentée à l'aide d'un simple script cron qui sélectionne un nombre donné de vidéos non traitées à chaque exécution et les transmet à un utilitaire de conversion (exemple de code source disponible ici).
L'utilitaire de conversion appelle FFMpeg pour effectuer la conversion et marque chaque vidéo comme ayant été traitée.
Nous avons également développé un mécanisme simple d'estimation du temps d'attente, qui calcule le temps moyen pour convertir 1 minute de vidéo. En utilisant cette moyenne, nous sommes en mesure de calculer et d'afficher pour l'utilisateur le temps de traitement restant estimé après la fin du téléchargement d'une vidéo, en fonction du nombre de minutes de vidéo restant à traiter.
Conversion de formats vidéo
Certains formats universellement reconnus (tels que JPEG et GIF) sont apparus pour les images fixes qui sont essentiellement pris en charge par tous les appareils et logiciels de traitement d'image. Bien que certains formats vidéo soient plus courants que d'autres, aucun format pris en charge universellement n'a encore émergé pour les vidéos.
Dans notre cas, en plus de devoir convertir une variété de formats en un seul format commun (MPEG-4), nous avions besoin que les vidéos converties soient optimisées pour la diffusion sur des appareils mobiles.
Pour la conversion de format vidéo (au moins pour nos besoins à court terme), l'utilisation d' Amazon Elastic Transcoder basé sur le cloud était la meilleure option disponible. En plus de sa facilité d'utilisation générale, le service de transcodeur s'occupe de l'optimisation et de tous les paramètres d'encodage. Heureusement, un SDK AWS pour PHP est disponible, ce qui simplifie l'appel du service à partir de notre code PHP.
Remarque : L'utilisation d'un service basé sur le cloud comme Amazon Elastic Transcoder est idéale si vous souhaitez être opérationnel rapidement. Cependant, gardez à l'esprit que cette option peut devenir coûteuse pour votre client, surtout si son modèle commercial est susceptible de nécessiter une utilisation intensive de vidéos volumineuses. Un autre facteur à prendre en compte est que vous ne devez pas nécessairement supposer que les vidéos ou le modèle commercial de votre client seront compatibles avec les Conditions d'utilisation.

Amazon utilise ses éléments de stockage et de calcul de base, S3 (Simple Storage Service) et EC2 (Elastic Compute Cloud) - combinés avec Auto Scaling et SNS (Simple Notification Service) - pour offrir la possibilité d'augmenter et de réduire pratiquement instantanément.
L'installation d' aws-sdk est simple, car Amazon gère une version du package installable par Composer. Ajoutez simplement ”aws/aws-sdk-php": "2.*"
à votre fichier composer.json
et effectuez une mise à composer update
.
Évidemment, l'accès à Amazon Elastic Transcoder nécessite un compte Amazon, vous devrez donc également le configurer si vous (ou votre client) n'en avez pas déjà un.
Notre utilisation du service Amazon Elastic Transcoder impliquait d'abord de télécharger des fichiers vidéo dans un compartiment approprié sur S3. Nous avons ensuite chargé le travail de transcodeur de décoder et de générer une vignette qui, une fois terminée, envoie une requête HTTP à l'adresse spécifiée. Cela nécessite une certaine configuration dans le panneau AWS, mais c'est assez simple et Amazon fournit une bonne documentation sur la façon de procéder.
N'hésitez pas à utiliser notre bundle de transcodeur, qui permet de simplifier l'intégration pour Symfony 2. Il comprend une description d'utilisation et propose un contrôleur pour la mise en œuvre rapide d'un service de notification envoyé par Amazon pour collecter des informations sur la vidéo traitée. Un exemple d'utilisation est disponible ici.
De plus, un exemple de contrôleur qui gère les notifications Amazon est disponible ici, qui implémente également la confirmation d'une adresse d'abonnement. Le service publiera d'abord l'URL à visiter pour confirmer qu'il s'agit d'un récepteur de notification valide. Tout ce qui est alors vraiment nécessaire est de marquer la vidéo comme traitée. Dès lors, nous pouvons utiliser la vidéo transcodée qui est stockée dans le cloud.
Streaming
Le streaming vidéo est une fonctionnalité qui nécessite des performances élevées : les attentes des utilisateurs en matière de streaming ininterrompu sont élevées et la tolérance à la latence est extrêmement faible. Ce défi est souvent exacerbé par la nécessité de diffuser de la vidéo sur plusieurs clients simultanément en temps réel.
Dans notre cas, nous devions aider chaque utilisateur à pouvoir créer sa propre chaîne vidéo et commencer à diffuser. Notre solution comportait trois composants :
- Tableau de bord. Application qui sert de tableau de bord de streamer, offrant la possibilité de diffuser de la vidéo.
- Téléspectateur. Client vidéo qui consomme et affiche un flux vidéo.
- Moteur de diffusion en continu. Service de streaming vidéo basé sur le cloud.
Outre le fait que la technologie de la vidéo à la demande (VOD) est en constante évolution, un autre problème auquel nous avons été confrontés était que l'accès à la caméra n'était pas bien pris en charge et n'offrait qu'une connexion P2P. De plus, notre objectif était de fournir une diffusion en ligne pour plusieurs utilisateurs simultanés. De plus, la prise en charge de l'API getUserMedia/Stream
(anciennement considérée comme l'élément <device>
) n'est pas encore cohérente dans les navigateurs modernes. Sur la base de ces facteurs, j'ai décidé d'utiliser la technologie Flash car c'était vraiment le seul choix raisonnable. Les deux applications (Dashboard et Viewer) ont donc été implémentées à l'aide de Flex et d'ActionScript .
Pour le moteur de streaming, nous avons utilisé Wowza . Bien qu'il existe d'autres solutions non commerciales (telles que Red5, qui est commercialisée essentiellement comme un remplacement instantané de Wowza), dans notre cas, le support produit commercial a été un facteur important. De plus, au moins au moment où nous construisions le système, Wowza offrait une meilleure documentation, ce qui était un avantage supplémentaire. (Notez que vous pouvez obtenir une version d'essai de Wowza gratuitement pendant 30 jours et qu'il existe également une version d'essai du développeur que vous pouvez utiliser jusqu'à 180 jours. Mais il y a certaines limitations ; le streaming ne peut fonctionner que pour deux clients et il y a une limite sur le nombre maximum de connexions.)
Moteur de diffusion Wowza
Nous avons utilisé l'application LiveStream fournie avec Wowza. Pour le configurer, laissez applications/app_name
vide et dans conf/app_name
copiez le fichier Application.xml
du catalogue conf
. Modifiez le fichier pour configurer la section <Streams>
comme suit :
<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>
Le paramètre clé est <StreamType>live</StreamType>
qui définit qu'il s'agira d'un flux provenant d'un flux vidéo en direct (par exemple, une caméra). Notez qu'après avoir modifié et enregistré ce fichier, vous devrez redémarrer Wowza.
Applications Flash (Flex/ActionScript)
Flash fournit un système entièrement intégré pour connecter une caméra et un microphone à un serveur de streaming Wowza. Ceci est particulièrement utile si votre expérience avec ActionScript est limitée.
L'ensemble de l'application repose essentiellement sur l'interaction entre les objets suivants :
- NetConnection. La classe NetConnection crée une connexion bidirectionnelle entre un client et un serveur. Le client peut être une application Flash Player ou AIR. Le serveur peut être un serveur Web, Flash Media Server, un serveur d'applications exécutant Flash Remoting ou le service Adobe Stratus.
- Appareil photo. La classe Camera est utilisée pour capturer la vidéo à partir de la caméra du système client ou de l'appareil.
- Microphone. La classe Microphone est utilisée pour surveiller ou capturer l'audio d'un microphone.
- NetStream. La classe NetStream ouvre un canal de diffusion unidirectionnel sur une NetConnection.
Tout d'abord, nous nous connectons au serveur de streaming Wowza à l'aide de l'instance NetConnection, puis attachons l'écouteur d'événement qui écoutera les changements d'état de la connexion réseau :
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? );
Voici un exemple minimaliste d'écouteur d'événement qui connecte la caméra et le microphone au serveur de diffusion :
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; }
Le code client est très similaire, sauf que nous affichons simplement l'entrée vidéo du côté utilisateur. Cela se fait en connectant le flux à l'objet Video
, comme illustré dans cet exemple simple :
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 }
Emballer
On peut s'attendre à ce que la diffusion en direct et la vidéo jouent un rôle de plus en plus important dans les applications mobiles et Web. Il est donc important que les développeurs Web se familiarisent avec le transcodage, le traitement et le streaming vidéo. De nombreux outils, bibliothèques et services existent aujourd'hui pour intégrer ces fonctionnalités dans les applications Web. Cet article montre comment nous avons exploité et intégré un certain nombre de ces technologies pour créer avec succès un site de base de type YouTube avec une relative facilité.