Este paquete proporciona una integración con FFmpeg para Laravel 10. El sistema de archivos de Laravel maneja el almacenamiento de los archivos.
Estamos orgullosos de apoyar a la comunidad desarrollando paquetes de Laravel y regalándolos de forma gratuita. Si este paquete le ahorra tiempo o si confía en él profesionalmente, considere patrocinar el mantenimiento y el desarrollo y consulte nuestro último paquete premium: Inertia Table. Realizar un seguimiento de los problemas y las solicitudes de extracción lleva tiempo, ¡pero estaremos encantados de ayudarle!
Envoltorio súper sencillo para PHP-FFMpeg, que incluye soporte para filtros y otras funciones avanzadas.
Integración con el sistema de archivos de Laravel, sistema de configuración y manejo de registros.
Compatible con Laravel 10, soporte para Package Discovery.
Soporte integrado para HLS.
Soporte integrado para HLS cifrado (AES-128) y claves rotativas (opcional).
Soporte integrado para concatenación, múltiples entradas/salidas, secuencias de imágenes (timelapse), filtros complejos (y mapeo), exportaciones de fotogramas/miniaturas.
Soporte incorporado para marcas de agua (posicionamiento y manipulación).
Soporte integrado para crear un mosaico/sprite/mosaico a partir de un vídeo.
Soporte integrado para generar archivos de miniaturas de vista previa de VTT .
Requiere PHP 8.1 o superior.
Probado con FFmpeg 4.4 y 5.0.
Verifique que tenga instalada la última versión de FFmpeg:
ffmpeg -versión
Puede instalar el paquete a través del compositor:
el compositor requiere pbmedia/laravel-ffmpeg
Agregue el proveedor de servicios y Facade a su archivo de configuración app.php
si no está utilizando Package Discovery.
// config/app.php'proveedores' => [ ...ProtoneMediaLaravelFFMpegSupportServiceProvider::clase, ... ];'alias' => [ ...'FFMpeg' => ProtoneMediaLaravelFFMpegSupportFFMpeg::clase ... ];
Publique el archivo de configuración utilizando la herramienta CLI artesanal:
Proveedor artesanal de php: publicar --provider="ProtoneMediaLaravelFFMpegSupportServiceProvider"
La clave de configuración set_command_and_error_output_on_exception
ahora tiene el valor predeterminado true
, lo que hace que las excepciones sean más informativas. Lea más en la sección Manejo de excepciones.
La clave de configuración enable_logging
ha sido reemplazada por log_channel
para elegir el canal de registro utilizado al escribir mensajes en los registros. Si aún desea deshabilitar el registro por completo, puede establecer la nueva clave de configuración en false
.
La longitud del segmento y el intervalo de fotogramas clave de las exportaciones HLS deben ser 2
o más; less ya no es compatible.
Como Laravel 9 ha migrado de Flysystem 1.x a 3.x, esta versión no es compatible con Laravel 8 o versiones anteriores.
Si está utilizando la función de manipulación de marcas de agua, asegúrese de actualizar spatie/image
a v2.
El espacio de nombres cambió a ProtoneMediaLaravelFFMpeg
, la fachada pasó a llamarse ProtoneMediaLaravelFFMpegSupportFFMpeg
y el proveedor de servicios pasó a llamarse ProtoneMediaLaravelFFMpegSupportServiceProvider
.
Aún se admiten exportaciones encadenadas, pero debe volver a aplicar filtros para cada exportación.
Las listas de reproducción HLS ahora incluyen datos de tasa de bits, velocidad de fotogramas y resolución. Los segmentos también utilizan un nuevo patrón de nomenclatura (leer más). Verifique que sus exportaciones aún funcionen en su reproductor.
La exportación HLS ahora se ejecuta como un trabajo en lugar de exportar cada formato/transmisión por separado. Esto utiliza map
de FFMpeg y las funciones filter_complex
. Podría ser suficiente reemplazar todas las llamadas a addFilter
con addLegacyFilter
, pero algunos filtros se deben migrar manualmente. Lea la documentación sobre HLS para obtener más información sobre cómo agregar filtros.
Convertir un archivo de audio o vídeo:
FFMpeg::fromDisk('canciones') ->abrir('ayer.mp3') ->exportar() ->toDisk('canciones_convertidas') ->inFormat(nuevo FFMpegFormatAudioAac) ->save('ayer.aac');
En lugar del método fromDisk()
también puedes usar el método fromFilesystem()
, donde $filesystem
es una instancia de IlluminateContractsFilesystemFilesystem
.
$media = FFMpeg::fromFilesystem($filesystem)->open('ayer.mp3');
Puede monitorear el progreso de la transcodificación. Utilice el método onProgress
para proporcionar una devolución de llamada, que le proporcionará el porcentaje completado. En versiones anteriores de este paquete tenías que pasar la devolución de llamada al objeto de formato.
FFMpeg::open('steve_howe.mp4') ->exportar() ->onProgress(function ($porcentaje) {echo "{$porcentaje}% transcodificado"; });
La devolución de llamada también puede exponer $remaining
(en segundos) y $rate
:
FFMpeg::open('steve_howe.mp4') ->exportar() ->onProgress(function ($porcentaje, $restante, $rate) {echo "{$restantes} segundos restantes en rate: {$rate}"; });
Puede abrir archivos cargados directamente desde la instancia Request
. Probablemente sea mejor guardar primero el archivo cargado en caso de que la solicitud se cancele, pero si lo deseas, puedes abrir una instancia UploadedFile
:
clase UploadVideoController {función pública __invocar(Solicitud $solicitud) { FFMpeg::open($solicitud->archivo('vídeo')); } }
Puede abrir archivos desde la web utilizando el método openUrl
. Puede especificar encabezados HTTP personalizados con el segundo parámetro opcional:
FFMpeg::openUrl('https://videocoursebuilder.com/lesson-1.mp4'); FFMpeg::openUrl('https://videocoursebuilder.com/lesson-2.mp4', ['Autorización' => 'Básico YWRtaW46MTIzNA==', ]);
Cuando la codificación falla, se lanzará una ProtoneMediaLaravelFFMpegExportersEncodingException
, que extiende la clase FFMpegExceptionRuntimeException
subyacente. Esta clase tiene dos métodos que pueden ayudarle a identificar el problema. Usando el método getCommand
, puede obtener el comando ejecutado con todos los parámetros. El método getErrorOutput
le proporciona un registro de salida completo.
En versiones anteriores de este paquete, el mensaje de excepción siempre era Error de codificación . Puede bajar a este mensaje actualizando la clave de configuración set_command_and_error_output_on_exception
a false
.
intentar { FFMpeg::open('ayer.mp3') ->exportar() ->inFormat(nuevo Aac) ->save('ayer.aac'); } catch (EncodingException $excepción) {$comando = $excepción->getCommand();$errorLog = $excepción->getErrorOutput(); }
Puede agregar filtros a través de un Closure
o utilizando los objetos Filter de PHP-FFMpeg:
utilice FFMpegFiltersVideoVideoFilters; FFMpeg::fromDisk('vídeos') ->abrir('steve_howe.mp4') ->addFilter(función (VideoFilters $filtros) {$filtros->resize(new FFMpegCoordinateDimension(640, 480)); }) ->exportar() ->toDisk('videos_convertidos') ->inFormat(nuevo FFMpegFormatVideoX264) ->save('small_steve.mkv');// o$start = FFMpegCoordinateTimeCode::fromSeconds(5)$clipFilter = new FFMpegFiltersVideoClipFilter($start); FFMpeg::fromDisk('vídeos') ->abrir('steve_howe.mp4') ->añadirFilter($clipFilter) ->exportar() ->toDisk('videos_convertidos') ->inFormat(nuevo FFMpegFormatVideoX264) ->save('short_steve.mkv');
También puedes llamar al método addFilter
después del método export
:
utilice FFMpegFiltersVideoVideoFilters; FFMpeg::fromDisk('vídeos') ->abrir('steve_howe.mp4') ->exportar() ->toDisk('videos_convertidos') ->inFormat(nuevo FFMpegFormatVideoX264) ->addFilter(función (VideoFilters $filtros) {$filtros->resize(new FFMpegCoordinateDimension(640, 480)); }) ->save('small_steve.mkv');
Dado que cambiar el tamaño es una operación común, hemos agregado un método dedicado para ello:
FFMpeg::open('steve_howe.mp4') ->exportar() ->inFormat(nuevo FFMpegFormatVideoX264) ->cambiar tamaño(640, 480) ->save('steve_howe_resized.mp4');
El primer argumento es el ancho y el segundo argumento la altura. El tercer argumento opcional es la moda. Puede elegir entre fit
(predeterminado), inset
, width
o height
. El cuarto argumento opcional es un valor booleano sobre si se debe forzar o no el uso de proporciones estándar. Puede obtener información sobre estos modos en la clase FFMpegFiltersVideoResizeFilter
.
A veces no desea utilizar los filtros integrados. Puede aplicar su propio filtro proporcionando un conjunto de opciones. Puede ser una matriz o varias cadenas como argumentos:
FFMpeg::fromDisk('vídeos') ->abrir('steve_howe.mp4') ->addFilter(['-itsoffset', 1]);// oFFMpeg::fromDisk('videos') ->abrir('steve_howe.mp4') ->addFilter('-sudesplazamiento', 1);
Puede agregar fácilmente una marca de agua utilizando el método addWatermark
. Con WatermarkFactory
, puede abrir su archivo de marca de agua desde un disco específico, tal como abre un archivo de audio o video. Cuando descarta el método fromDisk
, utiliza el disco predeterminado especificado en el archivo de configuración filesystems.php
.
Después de abrir su archivo de marca de agua, puede colocarlo con los métodos top
, right
, bottom
e left
. El primer parámetro de estos métodos es el desplazamiento, que es opcional y puede ser negativo.
utilice ProtoneMediaLaravelFFMpegFiltersWatermarkFactory; FFMpeg::fromDisk('vídeos') ->abrir('steve_howe.mp4') ->addWatermark(function(WatermarkFactory $marca de agua) {$marca de agua->fromDisk('local') ->abrir('logotipo.png') ->derecha(25) ->abajo(25); });
En lugar de utilizar los métodos de posición, también puede utilizar los métodos horizontalAlignment
y verticalAlignment
.
Para la alineación horizontal, puede utilizar las constantes WatermarkFactory::LEFT
, WatermarkFactory::CENTER
y WatermarkFactory::RIGHT
. Para la alineación vertical, puede utilizar las constantes WatermarkFactory::TOP
, WatermarkFactory::CENTER
y WatermarkFactory::BOTTOM
. Ambos métodos toman un segundo parámetro opcional, que es el desplazamiento.
FFMpeg::open('steve_howe.mp4') ->addWatermark(function(WatermarkFactory $watermark) {$watermark->open('logo.png') ->alineaciónhorizontal(WatermarkFactory::IZQUIERDA, 25) ->alineaciónvertical(WatermarkFactory::TOP, 25); });
WatermarkFactory
también admite la apertura de archivos desde la web con el método openUrl
. También admite encabezados HTTP personalizados.
FFMpeg::open('steve_howe.mp4') ->addWatermark(function(WatermarkFactory $watermark) {$watermark->openUrl('https://videocoursebuilder.com/logo.png');// o$watermark->openUrl('https://videocoursebuilder.com/ logo.png', ['Autorización' => 'Básico YWRtaW46MTIzNA==', ]); });
Si desea tener más control sobre la solicitud GET, puede pasar un tercer parámetro opcional, que le proporciona el recurso Curl.
$watermark->openUrl('https://videocoursebuilder.com/logo.png', ['Autorización' => 'Básico YWRtaW46MTIzNA==', ], función($curl) {curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 0);curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, 0); });
Este paquete puede manipular marcas de agua utilizando el paquete Image de Spatie. Para comenzar, instale el paquete con Composer:
el compositor requiere espacio/imagen
Ahora puedes encadenar un método de manipulación más en la instancia WatermarkFactory
:
FFMpeg::open('steve_howe.mp4') ->addWatermark(function(WatermarkFactory $watermark) {$watermark->open('logo.png') ->derecha(25) ->abajo(25) ->ancho(100) ->altura(100) ->escala de grises(); });
Consulte la documentación para conocer todos los métodos disponibles.
Este paquete viene con una clase ProtoneMediaLaravelFFMpegFFMpegCopyFormat
que le permite exportar un archivo sin transcodificar las transmisiones. Es posible que desee utilizar esto para utilizar otro contenedor:
utilice ProtoneMediaLaravelFFMpegFFMpegCopyFormat; FFMpeg::open('vídeo.mp4') ->exportar() ->inFormat(nuevo formato de copia) ->guardar('vídeo.mkv');
// El método 'fromDisk()' no es necesario, el archivo ahora// se abrirá desde el 'disco' predeterminado, como se especifica en// el archivo de configuración.FFMpeg::open('my_movie.mov')// exportar a FTP, convertir en WMV->export() ->al disco('ftp') ->inFormat(nuevo FFMpegFormatVideoWMV) ->save('my_movie.wmv')// exportar a Amazon S3, convertido a X264->export() ->al disco('s3') ->inFormat(nuevo FFMpegFormatVideoX264) ->save('my_movie.mkv');// ¡incluso podrías descartar el método 'toDisk()',// ahora el archivo convertido se guardará en// el mismo disco que la fuente!->export() ->inFormat(nuevo FFMpegFormatVideoWebM) ->save('my_movie.webm')// opcionalmente puedes configurar la visibilidad// del archivo exportado->export() ->inFormat(nuevo FFMpegFormatVideoWebM) ->conVisibilidad('público') ->guardar('mi_película.webm')
FFMpeg::fromDisk('vídeos') ->abrir('steve_howe.mp4') ->obtenerMarcoDeSegundos(10) ->exportar() ->toDisk('miniaturas') ->save('FrameAt10sec.png');// En lugar del método 'getFrameFromSeconds()', también puedes// utilizar los métodos 'getFrameFromString()' o// 'getFrameFromTimecode()':$media = FFMpeg ::open('steve_howe.mp4');$marco = $media->getFrameFromString('00:00:13.37');// o$timecode = new FFMpegCoordinateTimeCode(...);$frame = $media->getFrameFromTimecode($timecode);
También puedes obtener el contenido sin procesar del marco en lugar de guardarlo en el sistema de archivos:
$contenido = FFMpeg::open('video.mp4') ->getFrameFromSeconds(2) ->exportar() ->getFrameContents();
Hay un TileFilter
que potencia la función Tile. Para que la exportación de varios fotogramas sea más rápida y sencilla, aprovechamos esta función para agregar algunos métodos auxiliares. Por ejemplo, puede utilizar el método exportFramesByInterval
para exportar fotogramas en un intervalo fijo. Alternativamente, puede pasar la cantidad de cuadros que desea exportar al método exportFramesByAmount
, que luego calculará el intervalo en función de la duración del video.
FFMpeg::open('vídeo.mp4') ->exportarMarcosPorIntervalo(2) ->guardar('thumb_%05d.jpg');
Ambos métodos aceptan un segundo y tercer argumento opcionales para especificar el ancho y el alto de los marcos. En lugar de pasar tanto el ancho como el alto, también puedes pasar solo uno de ellos. FFmpeg respetará la relación de aspecto de la fuente.
FFMpeg::open('vídeo.mp4') ->exportarMarcosPorCantidad(10, 320, 180) ->save('thumb_%05d.png');
Ambos métodos aceptan un cuarto argumento opcional para especificar la calidad de la imagen cuando se exporta a un formato con pérdida como JPEG. El rango para JPEG es 2-31
, siendo 2
la mejor calidad y 31
la peor.
FFMpeg::open('vídeo.mp4') ->exportarMarcosPorIntervalo(2, 640, 360, 5) ->guardar('thumb_%05d.jpg');
Puedes crear mosaicos a partir de un vídeo. Puede llamar al método exportTile
para especificar cómo se deben generar sus mosaicos. En el siguiente ejemplo, cada imagen generada consta de una cuadrícula de 3x5 (que por lo tanto contiene 15 cuadros) y cada cuadro tiene 160x90 píxeles. Se tomará un fotograma cada 5 segundos del vídeo. En lugar de pasar tanto el ancho como el alto, también puedes pasar solo uno de ellos. FFmpeg respetará la relación de aspecto de la fuente.
utilice ProtoneMediaLaravelFFMpegFiltersTileFactory; FFMpeg::open('steve_howe.mp4') ->exportarTile(función (TileFactory $fábrica) {$fábrica->intervalo(5) ->escala(160, 90) ->cuadrícula(3, 5); }) ->guardar('tile_%05d.jpg');
En lugar de pasar tanto el ancho como el alto, también puedes pasar solo uno de ellos, como scale(160)
o scale(null, 90)
. Se respetará la relación de aspecto. TileFactory
también tiene métodos margin
, padding
, width
y height
. También existe un método quality
para especificar la calidad al exportar a un formato con pérdida como JPEG. El rango para JPEG es 2-31
, siendo 2
la mejor calidad y 31
la peor.
Este paquete también puede generar un archivo WebVTT para agregar miniaturas de vista previa a su reproductor de video. Esto es compatible desde el primer momento con JW Player y también hay disponibles complementos impulsados por la comunidad para Video.js. Puede llamar al método generateVTT
en TileFactory
con el nombre de archivo deseado:
FFMpeg::open('steve_howe.mp4') ->exportarTile(función (TileFactory $fábrica) {$fábrica->intervalo(10) ->escala(320, 180) ->cuadrícula(5, 5) ->generarVTT('miniaturas.vtt'); }) ->guardar('tile_%05d.jpg');
Encadenar múltiples conversiones funciona porque el método save
de MediaExporter
devuelve una nueva instancia de MediaOpener
. Puedes usar esto para recorrer elementos, por ejemplo, para exportar varios fotogramas de un vídeo:
$mediaOpener = FFMpeg::open('video.mp4');foreach ([5, 15, 25] as $key => $segundos) {$mediaOpener = $mediaOpener->getFrameFromSeconds($segundos) ->exportar() ->save("thumb_{$key}.png"); }
MediaOpener
también viene con each
método. El ejemplo anterior podría refactorizarse así:
FFMpeg::open('video.mp4')->cada uno([5, 15, 25], función ($ffmpeg, $segundos, $clave) {$ffmpeg->getFrameFromSeconds($segundos)->exportar()- >guardar("pulgar_{$clave}.png"); });
Puede crear un lapso de tiempo a partir de una secuencia de imágenes utilizando el método asTimelapseWithFramerate
en el exportador.
FFMpeg::open('feature_%04d.png') ->exportar() ->como TimelapseWithFramerate(1) ->inFormat(nuevo X264) ->guardar('timelapse.mp4');
Puede abrir múltiples entradas, incluso desde diferentes discos. Esto utiliza map
de FFMpeg y las funciones filter_complex
. Puede abrir varios archivos encadenando el método open
o utilizando una matriz. Puede mezclar entradas de diferentes discos.
FFMpeg::open('video1.mp4')->open('video2.mp4'); FFMpeg::open(['video1.mp4', 'video2.mp4']); FFMpeg::fromDisk('cargas') ->abrir('vídeo1.mp4') ->fromDisk('archivo') ->abrir('video2.mp4');
Cuando abre varias entradas, debe agregar asignaciones para que FFMpeg sepa cómo enrutarlas. Este paquete proporciona un método addFormatOutputMapping
, que toma tres parámetros: el formato, la salida y las etiquetas de salida de la parte -filter_complex
.
La salida (segundo argumento) debe ser una instancia de ProtoneMediaLaravelFFMpegFilesystemMedia
. Puede crear una instancia con el método make
, llámelo con el nombre del disco y la ruta (ver ejemplo).
Consulte este ejemplo, que asigna entradas de audio y video separadas en una salida.
FFMpeg::fromDisk('local') ->abrir(['video.mp4', 'audio.m4a']) ->exportar() ->addFormatOutputMapping(nuevo X264, Medios::make('local', 'new_video.mp4'), ['0:v', '1:a']) ->guardar();
Este es un ejemplo de la biblioteca subyacente:
// Este código toma 2 videos de entrada, los apila horizontalmente en 1 video de salida y// agrega a este nuevo video el audio del primer video. (Es imposible // con un gráfico de filtro simple que tiene solo 1 entrada y solo 1 salida). FFMpeg::fromDisk('local') ->abrir(['video.mp4', 'video2.mp4']) ->exportar() ->addFilter('[0:v][1:v]', 'hstack', '[v]') // $entrada, $parámetros, $salida->addFormatOutputMapping(nuevo X264, Media::make(' local', 'stacked_video.mp4'), ['0:a', '[v]']) ->guardar();
Al igual que las entradas individuales, también puedes pasar una devolución de llamada al método addFilter
. Esto le dará una instancia de FFMpegFiltersAdvancedMediaComplexFilters
:
utilice FFMpegFiltersAdvancedMediaComplexFilters; FFMpeg::open(['video.mp4', 'video2.mp4']) ->exportar() ->addFilter(function(ComplexFilters $filtros) {// $filtros->watermark(...);});
Abrir archivos desde la web funciona de manera similar. Puede pasar una serie de URL al método openUrl
, opcionalmente con encabezados HTTP personalizados.
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', ], ['Autorización' => 'Básico YWRtaW46MTIzNA==', ]);
Si desea utilizar otro conjunto de encabezados HTTP para cada URL, puede encadenar el método openUrl
:
FFMpeg::openUrl('https://videocoursebuilder.com/lesson-5.mp4', ['Autorización' => 'Básico YWRtaW46MTIzNA==', ])->openUrl('https://videocoursebuilder.com/lesson-6.mp4', ['Autorización' => 'bmltZGE6NDMyMQ==', ]);
FFMpeg::fromDisk('local') ->abrir(['video.mp4', 'video2.mp4']) ->exportar() ->concatSinTranscodificación() ->guardar('concat.mp4');
FFMpeg::fromDisk('local') ->abrir(['video.mp4', 'video2.mp4']) ->exportar() ->inFormat(nuevo X264) ->concatWithTranscoding($hasVideo = verdadero, $hasAudio = verdadero) ->guardar('concat.mp4');
Con la clase Media
puedes determinar la duración de un archivo:
$media = FFMpeg::open('wwdc_2006.mp4');$durationInSeconds = $media->getDurationInSeconds(); // devuelve un int$durationInMilisegundos = $media->getDuraciónInMilisegundos(); // devuelve un flotador
Al abrir o guardar archivos desde o hacia un disco remoto, se crearán archivos temporales en su servidor. Una vez que haya terminado de exportar o procesar estos archivos, puede limpiarlos llamando al método cleanupTemporaryFiles()
:
FFMpeg::cleanupTemporaryFiles();
De forma predeterminada, la raíz de los directorios temporales se evalúa mediante el método sys_get_temp_dir()
de PHP, pero puede modificarla configurando la clave de configuración temporary_files_root
en una ruta personalizada.
Puede crear una lista de reproducción M3U8 para hacer HLS.
$lowBitrate = (nuevo X264)->setKiloBitrate(250);$midBitrate = (nuevo X264)->setKiloBitrate(500);$highBitrate = (nuevo X264)->setKiloBitrate(1000); FFMpeg::fromDisk('vídeos') ->abrir('steve_howe.mp4') ->exportarParaHLS() ->setSegmentLength(10) // opcional->setKeyFrameInterval(48) // opcional->addFormat($lowBitrate) ->añadirFormato($tasa de bits media) ->añadirFormato($alta tasa de bits) ->save('adaptive_steve.m3u8');
El método addFormat
del exportador HLS toma un segundo parámetro opcional que puede ser un método de devolución de llamada. Esto le permite agregar diferentes filtros por formato. Primero, consulte la sección Múltiples entradas para comprender cómo se manejan los filtros complejos.
Puede utilizar el método addFilter
para agregar un filtro complejo (consulte el ejemplo de $lowBitrate
). Dado que el filtro scale
se usa mucho, existe un método auxiliar (consulte el ejemplo de $midBitrate
). También puede utilizar un elemento invocable para obtener acceso a la instancia ComplexFilters
. El paquete proporciona los argumentos $in
y $out
para que no tenga que preocuparse por ello (consulte el ejemplo $highBitrate
).
La exportación HLS se crea utilizando las funciones map
y filter_complex
de FFMpeg. Este es un cambio importante con respecto a versiones anteriores (1.x - 6.x) que realizaban una única exportación para cada formato. Si está actualizando, reemplace las llamadas addFilter
con llamadas addLegacyFilter
y verifique el resultado (consulte el ejemplo de $superBitrate
). No todos los filtros funcionarán de esta manera y algunos deben actualizarse manualmente.
$lowBitrate = (nuevo X264)->setKiloBitrate(250);$midBitrate = (nuevo X264)->setKiloBitrate(500);$highBitrate = (nuevo X264)->setKiloBitrate(1000);$superBitrate = (nuevo X264)- >establecer KiloBitrate(1500); FFMpeg::open('steve_howe.mp4') ->exportarParaHLS() ->addFormat($lowBitrate, function($media) {$media->addFilter('scale=640:480'); }) ->addFormat($midBitrate, function($medios) {$medios->escala(960, 720); }) ->addFormat($highBitrate, función ($medios) {$medios->addFilter(función ($filtros, $entrada, $salida) {$filtros->personalizado($entrada, 'escala=1920:1200', $salida ); // $entrada, $parámetros, $salida}); }) ->addFormat($superBitrate, function($media) {$media->addLegacyFilter(function ($filters) {$filters->resize(new FFMpegCoordinateDimension(2560, 1920)); }); }) ->save('adaptive_steve.m3u8');
Puede utilizar un patrón personalizado para nombrar los segmentos y las listas de reproducción. useSegmentFilenameGenerator
le proporciona 5 argumentos. El primer, segundo y tercer argumento proporcionan información sobre el nombre base de la exportación, el formato de la iteración actual y la clave de la iteración actual. El cuarto argumento es una devolución de llamada que debes llamar con tu patrón de segmentos . El quinto argumento es una devolución de llamada que debes llamar con tu patrón de lista de reproducción . Tenga en cuenta que este no es el nombre de la lista de reproducción principal, sino el nombre de la lista de reproducción de cada formato.
FFMpeg::fromDisk('vídeos') ->abrir('steve_howe.mp4') ->exportarParaHLS() ->useSegmentFilenameGenerator(función ($nombre, $formato, $clave, $segmentos invocables, $lista de reproducción invocable) {$segmentos("{$nombre}-{$formato->getKiloBitrate()}-{$clave}-%03d .ts");$playlist("{$nombre}-{$formato->getKiloBitrate()}-{$clave}.m3u8"); });
Puede cifrar cada segmento HLS mediante cifrado AES-128. Para hacer esto, llame al método withEncryptionKey
en el exportador HLS con una clave. Proporcionamos un método auxiliar generateEncryptionKey
en la clase HLSExporter
para generar una clave. Asegúrese de almacenar bien la clave, ya que el resultado exportado no tiene valor sin la clave. De forma predeterminada, el nombre de archivo de la clave es secret.key
, pero puede cambiarlo con el segundo parámetro opcional del método withEncryptionKey
.
utilice ProtoneMediaLaravelFFMpegExportersHLSExporter;$encryptionKey = HLSExporter::generateEncryptionKey(); FFMpeg::open('steve_howe.mp4') ->exportarParaHLS() ->conClave de cifrado($Clave de cifrado) ->añadirFormato($tasa de bits baja) ->añadirFormato($tasa de bits media) ->añadirFormato($alta tasa de bits) ->save('adaptive_steve.m3u8');
Para asegurar aún más su exportación HLS, puede rotar la clave en cada segmento exportado. Al hacerlo, generará múltiples claves que deberás almacenar. Utilice el método withRotatingEncryptionKey
para habilitar esta función y proporcionar una devolución de llamada que implemente el almacenamiento de las claves.
FFMpeg::open('steve_howe.mp4') ->exportarParaHLS() ->withRotatingEncryptionKey(function ($filename, $contents) {$videoId = 1;// use esta devolución de llamada para almacenar las claves de cifradoStorage::disk('secrets')->put($videoId . '/' . $filename, $contents);// o...DB::table('hls_secrets')->insert(['video_id' => $videoId,'filename' => $nombre de archivo,'contenido' => $contenido, ]); }) ->añadirFormato($tasa de bits baja) ->añadirFormato($tasa de bits media) ->añadirFormato($alta tasa de bits) ->save('adaptive_steve.m3u8');
El método withRotatingEncryptionKey
tiene un segundo argumento opcional para establecer el número de segmentos que utilizan la misma clave. El valor predeterminado es 1
.
FFMpeg::open('steve_howe.mp4') ->exportarParaHLS() ->withRotatingEncryptionKey($invocable, 10);
Algunos sistemas de archivos, especialmente en VPS baratos y lentos, no son lo suficientemente rápidos para manejar la clave giratoria. Esto puede provocar excepciones de codificación, como No key URI specified in key info file
. Una posible solución es utilizar un almacenamiento diferente para las claves, que puede especificar mediante la clave de configuración temporary_files_encrypted_hls
. En sistemas basados en UNIX, puede utilizar un sistema de archivos tmpfs
para aumentar las velocidades de lectura/escritura:
// config/laravel-ffmpeg.phpreturn ['temporary_files_encrypted_hls' => '/dev/shm'];
Para mejorar aún más el trabajo con HLS cifrado, agregamos una clase DynamicHLSPlaylist
que modifica las listas de reproducción sobre la marcha y específicamente para su aplicación. De esta manera, puede agregar su lógica de autenticación y autorización. Como usamos un controlador Laravel simple, puedes usar funciones como Gates y Middleware.
En este ejemplo, guardamos la exportación HLS en el disco public
y almacenamos las claves de cifrado en el disco secrets
, que no está disponible públicamente. Como el navegador no puede acceder a las claves de cifrado, no reproducirá el vídeo. Cada lista de reproducción tiene rutas a las claves de cifrado y debemos modificar esas rutas para que apunten a un punto final accesible.
Esta implementación consta de dos rutas. Uno que responde con una clave de cifrado y otro que responde con una lista de reproducción modificada. La primera ruta ( video.key
) es relativamente simple y aquí es donde debes agregar tu lógica adicional.
La segunda ruta ( video.playlist
) utiliza la clase DynamicHLSPlaylist
. Llame al método dynamicHLSPlaylist
en la fachada FFMpeg
y, de manera similar a abrir archivos multimedia, puede abrir una lista de reproducción utilizando los métodos fromDisk
y open
. Luego debes proporcionar tres devoluciones de llamada. Cada uno de ellos le proporciona un camino relativo y espera un camino completo a cambio. Como la clase DynamicHLSPlaylist
implementa la interfaz IlluminateContractsSupportResponsable
, puede devolver la instancia.
La primera devolución de llamada (KeyUrlResolver) le proporciona la ruta relativa a una clave de cifrado. La segunda devolución de llamada (MediaUrlResolver) le proporciona la ruta relativa a un segmento multimedia (archivos .ts). La tercera devolución de llamada (PlaylistUrlResolver) le proporciona la ruta relativa a una lista de reproducción.
Ahora, en lugar de usar Storage::disk('public')->url('adaptive_steve.m3u8')
para obtener la URL completa de su lista de reproducción principal, puede usar route('video.playlist', ['playlist' => 'adaptive_steve.m3u8'])
. La clase DynamicHLSPlaylist
se encarga de todas las rutas y URL.
Ruta::get('/video/secret/{clave}', función ($clave) {return Almacenamiento::disco('secretos')->descargar($clave); })->nombre('video.clave'); Ruta::get('/video/{lista de reproducción}', función ($lista de reproducción) {return FFMpeg::dynamicHLSPlaylist() ->desdeDisco('público') ->abrir($lista de reproducción) ->setKeyUrlResolver(función ($clave) {ruta de retorno('video.key', ['clave' => $clave]); }) ->setMediaUrlResolver(function ($mediaFilename) {return Storage::disk('public')->url($mediaFilename); }) ->setPlaylistUrlResolver(function ($playlistFilename) {ruta de retorno('video.playlist', ['playlist' => $playlistFilename]); }); })->nombre('video.lista de reproducción');
Aquí puede encontrar una sesión de codificación en vivo sobre cifrado HLS:
https://www.youtube.com/watch?v=WlbzWoAcez4
Puede obtener el resultado del proceso sin procesar llamando al método getProcessOutput
. Aunque el caso de uso es limitado, puede usarlo para analizar un archivo (por ejemplo, con el filtro volumedetect
). Devuelve una clase ProtoneMediaLaravelFFMpegSupportProcessOutput
que tiene tres métodos: all
, errors
y output
. Cada método devuelve una matriz con las líneas correspondientes.
$procesoSalida = FFMpeg::open('video.mp4') ->exportar() ->addFilter(['-filtro:a', 'volumedetect', '-f', 'nulo']) ->getProcessOutput();$processOutput->all();$processOutput->errores();$processOutput->out();
El objeto Media que obtienes cuando "abres" un archivo, en realidad contiene el objeto Media que pertenece al controlador subyacente. Maneja llamadas a métodos dinámicos como puede ver aquí. De esta manera, todos los métodos del controlador subyacente seguirán disponibles.
// Esto le proporciona una instancia de ProtoneMediaLaravelFFMpegMediaOpener$media = FFMpeg::fromDisk('videos')->open('video.mp4');// El método 'getStreams' se llamará en el objeto Media subyacente desde// no existe en este objeto.$codec = $media->getStreams()->first()->get('codec_name');
Si desea acceso directo al objeto subyacente, llame al objeto como una función (invoque):
// Esto le proporciona una instancia de ProtoneMediaLaravelFFMpegMediaOpener$media = FFMpeg::fromDisk('videos')->open('video.mp4');// Esto le proporciona una instancia de FFMpegMediaMediaTypeInterface$baseMedia = $media();
El detector de progreso expone el porcentaje transcodificado, pero el paquete subyacente también tiene un AbstractProgressListener
interno que expone el paso actual y la hora actual. Aunque el caso de uso es limitado, es posible que desee obtener acceso a esta instancia de escucha. Puedes hacer esto decorando el formato con ProgressListenerDecorator
. Esta característica es altamente experimental, así que asegúrese de probarla minuciosamente antes de usarla en producción.
use FFMpegFormatProgressListenerAbstractProgressListener;use ProtoneMediaLaravelFFMpegFFMpegProgressListenerDecorator;$format = new FFMpegFormatVideoX264;$decoratedFormat = ProgressListenerDecorator::decorate($format); FFMpeg::open('vídeo.mp4') ->exportar() ->enFormato($formatodecorado) ->onProgress(function () use ($decoratedFormat) {$oyentes = $decoratedFormat->getListeners(); // matriz de oyentes$listener = $listeners[0]; // instancia de AbstractProgressListener$listener->getCurrentPass() ;$escucha->getTotalPass();$escucha->getCurrentTime(); }) ->guardar('nuevo_video.mp4');
Como no podemos deshacernos de algunas de las opciones subyacentes, puede interactuar con el comando FFmpeg final agregando una devolución de llamada al exportador. Puede agregar una o más devoluciones de llamada utilizando el método beforeSaving
:
FFMpeg::open('vídeo.mp4') ->exportar() ->inFormat(nuevo X264) ->beforeSaving(función ($comandos) {$comandos[] = '-hola';return $comandos; }) ->guardar('concat.mp4');
Nota: esto no funciona con concatenación y exportaciones de cuadros.
Aquí hay una publicación de blog que lo ayudará a comenzar con este paquete:
https://protone.media/en/blog/how-to-use-ffmpeg-in-your-laravel-projects
A continuación se ofrece una descripción general de 20 minutos sobre cómo empezar a utilizar Video.js. Cubre la inclusión de Video.js desde una CDN, su importación como un módulo ES6 con Laravel Mix (Webpack) y la construcción de un componente Vue.js reutilizable.
https://www.youtube.com/watch?v=nA1Jy8BPjys
Filtros personalizados
FFmpeg no pudo ejecutar el comando
Obtener las dimensiones de un archivo de vídeo
Supervisión del progreso de la transcodificación
No se puede cargar FFProbe
Consulte CHANGELOG para obtener más información sobre los cambios recientes.
$ prueba de compositor
Consulte CONTRIBUCIÓN para obtener más detalles.
Inertia Table
: la tabla definitiva para Inertia.js con Query Builder integrado.
Laravel Blade On Demand
: Paquete Laravel para compilar plantillas Blade en memoria.
Laravel Cross Eloquent Search
: paquete Laravel para buscar en múltiples modelos Eloquent.
Laravel Eloquent Scope as Select
: deje de duplicar los alcances y restricciones de sus consultas de Eloquent en PHP. Este paquete le permite reutilizar los alcances y restricciones de su consulta agregándolos como una subconsulta.
Laravel MinIO Testing Tools
: ejecute sus pruebas en un servidor MinIO S3.
Laravel Mixins
: una colección de delicias de Laravel.
Laravel Paddle
: integración de la API de Paddle.com para Laravel con soporte para webhooks/eventos.
Laravel Task Runner
: escriba scripts de Shell como Blade Components y ejecútelos localmente o en un servidor remoto.
Laravel Verify New Email
: este paquete agrega soporte para verificar nuevas direcciones de correo electrónico: cuando un usuario actualiza su dirección de correo electrónico, no reemplazará la anterior hasta que se verifique la nueva.
Laravel XSS Protection
: Laravel Middleware para proteger su aplicación contra secuencias de comandos entre sitios (XSS). Limpia la entrada de solicitudes y puede limpiar las declaraciones de eco de Blade.
Si descubre algún problema relacionado con la seguridad, envíe un correo electrónico a [email protected] en lugar de utilizar el rastreador de problemas. No envíe preguntas por correo electrónico; abra un problema si tiene alguna pregunta.
Pascal Baljet
Todos los contribuyentes
La Licencia MIT (MIT). Consulte el archivo de licencia para obtener más información.