Ce package fournit une intégration avec FFmpeg pour Laravel 10. Le système de fichiers de Laravel gère le stockage des fichiers.
Nous sommes fiers de soutenir la communauté en développant des packages Laravel et en les distribuant gratuitement. Si ce package vous fait gagner du temps ou si vous comptez dessus professionnellement, pensez à sponsoriser la maintenance et le développement et consultez notre dernier package premium : Inertia Table. Garder une trace des problèmes et des demandes de tirage prend du temps, mais nous sommes heureux de vous aider !
Wrapper super simple autour de PHP-FFMpeg, incluant la prise en charge des filtres et d'autres fonctionnalités avancées.
Intégration avec le système de fichiers de Laravel, le système de configuration et la gestion de la journalisation.
Compatible avec Laravel 10, prise en charge de Package Discovery.
Prise en charge intégrée de HLS.
Prise en charge intégrée du HLS chiffré (AES-128) et des clés rotatives (en option).
Prise en charge intégrée de la concaténation, des entrées/sorties multiples, des séquences d'images (timelapse), des filtres complexes (et du mappage), des exportations d'images/vignettes.
Prise en charge intégrée des filigranes (positionnement et manipulation).
Prise en charge intégrée pour la création d'une mosaïque/sprite/tuile à partir d'une vidéo.
Prise en charge intégrée de la génération de fichiers VTT Preview Thumbnail .
Nécessite PHP 8.1 ou supérieur.
Testé avec FFmpeg 4.4 et 5.0.
Vérifiez que la dernière version de FFmpeg est installée :
ffmpeg -version
Vous pouvez installer le package via composer :
le compositeur nécessite pbmedia/laravel-ffmpeg
Ajoutez le fournisseur de services et la façade à votre fichier de configuration app.php
si vous n'utilisez pas Package Discovery.
// config/app.php'providers' => [ ...ProtoneMediaLaravelFFMpegSupportServiceProvider::class, ... ];'alias' => [ ...'FFMpeg' => ProtoneMediaLaravelFFMpegSupportFFMpeg::class ... ];
Publiez le fichier de configuration à l'aide de l'outil CLI artisanal :
Vendeur artisanal php :publish --provider="ProtoneMediaLaravelFFMpegSupportServiceProvider"
La clé de configuration set_command_and_error_output_on_exception
est désormais par défaut true
, ce qui rend les exceptions plus informatives. Pour en savoir plus, consultez la section Gestion des exceptions.
La clé de configuration enable_logging
a été remplacée par log_channel
pour choisir le canal de journalisation utilisé lors de l'écriture des messages dans les journaux. Si vous souhaitez toujours désactiver complètement la journalisation, vous pouvez définir la nouvelle clé de configuration sur false
.
La longueur du segment et l'intervalle d'images clés des exportations HLS doivent être 2
ou plus ; less n’est plus pris en charge.
Comme Laravel 9 a migré de Flysystem 1.x vers 3.x, cette version n'est pas compatible avec Laravel 8 ou version antérieure.
Si vous utilisez la fonction de manipulation du filigrane, assurez-vous de mettre à niveau spatie/image
vers la v2.
L'espace de noms a été modifié en ProtoneMediaLaravelFFMpeg
, la façade a été renommée en ProtoneMediaLaravelFFMpegSupportFFMpeg
et le fournisseur de services a été renommé en ProtoneMediaLaravelFFMpegSupportServiceProvider
.
Les exportations chaînées sont toujours prises en charge, mais vous devez réappliquer des filtres pour chaque exportation.
Les listes de lecture HLS incluent désormais des données de débit, de fréquence d'images et de résolution. Les segments utilisent également un nouveau modèle de dénomination (en savoir plus). Veuillez vérifier que vos exportations fonctionnent toujours dans votre lecteur.
L'exportation HLS est désormais exécutée en une seule tâche au lieu d'exporter chaque format/flux séparément. Cela utilise les fonctionnalités map
et filter_complex
de FFMpeg. Il peut suffire de remplacer tous les appels à addFilter
par addLegacyFilter
, mais certains filtres doivent être migrés manuellement. Veuillez lire la documentation sur HLS pour en savoir plus sur l'ajout de filtres.
Convertir un fichier audio ou vidéo :
FFMpeg::fromDisk('chansons') ->ouvrir('hier.mp3') ->exporter() ->toDisk('converted_songs') ->inFormat (nouveau FFMpegFormatAudioAac) ->save('hier.aac');
Au lieu de la méthode fromDisk()
vous pouvez également utiliser la méthode fromFilesystem()
, où $filesystem
est une instance de IlluminateContractsFilesystemFilesystem
.
$media = FFMpeg::fromFilesystem($filesystem)->open('hier.mp3');
Vous pouvez surveiller la progression du transcodage. Utilisez la méthode onProgress
pour fournir un rappel, qui vous donne le pourcentage terminé. Dans les versions précédentes de ce package, vous deviez transmettre le rappel à l'objet format.
FFMpeg::open('steve_howe.mp4') ->exporter() ->onProgress(function ($percentage) {echo "{$percentage}% transcodé" ; });
Le rappel peut également exposer $remaining
(en secondes) et $rate
:
FFMpeg::open('steve_howe.mp4') ->exporter() ->onProgress(function ($percentage, $remaining, $rate) {echo "{$remaining} secondes restantes au taux : {$rate}" ; });
Vous pouvez ouvrir les fichiers téléchargés directement à partir de l'instance Request
. Il est probablement préférable d'enregistrer d'abord le fichier téléchargé au cas où la requête serait abandonnée, mais si vous le souhaitez, vous pouvez ouvrir une instance UploadedFile
:
classe UploadVideoController {fonction publique __invoke(Request $request) { FFMpeg::open($request->file('video')); } }
Vous pouvez ouvrir des fichiers à partir du Web à l'aide de la méthode openUrl
. Vous pouvez spécifier des en-têtes HTTP personnalisés avec le deuxième paramètre facultatif :
FFMpeg::openUrl('https://videocoursebuilder.com/lesson-1.mp4'); FFMpeg::openUrl('https://videocoursebuilder.com/lesson-2.mp4', ['Autorisation' => 'Basic YWRtaW46MTIzNA==', ]);
Lorsque l'encodage échoue, une ProtoneMediaLaravelFFMpegExportersEncodingException
doit être levée, ce qui étend la classe FFMpegExceptionRuntimeException
sous-jacente. Ce cours propose deux méthodes qui peuvent vous aider à identifier le problème. En utilisant la méthode getCommand
, vous pouvez obtenir la commande exécutée avec tous les paramètres. La méthode getErrorOutput
vous donne un journal de sortie complet.
Dans les versions précédentes de ce package, le message d'exception était toujours Encoding failed . Vous pouvez revenir à ce message en mettant à jour la clé de configuration set_command_and_error_output_on_exception
sur false
.
essayer { FFMpeg::open('hier.mp3') ->exporter() ->inFormat (nouveau Aac) ->save('hier.aac'); } catch (EncodingException $exception) {$command = $exception->getCommand();$errorLog = $exception->getErrorOutput(); }
Vous pouvez ajouter des filtres via une Closure
ou en utilisant les objets Filter de PHP-FFMpeg :
utilisez FFMpegFiltersVideoVideoFilters ; FFMpeg::fromDisk('vidéos') ->ouvrir('steve_howe.mp4') ->addFilter(function (VideoFilters $filters) {$filters->resize(new FFMpegCoordonnéeDimension(640, 480)); }) ->exporter() ->toDisk('converted_videos') ->inFormat (nouveau FFMpegFormatVideoX264) ->save('small_steve.mkv');// ou$start = FFMpegCoordonnéeTimeCode::fromSeconds(5)$clipFilter = new FFMpegFiltersVideoClipFilter($start); FFMpeg::fromDisk('vidéos') ->ouvrir('steve_howe.mp4') -> ajouter un filtre ($ clipFilter) ->exporter() ->toDisk('converted_videos') ->inFormat (nouveau FFMpegFormatVideoX264) ->save('short_steve.mkv');
Vous pouvez également appeler la méthode addFilter
après la méthode export
:
utilisez FFMpegFiltersVideoVideoFilters ; FFMpeg::fromDisk('vidéos') ->ouvrir('steve_howe.mp4') ->exporter() ->toDisk('converted_videos') ->inFormat (nouveau FFMpegFormatVideoX264) ->addFilter(function (VideoFilters $filters) {$filters->resize(new FFMpegCoordonnéeDimension(640, 480)); }) ->save('small_steve.mkv');
Le redimensionnement étant une opération courante, nous avons ajouté une méthode dédiée :
FFMpeg::open('steve_howe.mp4') ->exporter() ->inFormat (nouveau FFMpegFormatVideoX264) ->redimensionner(640, 480) ->save('steve_howe_resized.mp4');
Le premier argument est la largeur et le deuxième la hauteur. Le troisième argument facultatif est le mode. Vous pouvez choisir entre fit
(par défaut), inset
, width
ou height
. Le quatrième argument facultatif est un booléen indiquant s'il faut ou non forcer l'utilisation de ratios standards. Vous pouvez découvrir ces modes dans la classe FFMpegFiltersVideoResizeFilter
.
Parfois, vous ne souhaitez pas utiliser les filtres intégrés. Vous pouvez appliquer votre propre filtre en fournissant un ensemble d'options. Il peut s'agir d'un tableau ou de plusieurs chaînes comme arguments :
FFMpeg::fromDisk('vidéos') ->ouvrir('steve_howe.mp4') ->addFilter(['-itsoffset', 1]);// ouFFMpeg::fromDisk('videos') ->ouvrir('steve_howe.mp4') ->addFilter('-itsoffset', 1);
Vous pouvez facilement ajouter un filigrane à l'aide de la méthode addWatermark
. Avec WatermarkFactory
, vous pouvez ouvrir votre fichier de filigrane à partir d'un disque spécifique, tout comme vous ouvrez un fichier audio ou vidéo. Lorsque vous supprimez la méthode fromDisk
, elle utilise le disque par défaut spécifié dans le fichier de configuration filesystems.php
.
Après avoir ouvert votre fichier de filigrane, vous pouvez le positionner avec les méthodes top
, right
, bottom
et left
. Le premier paramètre de ces méthodes est le décalage, qui est facultatif et peut être négatif.
utilisez ProtoneMediaLaravelFFMpegFiltersWatermarkFactory ; FFMpeg::fromDisk('vidéos') ->ouvrir('steve_howe.mp4') ->addWatermark(function(WatermarkFactory $watermark) {$watermark->fromDisk('local') ->ouvrir('logo.png') ->droite(25) ->bas(25); });
Au lieu d’utiliser les méthodes position, vous pouvez également utiliser les méthodes horizontalAlignment
et verticalAlignment
.
Pour l’alignement horizontal, vous pouvez utiliser les constantes WatermarkFactory::LEFT
, WatermarkFactory::CENTER
et WatermarkFactory::RIGHT
. Pour l’alignement vertical, vous pouvez utiliser les constantes WatermarkFactory::TOP
, WatermarkFactory::CENTER
et WatermarkFactory::BOTTOM
. Les deux méthodes prennent un deuxième paramètre facultatif, qui est le décalage.
FFMpeg::open('steve_howe.mp4') ->addWatermark(function(WatermarkFactory $watermark) {$watermark->open('logo.png') ->alignementhorizontal(WatermarkFactory::LEFT, 25) ->alignementvertical(WatermarkFactory::TOP, 25); });
WatermarkFactory
prend également en charge l'ouverture de fichiers à partir du Web avec la méthode openUrl
. Il prend également en charge les en-têtes HTTP personnalisés.
FFMpeg::open('steve_howe.mp4') ->addWatermark(function(WatermarkFactory $watermark) {$watermark->openUrl('https://videocoursebuilder.com/logo.png');// ou$watermark->openUrl('https://videocoursebuilder.com/ logo.png', ['Autorisation' => 'YWRtaW46MTIzNA==' de base, ]); });
Si vous souhaitez plus de contrôle sur la requête GET, vous pouvez transmettre un troisième paramètre facultatif, qui vous donne la ressource Curl.
$watermark->openUrl('https://videocoursebuilder.com/logo.png', ['Autorisation' => 'Basic YWRtaW46MTIzNA==', ], function($curl) {curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 0);curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, 0); });
Ce package peut manipuler les filigranes en utilisant le package Image de Spatie. Pour commencer, installez le package avec Composer :
le compositeur nécessite spatie/image
Vous pouvez désormais enchaîner une méthode de manipulation supplémentaire sur l'instance WatermarkFactory
:
FFMpeg::open('steve_howe.mp4') ->addWatermark(function(WatermarkFactory $watermark) {$watermark->open('logo.png') ->droite(25) ->bas(25) ->largeur(100) ->hauteur(100) ->échelle de gris(); });
Consultez la documentation pour toutes les méthodes disponibles.
Ce package est livré avec une classe ProtoneMediaLaravelFFMpegFFMpegCopyFormat
qui vous permet d'exporter un fichier sans transcoder les flux. Vous souhaiterez peut-être utiliser ceci pour utiliser un autre conteneur :
utilisez ProtoneMediaLaravelFFMpegFFMpegCopyFormat ; FFMpeg::open('vidéo.mp4') ->exporter() ->inFormat (nouveau CopyFormat) ->save('video.mkv');
// La méthode 'fromDisk()' n'est pas requise, le fichier va maintenant// être ouvert à partir du 'disque' par défaut, comme spécifié dans// le fichier de configuration.FFMpeg::open('my_movie.mov')// exporter vers FTP, converti en WMV->export() ->versDisque('ftp') ->inFormat (nouveau FFMpegFormatVideoWMV) ->save('my_movie.wmv')// export vers Amazon S3, converti en X264->export() ->versDisque('s3') ->inFormat (nouveau FFMpegFormatVideoX264) ->save('my_movie.mkv');// vous pouvez même ignorer la méthode 'toDisk()',// maintenant le fichier converti sera enregistré sur// le même disque que la source !->export() ->inFormat (nouveau FFMpegFormatVideoWebM) ->save('my_movie.webm')// vous pouvez éventuellement définir la visibilité// du fichier exporté->export() ->inFormat (nouveau FFMpegFormatVideoWebM) ->avecVisibilité('public') ->sauvegarder('mon_film.webm')
FFMpeg::fromDisk('vidéos') ->ouvrir('steve_howe.mp4') ->getFrameFromSeconds(10) ->exporter() ->toDisk('vignettes') ->save('FrameAt10sec.png');// Au lieu de la méthode 'getFrameFromSeconds()', vous pouvez// utiliser également la méthode 'getFrameFromString()' ou// 'getFrameFromTimecode()' :$media = FFMpeg ::open('steve_howe.mp4');$frame = $media->getFrameFromString('00:00:13.37');// ou$timecode = new FFMpegCoordonnéeTimeCode(...);$frame = $media->getFrameFromTimecode($timecode);
Vous pouvez également obtenir le contenu brut du cadre au lieu de l'enregistrer dans le système de fichiers :
$contents = FFMpeg::open('video.mp4') ->getFrameFromSeconds(2) ->exporter() ->getFrameContents();
Il existe un TileFilter
qui alimente la fonctionnalité Tile. Pour rendre l'exportation de plusieurs images plus rapide et plus simple, nous avons exploité cette fonctionnalité pour ajouter quelques méthodes d'assistance. Par exemple, vous pouvez utiliser la méthode exportFramesByInterval
pour exporter des images selon un intervalle fixe. Alternativement, vous pouvez transmettre le nombre d'images que vous souhaitez exporter à la méthode exportFramesByAmount
, qui calculera ensuite l'intervalle en fonction de la durée de la vidéo.
FFMpeg::open('vidéo.mp4') ->exportFramesByInterval(2) ->save('thumb_%05d.jpg');
Les deux méthodes acceptent un deuxième et un troisième arguments facultatifs pour spécifier la largeur et la hauteur des cadres. Au lieu de transmettre à la fois la largeur et la hauteur, vous pouvez également en transmettre une seule. FFmpeg respectera le rapport hauteur/largeur de la source.
FFMpeg::open('vidéo.mp4') ->exportFramesByAmount(10, 320, 180) ->save('thumb_%05d.png');
Les deux méthodes acceptent un quatrième argument facultatif pour spécifier la qualité de l'image lorsque vous exportez vers un format avec perte tel que JPEG. La plage pour JPEG est 2-31
, 2
étant la meilleure qualité et 31
la pire.
FFMpeg::open('vidéo.mp4') ->exportFramesByInterval(2, 640, 360, 5) ->save('thumb_%05d.jpg');
Vous pouvez créer des vignettes à partir d'une vidéo. Vous pouvez appeler la méthode exportTile
pour spécifier comment vos vignettes doivent être générées. Dans l'exemple ci-dessous, chaque image générée est constituée d'une grille 3x5 (contenant donc 15 images) et chaque image fait 160x90 pixels. Une image sera prise toutes les 5 secondes à partir de la vidéo. Au lieu de transmettre à la fois la largeur et la hauteur, vous pouvez également en transmettre une seule. FFmpeg respectera le rapport hauteur/largeur de la source.
utilisez ProtoneMediaLaravelFFMpegFiltersTileFactory ; FFMpeg::open('steve_howe.mp4') ->exportTile(fonction (TileFactory $factory) {$factory->intervalle(5) ->échelle(160, 90) ->grille(3, 5); }) ->save('tile_%05d.jpg');
Au lieu de transmettre à la fois la largeur et la hauteur, vous pouvez également en transmettre une seule, comme scale(160)
ou scale(null, 90)
. Le rapport hauteur/largeur sera respecté. Le TileFactory
a également des méthodes margin
, padding
, width
et height
. Il existe également une méthode quality
pour spécifier la qualité lors de l'exportation vers un format avec perte comme JPEG. La plage pour JPEG est 2-31
, 2
étant la meilleure qualité et 31
la pire.
Ce package peut également générer un fichier WebVTT pour ajouter des vignettes d'aperçu à votre lecteur vidéo. Ceci est pris en charge immédiatement par le lecteur JW et des plugins communautaires pour Video.js sont également disponibles. Vous pouvez appeler la méthode generateVTT
sur TileFactory
avec le nom de fichier souhaité :
FFMpeg::open('steve_howe.mp4') ->exportTile(fonction (TileFactory $factory) {$factory->intervalle(10) ->échelle(320, 180) ->grille(5, 5) ->generateVTT('thumbnails.vtt'); }) ->save('tile_%05d.jpg');
Le chaînage de plusieurs conversions fonctionne car la méthode save
de MediaExporter
renvoie une nouvelle instance de MediaOpener
. Vous pouvez l'utiliser pour parcourir des éléments, par exemple pour exporter plusieurs images d'une même vidéo :
$mediaOpener = FFMpeg::open('video.mp4');foreach ([5, 15, 25] comme $key => $seconds) {$mediaOpener = $mediaOpener->getFrameFromSeconds($seconds) ->exporter() ->save("thumb_{$key}.png"); }
Le MediaOpener
est également livré avec une méthode each
. L'exemple ci-dessus pourrait être refactorisé comme ceci :
FFMpeg::open('video.mp4')->each([5, 15, 25], fonction ($ffmpeg, $seconds, $key) {$ffmpeg->getFrameFromSeconds($seconds)->export()- >save("thumb_{$key}.png"); });
Vous pouvez créer un timelapse à partir d'une séquence d'images en utilisant la méthode asTimelapseWithFramerate
sur l'exportateur.
FFMpeg::open('feature_%04d.png') ->exporter() ->asTimelapseWithFramerate(1) ->inFormat (nouveau X264) ->save('timelapse.mp4');
Vous pouvez ouvrir plusieurs entrées, même à partir de disques différents. Cela utilise les fonctionnalités map
et filter_complex
de FFMpeg. Vous pouvez ouvrir plusieurs fichiers en chaînant la méthode open
ou en utilisant un tableau. Vous pouvez mélanger les entrées de différents disques.
FFMpeg::open('video1.mp4')->open('video2.mp4'); FFMpeg::open(['video1.mp4', 'video2.mp4']); FFMpeg::fromDisk('téléchargements') ->ouvrir('video1.mp4') ->fromDisk('archive') ->ouvrir('video2.mp4');
Lorsque vous ouvrez plusieurs entrées, vous devez ajouter des mappages pour que FFMpeg sache comment les acheminer. Ce package fournit une méthode addFormatOutputMapping
, qui prend trois paramètres : le format, la sortie et les étiquettes de sortie de la partie -filter_complex
.
La sortie (2ème argument) doit être une instance de ProtoneMediaLaravelFFMpegFilesystemMedia
. Vous pouvez instancier avec la méthode make
, l'appeler avec le nom du disque et le chemin (voir exemple).
Découvrez cet exemple, qui mappe des entrées vidéo et audio distinctes en une seule sortie.
FFMpeg::fromDisk('local') ->ouvrir(['video.mp4', 'audio.m4a']) ->exporter() ->addFormatOutputMapping(new X264, Media::make('local', 'new_video.mp4'), ['0:v', '1:a']) ->sauvegarder();
Ceci est un exemple de la bibliothèque sous-jacente :
// Ce code prend 2 vidéos d'entrée, les empile horizontalement dans 1 vidéo de sortie et// ajoute à cette nouvelle vidéo l'audio de la première vidéo. (C'est impossible // avec un simple filtre graphique qui n'a qu'une seule entrée et une seule sortie).FFMpeg::fromDisk('local') ->ouvrir(['video.mp4', 'video2.mp4']) ->exporter() ->addFilter('[0:v][1:v]', 'hstack', '[v]') // $in, $parameters, $out->addFormatOutputMapping(new X264, Media::make(' local', 'stacked_video.mp4'), ['0:a', '[v]']) ->sauvegarder();
Tout comme les entrées simples, vous pouvez également transmettre un rappel à la méthode addFilter
. Cela vous donnera une instance de FFMpegFiltersAdvancedMediaComplexFilters
:
utilisez FFMpegFiltersAdvancedMediaComplexFilters ; FFMpeg::open(['video.mp4', 'video2.mp4']) ->exporter() ->addFilter(function(ComplexFilters $filters) {// $filters->watermark(...);});
L'ouverture de fichiers à partir du Web fonctionne de la même manière. Vous pouvez transmettre un tableau d'URL à la méthode openUrl
, éventuellement avec des en-têtes HTTP personnalisés.
FFMpeg::openUrl(['https://videocoursebuilder.com/lesson-3.mp4','https://videocoursebuilder.com/lesson-4.mp4', ]); FFMpeg::openUrl(['https://videocoursebuilder.com/lesson-3.mp4','https://videocoursebuilder.com/lesson-4.mp4', ], ['Autorisation' => 'YWRtaW46MTIzNA==' de base, ]);
Si vous souhaitez utiliser un autre ensemble d'en-têtes HTTP pour chaque URL, vous pouvez chaîner la méthode openUrl
:
FFMpeg::openUrl('https://videocoursebuilder.com/lesson-5.mp4', ['Autorisation' => 'Basic YWRtaW46MTIzNA==', ])->openUrl('https://videocoursebuilder.com/lesson-6.mp4', ['Autorisation' => 'Basic bmltZGE6NDMyMQ==', ]);
FFMpeg::fromDisk('local') ->ouvrir(['video.mp4', 'video2.mp4']) ->exporter() ->concatSansTranscodage() ->save('concat.mp4');
FFMpeg::fromDisk('local') ->ouvrir(['video.mp4', 'video2.mp4']) ->exporter() ->inFormat (nouveau X264) ->concatWithTranscoding($hasVideo = true, $hasAudio = true) ->save('concat.mp4');
Avec la classe Media
vous pouvez déterminer la durée d'un fichier :
$media = FFMpeg::open('wwdc_2006.mp4');$durationInSeconds = $media->getDurationInSeconds(); // renvoie un int$durationInMiliseconds = $media->getDurationInMiliseconds(); // renvoie un flottant
Lors de l'ouverture ou de l'enregistrement de fichiers depuis ou vers un disque distant, des fichiers temporaires seront créés sur votre serveur. Une fois que vous avez fini d'exporter ou de traiter ces fichiers, vous pouvez les nettoyer en appelant la méthode cleanupTemporaryFiles()
:
FFMpeg::cleanupTemporaryFiles();
Par défaut, la racine des répertoires temporaires est évaluée par la méthode sys_get_temp_dir()
de PHP, mais vous pouvez la modifier en définissant la clé de configuration temporary_files_root
sur un chemin personnalisé.
Vous pouvez créer une playlist M3U8 pour faire du HLS.
$lowBitrate = (nouveau X264)->setKiloBitrate(250);$midBitrate = (nouveau X264)->setKiloBitrate(500);$highBitrate = (nouveau X264)->setKiloBitrate(1000); FFMpeg::fromDisk('vidéos') ->ouvrir('steve_howe.mp4') ->exportForHLS() ->setSegmentLength(10) // facultatif->setKeyFrameInterval(48) // facultatif->addFormat($lowBitrate) ->ajouterFormat($midBitrate) ->ajouterFormat($highBitrate) ->save('adaptive_steve.m3u8');
La méthode addFormat
de l'exportateur HLS prend un deuxième paramètre facultatif qui peut être une méthode de rappel. Cela vous permet d'ajouter différents filtres par format. Tout d’abord, consultez la section Entrées multiples pour comprendre comment les filtres complexes sont gérés.
Vous pouvez utiliser la méthode addFilter
pour ajouter un filtre complexe (voir l'exemple $lowBitrate
). Comme le filtre scale
est beaucoup utilisé, il existe une méthode d'assistance (voir l'exemple $midBitrate
). Vous pouvez également utiliser un appelable pour accéder à l'instance ComplexFilters
. Le package fournit les arguments $in
et $out
afin que vous n'ayez pas à vous en soucier (voir l'exemple $highBitrate
).
L'exportation HLS est construite à l'aide des fonctionnalités map
et filter_complex
de FFMpeg. Il s'agit d'un changement radical par rapport aux versions précédentes (1.x - 6.x) qui effectuaient une seule exportation pour chaque format. Si vous effectuez une mise à niveau, remplacez les appels addFilter
par des appels addLegacyFilter
et vérifiez le résultat (voir l'exemple $superBitrate
). Tous les filtres ne fonctionneront pas de cette façon et certains devront être mis à niveau manuellement.
$lowBitrate = (nouveau X264)->setKiloBitrate(250);$midBitrate = (nouveau X264)->setKiloBitrate(500);$highBitrate = (nouveau X264)->setKiloBitrate(1000);$superBitrate = (nouveau X264)- >setKiloBitrate(1500); FFMpeg::open('steve_howe.mp4') ->exportForHLS() ->addFormat($lowBitrate, function($media) {$media->addFilter('scale=640:480'); }) ->addFormat($midBitrate, function($media) {$media->scale(960, 720); }) ->addFormat($highBitrate, fonction ($media) {$media->addFilter(function ($filters, $in, $out) {$filters->custom($in, 'scale=1920:1200', $out ); // $in, $parameters, $out}); }) ->addFormat($superBitrate, function($media) {$media->addLegacyFilter(function ($filters) {$filters->resize(new FFMpegCoordonnéeDimension(2560, 1920)); }); }) ->save('adaptive_steve.m3u8');
Vous pouvez utiliser un modèle personnalisé pour nommer les segments et les listes de lecture. Le useSegmentFilenameGenerator
vous donne 5 arguments. Les premier, deuxième et troisième arguments fournissent des informations sur le nom de base de l'export, le format de l'itération en cours et la clé de l'itération en cours. Le quatrième argument est un rappel que vous devez appeler avec votre modèle de segments . Le cinquième argument est un rappel que vous devez appeler avec votre modèle de playlist . Notez qu'il ne s'agit pas du nom de la playlist principale, mais du nom de la playlist de chaque format.
FFMpeg::fromDisk('vidéos') ->ouvrir('steve_howe.mp4') ->exportForHLS() ->useSegmentFilenameGenerator(function ($name, $format, $key, $segments appelables, $playlist appelable) {$segments("{$name}-{$format->getKiloBitrate()}-{$key}-%03d .ts");$playlist("{$name}-{$format->getKiloBitrate()}-{$key}.m3u8"); });
Vous pouvez chiffrer chaque segment HLS à l'aide du chiffrement AES-128. Pour ce faire, appelez la méthode withEncryptionKey
sur l'exportateur HLS avec une clé. Nous fournissons une méthode d'assistance generateEncryptionKey
sur la classe HLSExporter
pour générer une clé. Assurez-vous de bien stocker la clé, car le résultat exporté ne vaut rien sans la clé. Par défaut, le nom de fichier de la clé est secret.key
, mais vous pouvez le modifier avec le deuxième paramètre facultatif de la méthode withEncryptionKey
.
utilisez ProtoneMediaLaravelFFMpegExportersHLSExporter;$encryptionKey = HLSExporter::generateEncryptionKey(); FFMpeg::open('steve_howe.mp4') ->exportForHLS() ->avecEncryptionKey($encryptionKey) ->ajouterFormat($lowBitrate) ->ajouterFormat($midBitrate) ->ajouterFormat($highBitrate) ->save('adaptive_steve.m3u8');
Pour sécuriser encore plus votre export HLS, vous pouvez faire pivoter la clé sur chaque segment exporté. Ce faisant, il générera plusieurs clés que vous devrez stocker. Utilisez la méthode withRotatingEncryptionKey
pour activer cette fonctionnalité et fournir un rappel qui implémente le stockage des clés.
FFMpeg::open('steve_howe.mp4') ->exportForHLS() ->withRotatingEncryptionKey(function ($filename, $contents) {$videoId = 1;// utiliser ce rappel pour stocker les clés de cryptageStorage::disk('secrets')->put($videoId . '/' . $filename, $contents);// ou...DB::table('hls_secrets')->insert(['video_id' => $videoId,'filename' => $filename,'contents' => $contents, ]); }) ->ajouterFormat($lowBitrate) ->ajouterFormat($midBitrate) ->ajouterFormat($highBitrate) ->save('adaptive_steve.m3u8');
La méthode withRotatingEncryptionKey
a un deuxième argument facultatif pour définir le nombre de segments qui utilisent la même clé. La valeur par défaut est 1
.
FFMpeg::open('steve_howe.mp4') ->exportForHLS() ->withRotatingEncryptionKey($callable, 10);
Certains systèmes de fichiers, en particulier sur les VPS lents et bon marché, ne sont pas assez rapides pour gérer la clé rotative. Cela peut entraîner des exceptions d'encodage, comme No key URI specified in key info file
. Une solution possible consiste à utiliser un stockage différent pour les clés, que vous pouvez spécifier à l'aide de la clé de configuration temporary_files_encrypted_hls
. Sur les systèmes basés sur UNIX, vous pouvez utiliser un système de fichiers tmpfs
pour augmenter les vitesses de lecture/écriture :
// config/laravel-ffmpeg.phpreturn ['temporary_files_encrypted_hls' => '/dev/shm'];
Pour améliorer encore le travail avec HLS chiffré, nous avons ajouté une classe DynamicHLSPlaylist
qui modifie les listes de lecture à la volée et spécifiquement pour votre application. De cette façon, vous pouvez ajouter votre logique d’authentification et d’autorisation. Comme nous utilisons un simple contrôleur Laravel, vous pouvez utiliser des fonctionnalités telles que Gates et Middleware.
Dans cet exemple, nous avons enregistré l'exportation HLS sur le disque public
et nous avons stocké les clés de chiffrement sur le disque secrets
, qui n'est pas accessible au public. Comme le navigateur ne peut pas accéder aux clés de cryptage, il ne lira pas la vidéo. Chaque liste de lecture possède des chemins vers les clés de chiffrement, et nous devons modifier ces chemins pour pointer vers un point de terminaison accessible.
Cette implémentation se compose de deux itinéraires. Celui qui répond avec une clé de cryptage et celui qui répond avec une liste de lecture modifiée. La première route ( video.key
) est relativement simple, et c'est ici que vous devez ajouter votre logique supplémentaire.
La deuxième route ( video.playlist
) utilise la classe DynamicHLSPlaylist
. Appelez la méthode dynamicHLSPlaylist
sur la façade FFMpeg
, et comme pour l'ouverture de fichiers multimédias, vous pouvez ouvrir une liste de lecture en utilisant les méthodes fromDisk
et open
. Ensuite, vous devez fournir trois rappels. Chacun d’eux vous donne un chemin relatif et attend un chemin complet en retour. Comme la classe DynamicHLSPlaylist
implémente l'interface IlluminateContractsSupportResponsable
, vous pouvez renvoyer l'instance.
Le premier rappel (KeyUrlResolver) vous donne le chemin relatif vers une clé de chiffrement. Le deuxième rappel (MediaUrlResolver) vous donne le chemin relatif vers un segment multimédia (fichiers .ts). Le troisième rappel (PlaylistUrlResolver) vous donne le chemin relatif vers une playlist.
Désormais, au lieu d'utiliser Storage::disk('public')->url('adaptive_steve.m3u8')
pour obtenir l'URL complète de votre liste de lecture principale, vous pouvez utiliser route('video.playlist', ['playlist' => 'adaptive_steve.m3u8'])
. La classe DynamicHLSPlaylist
prend en charge tous les chemins et URL.
Route::get('/video/secret/{key}', function ($key) {return Storage::disk('secrets')->download($key); }) -> nom ('video.key'); Route::get('/video/{playlist}', fonction ($playlist) {return FFMpeg::dynamicHLSPlaylist() ->fromDisk('public') ->ouvrir ($playlist) ->setKeyUrlResolver(function ($key) {return route('video.key', ['key' => $key]); }) ->setMediaUrlResolver(function ($mediaFilename) {return Storage::disk('public')->url($mediaFilename); }) ->setPlaylistUrlResolver(function ($playlistFilename) {return route('video.playlist', ['playlist' => $playlistFilename]); }); }) -> nom ('video.playlist');
Vous trouverez ici une session de codage en direct sur le cryptage HLS :
https://www.youtube.com/watch?v=WlbzWoAcez4
Vous pouvez obtenir le résultat brut du processus en appelant la méthode getProcessOutput
. Bien que le cas d'utilisation soit limité, vous pouvez l'utiliser pour analyser un fichier (par exemple, avec le filtre volumedetect
). Il renvoie une classe ProtoneMediaLaravelFFMpegSupportProcessOutput
qui possède trois méthodes : all
, errors
et output
. Chaque méthode renvoie un tableau avec les lignes correspondantes.
$processOutput = FFMpeg::open('video.mp4') ->exporter() ->addFilter(['-filter:a', 'volumedetect', '-f', 'null']) ->getProcessOutput();$processOutput->all();$processOutput->errors();$processOutput->out();
L'objet Media que vous obtenez lorsque vous « ouvrez » un fichier contient en fait l'objet Media qui appartient au pilote sous-jacent. Il gère les appels de méthodes dynamiques comme vous pouvez le voir ici. De cette façon, toutes les méthodes du pilote sous-jacent sont toujours disponibles.
// Cela vous donne une instance de ProtoneMediaLaravelFFMpegMediaOpener$media = FFMpeg::fromDisk('videos')->open('video.mp4');// La méthode 'getStreams' sera appelée sur l'objet Media sous-jacent puisque// il n'existe pas sur cet objet.$codec = $media->getStreams()->first()->get('codec_name');
Si vous souhaitez un accès direct à l'objet sous-jacent, appelez l'objet en tant que fonction (invoquer) :
// Cela vous donne une instance de ProtoneMediaLaravelFFMpegMediaOpener$media = FFMpeg::fromDisk('videos')->open('video.mp4');// Cela vous donne une instance de FFMpegMediaMediaTypeInterface$baseMedia = $media();
L'écouteur de progression expose le pourcentage transcodé, mais le package sous-jacent dispose également d'un AbstractProgressListener
interne qui expose la passe actuelle et l'heure actuelle. Bien que le cas d'utilisation soit limité, vous souhaiterez peut-être accéder à cette instance d'écoute. Vous pouvez le faire en décorant le format avec ProgressListenerDecorator
. Cette fonctionnalité est hautement expérimentale, alors assurez-vous de la tester minutieusement avant de l'utiliser en production.
utilisez FFMpegFormatProgressListenerAbstractProgressListener; utilisez ProtoneMediaLaravelFFMpegFFMpegProgressListenerDecorator;$format = new FFMpegFormatVideoX264;$decoratedFormat = ProgressListenerDecorator::decorate($format); FFMpeg::open('vidéo.mp4') ->exporter() ->inFormat($decoratedFormat) ->onProgress(function () use ($decoratedFormat) {$listeners = $decoratedFormat->getListeners(); // tableau d'écouteurs$listener = $listeners[0]; // instance de AbstractProgressListener$listener->getCurrentPass() ;$listener->getTotalPass();$listener->getCurrentTime(); }) ->save('new_video.mp4');
Comme nous ne pouvons pas supprimer certaines options sous-jacentes, vous pouvez interagir avec la commande FFmpeg finale en ajoutant un rappel à l'exportateur. Vous pouvez ajouter un ou plusieurs rappels en utilisant la méthode beforeSaving
:
FFMpeg::open('vidéo.mp4') ->exporter() ->inFormat (nouveau X264) ->beforeSaving(function ($commandes) {$commands[] = '-hello';return $commands; }) ->save('concat.mp4');
Remarque : cela ne fonctionne pas avec la concaténation et les exportations de trames
Voici un article de blog qui vous aidera à démarrer avec ce package :
https://protone.media/en/blog/how-to-use-ffmpeg-in-your-laravel-projects
Voici un aperçu de 20 minutes sur la façon de démarrer avec Video.js. Il couvre l'inclusion de Video.js à partir d'un CDN, son importation en tant que module ES6 avec Laravel Mix (Webpack) et la création d'un composant Vue.js réutilisable.
https://www.youtube.com/watch?v=nA1Jy8BPjys
Filtres personnalisés
FFmpeg n'a pas réussi à exécuter la commande
Obtenir les dimensions d'un fichier vidéo
Suivi de la progression du transcodage
Impossible de charger FFProbe
Veuillez consulter CHANGELOG pour plus d'informations sur ce qui a changé récemment.
$ test du compositeur
Veuillez consulter CONTRIBUER pour plus de détails.
Inertia Table
: la table ultime pour Inertia.js avec le générateur de requêtes intégré.
Laravel Blade On Demand
: Package Laravel pour compiler des modèles Blade en mémoire.
Laravel Cross Eloquent Search
: package Laravel pour rechercher dans plusieurs modèles Eloquent.
Laravel Eloquent Scope as Select
: arrêtez de dupliquer les portées et les contraintes de vos requêtes Eloquent en PHP. Ce package vous permet de réutiliser les étendues et contraintes de vos requêtes en les ajoutant en tant que sous-requête.
Laravel MinIO Testing Tools
: exécutez vos tests sur un serveur MinIO S3.
Laravel Mixins
: Une collection de goodies Laravel.
Laravel Paddle
: Intégration de l'API Paddle.com pour Laravel avec prise en charge des webhooks/événements.
Laravel Task Runner
: écrivez des scripts Shell comme les composants Blade et exécutez-les localement ou sur un serveur distant.
Laravel Verify New Email
: Ce package ajoute la prise en charge de la vérification des nouvelles adresses e-mail : lorsqu'un utilisateur met à jour son adresse e-mail, il ne remplacera pas l'ancienne tant que la nouvelle n'est pas vérifiée.
Laravel XSS Protection
: Laravel Middleware pour protéger votre application contre le Cross-site scripting (XSS). Il nettoie les entrées de requête et peut nettoyer les instructions d'écho de Blade.
Si vous découvrez des problèmes liés à la sécurité, veuillez envoyer un e-mail à [email protected] au lieu d'utiliser le suivi des problèmes. Veuillez ne pas envoyer de questions par courrier électronique, ouvrez un problème si vous avez une question.
Pascal Baljet
Tous les contributeurs
La licence MIT (MIT). Veuillez consulter le fichier de licence pour plus d'informations.