PHP et la vidéo avec ffmpeg-php
FFMPEG php, à l’instar de FFMPEG, est le genre d’outil qu’on ne se lasse jamais de présenter. FFMPEG PHP offre des classes permettant de “discuter” en php avec FFMPEG. On peut donc récupérer toutes sortes d’info sur des vidéos, en extraire des images etc. En revanche, il n’est pas possible d’encoder directement d’un format à un autre avec FFMPEG PHP. Pour cela, il faudra passer par FFMPEG tout court.
Je ne donnerai ici qu’un aperçu de quelques commandes, pour le reste, il y a la doc officielle.
Prérequis
FFMPEG PHP, n’est pas installé par défaut avec php. En outre, certaines fonctions de FFMPEG php nécessitent la librairie GD de php. Celle-ci est normalement installé avec PHP dans les versions récentes de ce dernier.
# Install de ffmpeg php pour les distributions à base de debian
sudo apt-get php5-ffmpeg
Récupérer des informations sur les vidéos
C’est la classe ffmpeg_movie
qui va nous permettre de récupérer les informations sur la vidéo. Cette classe prend de très nombreuses méthodes (cf la doc.), parmi lesquelles :
getDuration()
- Renvoie la durée en secondes.
getFrameCount()
- Renvoie le nombre total d'images dans la vidéo.
getFrameWidth()
- Renvoie la largeur de l'image en pixels.
getFrameHeight()
- Renvoie la hauteur de l'image en pixels (donc
getFrameWidth*getFrameHeight
vous fournit la résolution de votre vidéo). getFrameRate()
- Renvoie le nombre d'images/sec.
getBitRate()
- Renvoie le bitrate en bits/sec (attention à bien interpréter, on a l'habitude d'utiliser les Kbits voir les Mbits).
getAudioBitRate()
- Même fonctionnement que
getAudioBitRate()
mais pour l'audio. getVideoCodec()
- Renvoie le nom du codec qui a été utilisé pour encoder la video.
getAudioCodec()
- Même fonctionnement que
getAudioCodec()
mais pour l'audio.. getFrame()
- Renvoie l'image correspondante au paramètre passé, comme si on avait invoqué la classe
ffmpeg_frame
. Retourne false si aucune image ne correspond au paramètre.
Par exemple, si nous avons une vidéo “video.avi”, dans le répertoire vidéo de notre racine web. Nous pouvons récupérer la durée de la vidéo (en secondes je le rappelle ;) ), et le nombre total d’images de la vidéo, comme ceci :
$videoInfo = new ffmpeg_movie('videos/video.avi');
$videoLenth = $videoInfo->getDuration();
$videoFrames = $videoInfo->getFrameCount();
Les bariables $videoLenth
et $videoFrames
contiennent donc chacune un nombre entier correspondant respectivement à la durée et aux nombre d’images !
Extraire des images et les modifier
C’est déjà plus puissant !! Les fonctions de création et modification des images sont relatives à la classe ffmpeg_frame
. Cependant, comme vous l’avez peut-être lu juste au-dessus (comment ça non ? :evil: ), il est possible d’utiliser toutes ces méthodes directement avec la classe ffmpeg_movie, en appelant d’abord la méthode getFrame(). Il y a beaucoup moins de méthodes ici, passons en revue les plus intéressantes :
getWidth()
- Renvoie la largeur de l'image.
getHeight()
- Renvoie la hauteur de l'image.
resize(entier Hauteur, entier Largeur)
- Redimensionne l'image.
crop(entier)
- Coupe les x pixels du haut de l'image par défaut. Il faut sinon préciser cropbottom pour le bas, cropleft pour la gauche, ou cropright pour la droite.
toDGImage()
- Retourne une image affichable grâce à la librairie GD.
Note : certaines versions de ffmpeg-php ne supporte pas le redimmensionnement. Vous le saurez si vous avez une erreur du type Call to undefined method ffmpeg_frame::resize()
. Dans ce cas, laissez tomber, enregistrez les images en plein taille et redimensionnez les par la suite avec GD.
$videoInfo = new ffmpeg_movie('../../src/vids/toencode/mp4/'.$name.'.mp4');
$videoFrames = $videoInfo->getFrameCount();
$largeur = $videoImage->getWidth();
$hauteur = $videoImage->getHeight();
// ici je divise le nombre d'images de la video par 2,
// ainsi je prendrai ma miniature en plein milieu de la video
$videoImage = $videoInfo->getFrame($videoFrames/2);
// je veux des miniatures de 300px de large je calcule donc le % de réduction pour avoir
// une largeur de 300px et une hauteur proportionnelle
$pourcentageReduction = (300/$largeur)*100;
// je calcule donc mes nouvelles valeur en appliquant la focntion
// ceil qui arrondit à l'entier supérieur (on ne peut pas avoir des moitiés de pixels !)
$newLargeur = ceil($largeur*($pourcentageReduction/100));
$newHauteur = ceil($hauteur*($pourcentageReduction/100));
$miniature = $videoImage->resize($newHauteur, $newLargeur);
$img = $miniature->toGDImage();
imagejpeg($img, 'mon_dossier/ma_miniature.jpeg');
Voilà, nous avons a peu près fait le tour.
PS : ffmpeg-php, bien que tout a fait fonctionnel, n’est plus maintenu [en]. Il y a une nouvelle bibliothèque PHP qui permet de manipuler les vidéos (elle permet même de lancer les encodages depuis php). Cette bibliothèque s’appelle php ffmpeg et est maintenu par SensioLabs (l’équipe qui est derrière Symfony).
Commentaires
qwerty dit –
Concrètement, ca peut servir a quoi par exemple ? aux portails vidéos ?
Buzut dit –
N'importe quel site qui va travailler avec de la vidéo et à besoins d'info à leur sujet ou de générer des vignettes. Par exemple Vimeo utile ffmpeg-php pour la génération des miniatures ;)
bastien dit –
par exemple, ça me sert en ce moment pour faire un CMS de TubeLike :)
Buzut dit –
Tu passeras le lien à l'occasion !
bastien dit –
ouaip, mais c'est pas prêt d’être fini, je commence à peine en fait :)
david dit –
Bonjour quelqu'un sait il comment sa fonctionne avec le nouveau logiciel qui remplace FFMPEG (depuis ubuntu14.04) >> avconv. Pour l’exécuté en PHP.
Merci
Buzut dit –
Salut !
Tu as la doc d'ubuntu qui est bien faite http://doc.ubuntu-fr.org/avconv
En ce qui me concerne, je continue à utiliser ffmpeg. Tu peux toujours l'installer sur Ubuntu et toutes les distributions Linux. Jette un œil a mon tuto a ce sujet http://buzut.fr/installer-ffmpeg-et-encoder-pour-html5/
david dit –
Bonjour, oui je l'ai déjà vu cela fonctionne sur le terminal, mais pas dans un script php.
Merci.
Buzut dit –
Bien sur que ça fonctionne dans un script !
Il faut rendre le binaire exécutable en faisant chmod +x nom-du-binaire puis en php il faut renseigner le chemin absolu vers le binaire par ex /var/www/ffmpeg donc dans ton script exec('/var/www/ffmpeg -i test.avi -vcodec libx264 -ab 192k encoded.mp4'); et le tour est joué ;)
david dit –
j'utilise pas ffmpeg mais avconv car je suis sur Ubuntu14.04, mais je vais testé voir sur une 12.04 avec ffmpeg si le problème est identique.
Visiblement il y aurait un problème de droit "Permission denied".
Mais pourtant, j'ai fais qui faut. J'ai même recréer le fichier par code php avec les droits maximum. mkdir('avconv'); chown("avconv", "www-data"); chmod("avconv", 0777);
Merci!
david dit –
Je viens d'essayer avec une 12.04 et ffmpeg et cela fais aussi « Permission denied ». Malgré que cela fonctionne sur le terminale.
Merci!
david dit –
Alors je suis repasser sur avconv puisque cela n'a pas changer avec ffmpeg et visiblement il le conseille "Please use avconv instead.".
Visiblement j'avais un problème de syntaxe!
$output = shell_exec('avconv -i /var/www/avi/1.mp4 test.webm 2>&1');
Merci!
Buzut dit –
Tant mieux que tu aies réussi. Ubuntu supporte officiellement avconv, qui est un fork de ffmpeg, mais ce dernier fonctionne tout aussi bien ;)
Buzut dit –
Tu tentes de lancer ffmpeg depuis php en cli ou depuis un serveur web ?
david dit –
Depuis le serveur!
J'ai mon script dans un fichier php, mais j'y accède par le serveur avec le navigateur http://127.0.0.1
Merci!
Buzut dit –
Attention quand même si l'encodage prend un peu de temps au max execution time qui est à 30s par défaut, ainsi qu'au memory limit.
Pour travailler la vidéo en php avec ffmpeg ou avcon, tu as aussi la très bonne bibliothèque https://github.com/PHP-FFMpeg/PHP-FFMpeg
david dit –
Oui justement, du coup je vais simplement me contenter de récupérer une capture pour l’aperçue des vidéo.
Merci!
Rejoignez la discussion !