该包为 Laravel 10 提供了与 FFmpeg 的集成。Laravel 的文件系统处理文件的存储。
我们很自豪通过开发 Laravel 包并免费赠送来支持社区。如果该软件包可以节省您的时间或者您在专业上依赖它,请考虑赞助维护和开发并查看我们最新的高级软件包:惯性表。跟踪问题和拉取请求需要时间,但我们很乐意提供帮助!
PHP-FFMpeg 的超级简单包装,包括对过滤器和其他高级功能的支持。
与 Laravel 的文件系统、配置系统和日志处理集成。
兼容 Laravel 10,支持包发现。
对 HLS 的内置支持。
内置支持加密 HLS (AES-128) 和轮换密钥(可选)。
内置支持串联、多个输入/输出、图像序列(延时)、复杂过滤器(和映射)、帧/缩略图导出。
内置支持水印(定位和操作)。
内置支持从视频创建马赛克/精灵/图块。
内置支持生成VTT 预览缩略图文件。
需要 PHP 8.1 或更高版本。
使用 FFmpeg 4.4 和 5.0 进行测试。
验证您是否安装了最新版本的 FFmpeg:
ffmpeg-版本
您可以通过 Composer 安装该软件包:
作曲家需要 pbmedia/laravel-ffmpeg
如果您不使用 Package Discovery,请将服务提供程序和 Facade 添加到您的app.php
配置文件中。
// config/app.php'providers' => [ ...ProtoneMediaLaravelFFMpegSupportServiceProvider::类, ... ];'别名' => [ ...'FFMpeg' => ProtoneMediaLaravelFFMpegSupportFFMpeg::class ... ];
使用 artisan CLI 工具发布配置文件:
php artisan 供应商:发布 --provider="ProtoneMediaLaravelFFMpegSupportServiceProvider"
set_command_and_error_output_on_exception
配置键现在默认为true
,使异常提供更多信息。请阅读处理异常部分了解更多信息。
enable_logging
配置键已被log_channel
取代,用于选择将消息写入日志时使用的日志通道。如果您仍然想完全禁用日志记录,可以将新的配置键设置为false
。
HLS导出的段长度和关键帧间隔应为2
或更大; less 不再支持。
由于 Laravel 9 已从 Flysystem 1.x 迁移到 3.x,因此该版本与 Laravel 8 或更早版本不兼容。
如果您使用水印处理功能,请确保将spatie/image
升级到 v2。
命名空间已更改为ProtoneMediaLaravelFFMpeg
,外观已重命名为ProtoneMediaLaravelFFMpegSupportFFMpeg
,服务提供商已重命名为ProtoneMediaLaravelFFMpegSupportServiceProvider
。
仍然支持链接导出,但您必须为每个导出重新应用过滤器。
HLS 播放列表现在包括比特率、帧率和分辨率数据。这些段还使用新的命名模式(了解更多)。请验证您的导出在您的播放器中是否仍然有效。
HLS 导出现在作为一项作业执行,而不是单独导出每种格式/流。这使用了 FFMpeg 的map
和filter_complex
功能。将所有对addFilter
调用替换为addLegacyFilter
可能就足够了,但某些过滤器应手动迁移。请阅读 HLS 文档以了解有关添加过滤器的更多信息。
转换音频或视频文件:
FFMpeg::fromDisk('歌曲') ->打开('昨天.mp3') -> 导出() ->toDisk('converted_songs') ->inFormat(新 FFMpegFormatAudioAac) ->保存('昨天.aac');
除了fromDisk()
方法,您还可以使用fromFilesystem()
方法,其中$filesystem
是IlluminateContractsFilesystemFilesystem
的实例。
$media = FFMpeg::fromFilesystem($filesystem)->open('yesterday.mp3');
您可以监控转码进度。使用onProgress
方法提供回调,为您提供完成的百分比。在此包的早期版本中,您必须将回调传递给格式对象。
FFMpeg::open('steve_howe.mp4') ->导出() ->onProgress(function ($percentage) {echo "{$percentage}% 转码"; });
回调还可能公开$remaining
(以秒为单位)和$rate
:
FFMpeg::open('steve_howe.mp4') ->导出() ->onProgress(function ($percentage, $remaining, $rate) {echo "{$remaining} 秒剩余速率:{$rate}"; });
您可以直接从Request
实例打开上传的文件。最好先保存上传的文件,以防请求中止,但如果您愿意,可以打开一个UploadedFile
实例:
上传视频控制器类 {公共函数__invoke(请求$请求) { FFMpeg::open($request->file('video')); } }
您可以使用openUrl
方法从 Web 打开文件。您可以使用可选的第二个参数指定自定义 HTTP 标头:
FFMpeg::openUrl('https://videocoursebuilder.com/lesson-1.mp4'); FFMpeg::openUrl('https://videocoursebuilder.com/lesson-2.mp4', ['授权' => '基本 YWRtaW46MTIzNA==', ]);
当编码失败时,应抛出ProtoneMediaLaravelFFMpegExportersEncodingException
,该异常扩展了底层FFMpegExceptionRuntimeException
类。此类有两种方法可以帮助您识别问题。使用getCommand
方法,您可以获得执行的命令及其所有参数。 getErrorOutput
方法为您提供完整的输出日志。
在此软件包的早期版本中,异常消息始终为Encoding failed 。您可以通过将set_command_and_error_output_on_exception
配置键更新为false
来降级到此消息。
尝试 { FFMpeg::open('昨天.mp3') ->导出() ->inFormat(新 Aac) ->保存('昨天.aac'); } catch (EncodingException $异常) {$command = $异常->getCommand();$errorLog = $异常->getErrorOutput(); }
您可以通过Closure
或使用 PHP-FFMpeg 的 Filter 对象添加过滤器:
使用 FFMpegFiltersVideoVideoFilters; FFMpeg::fromDisk('视频') ->打开('steve_howe.mp4') ->addFilter(function (VideoFilters $filters) {$filters->resize(new FFMpegCooperativeDimension(640, 480)); }) ->导出() ->toDisk('converted_videos') ->inFormat(新 FFMpegFormatVideoX264) ->save('small_steve.mkv');// 或$start = FFMpegCooperativeTimeCode::fromSeconds(5)$clipFilter = new FFMpegFiltersVideoClipFilter($start); FFMpeg::fromDisk('视频') ->打开('steve_howe.mp4') ->addFilter($clipFilter) ->导出() ->toDisk('converted_videos') ->inFormat(新 FFMpegFormatVideoX264) ->保存('short_steve.mkv');
您还可以在export
方法之后调用addFilter
方法:
使用 FFMpegFiltersVideoVideoFilters; FFMpeg::fromDisk('视频') ->打开('steve_howe.mp4') ->导出() ->toDisk('converted_videos') ->inFormat(新 FFMpegFormatVideoX264) ->addFilter(function (VideoFilters $filters) {$filters->resize(new FFMpegCooperativeDimension(640, 480)); }) ->保存('small_steve.mkv');
由于调整大小是一个常见的操作,我们为其添加了一个专用的方法:
FFMpeg::open('steve_howe.mp4') ->导出() ->inFormat(新 FFMpegFormatVideoX264) ->调整大小(640, 480) ->保存('steve_howe_resized.mp4');
第一个参数是宽度,第二个参数是高度。可选的第三个参数是模式。您可以在fit
(默认)、 inset
、 width
或height
之间进行选择。可选的第四个参数是一个布尔值,是否强制使用标准比率。您可以在FFMpegFiltersVideoResizeFilter
类中找到有关这些模式的信息。
有时您不想使用内置过滤器。您可以通过提供一组选项来应用您自己的过滤器。这可以是一个数组或多个字符串作为参数:
FFMpeg::fromDisk('视频') ->打开('steve_howe.mp4') ->addFilter(['-itsoffset', 1]);// 或FFMpeg::fromDisk('videos') ->打开('steve_howe.mp4') ->addFilter('-itsoffset', 1);
您可以使用addWatermark
方法轻松添加水印。使用WatermarkFactory
,您可以从特定磁盘打开水印文件,就像打开音频或视频文件一样。当您放弃fromDisk
方法时,它会使用filesystems.php
配置文件中指定的默认磁盘。
打开水印文件后,您可以使用top
、 right
、 bottom
和left
方法对其进行定位。这些方法的第一个参数是偏移量,它是可选的并且可以是负数。
使用 ProtoneMediaLaravelFFMpegFiltersWatermarkFactory; FFMpeg::fromDisk('视频') ->打开('steve_howe.mp4') ->addWatermark(function(WatermarkFactory $watermark) {$watermark->fromDisk('local') ->打开('标志.png') ->右(25) ->底部(25); });
除了使用位置方法之外,您还可以使用horizontalAlignment
和verticalAlignment
方法。
对于水平对齐,您可以使用WatermarkFactory::LEFT
、 WatermarkFactory::CENTER
和WatermarkFactory::RIGHT
常量。对于垂直对齐,您可以使用WatermarkFactory::TOP
、 WatermarkFactory::CENTER
和WatermarkFactory::BOTTOM
常量。两种方法都采用可选的第二个参数,即偏移量。
FFMpeg::open('steve_howe.mp4') ->addWatermark(function(WatermarkFactory $watermark) {$watermark->open('logo.png') ->horizontalAlignment(WatermarkFactory::LEFT, 25) ->verticalAlignment(WatermarkFactory::TOP, 25); });
WatermarkFactory
还支持使用openUrl
方法从 Web 打开文件。它还支持自定义 HTTP 标头。
FFMpeg::open('steve_howe.mp4') ->addWatermark(function(WatermarkFactory $watermark) {$watermark->openUrl('https://videocoursebuilder.com/logo.png');// 或 $watermark->openUrl('https://videocoursebuilder.com/ logo.png', ['授权' => '基本 YWRtaW46MTIzNA==', ]); });
如果您想要对 GET 请求进行更多控制,可以传入可选的第三个参数,该参数为您提供 Curl 资源。
$watermark->openUrl('https://videocoursebuilder.com/logo.png', ['授权' => '基本 YWRtaW46MTIzNA==', ], 函数($curl) {curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 0);curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, 0); });
该包可以通过使用 Spatie 的 Image 包来操作水印。首先,使用 Composer 安装该软件包:
作曲家需要空间/图像
现在您可以在WatermarkFactory
实例上再链接一种操作方法:
FFMpeg::open('steve_howe.mp4') ->addWatermark(function(WatermarkFactory $watermark) {$watermark->open('logo.png') ->右(25) ->底部(25) ->宽度(100) ->高度(100) ->灰度(); });
查看文档以了解所有可用的方法。
该包附带ProtoneMediaLaravelFFMpegFFMpegCopyFormat
类,允许您导出文件而无需对流进行转码。您可能想使用它来使用另一个容器:
使用 ProtoneMediaLaravelFFMpegFFMpegCopyFormat; FFMpeg::open('视频.mp4') ->导出() ->inFormat(新的CopyFormat) ->保存('视频.mkv');
// 不需要“fromDisk()”方法,文件现在将从默认“磁盘”打开, // 配置文件中指定。FFMpeg::open('my_movie.mov')//导出到FTP,转换为WMV->export() ->toDisk('ftp') ->inFormat(新 FFMpegFormatVideoWMV) ->save('my_movie.wmv')//导出到Amazon S3,在X264中转换->export() ->toDisk('s3') ->inFormat(新 FFMpegFormatVideoX264) ->save('my_movie.mkv');// 你甚至可以放弃 'toDisk()' 方法,// 现在转换后的文件将被保存到 // 与源相同的磁盘!->export() ->inFormat(新 FFMpegFormatVideoWebM) ->save('my_movie.webm')// 您可以选择设置导出文件的可见性//->export() ->inFormat(新 FFMpegFormatVideoWebM) ->withVisibility('公开') ->保存('my_movie.webm')
FFMpeg::fromDisk('视频') ->打开('steve_howe.mp4') ->getFrameFromSeconds(10) ->导出() ->toDisk('缩略图') ->save('FrameAt10sec.png');// 除了使用 'getFrameFromSeconds()' 方法,您还可以使用 'getFrameFromString()' 或 // 'getFrameFromTimecode()' 方法:$media = FFMpeg ::open('steve_howe.mp4');$frame = $media->getFrameFromString('00:00:13.37');// 或$timecode = new FFMpegCooperativeTimeCode(...);$frame = $media->getFrameFromTimecode($timecode);
您还可以获取帧的原始内容,而不是将其保存到文件系统:
$contents = FFMpeg::open('video.mp4') ->getFrameFromSeconds(2) ->导出() ->getFrameContents();
有一个TileFilter
可以支持 Tile 功能。为了使导出多个帧更快、更简单,我们利用此功能添加了一些辅助方法。例如,您可以使用exportFramesByInterval
方法按固定间隔导出帧。或者,您可以将要导出的帧数传递给exportFramesByAmount
方法,然后该方法将根据视频的持续时间计算间隔。
FFMpeg::open('视频.mp4') ->exportFramesByInterval(2) ->保存('thumb_%05d.jpg');
两种方法都接受可选的第二个和第三个参数来指定框架的宽度和高度。您也可以只传递其中之一,而不是同时传递宽度和高度。 FFmpeg 将尊重源的宽高比。
FFMpeg::open('视频.mp4') ->exportFramesByAmount(10, 320, 180) ->保存('thumb_%05d.png');
当您导出为有损格式(如 JPEG)时,这两种方法都接受可选的第四个参数来指定图像的质量。 JPEG 的范围是2-31
,其中2
是最好的质量, 31
是最差的。
FFMpeg::open('视频.mp4') ->exportFramesByInterval(2, 640, 360, 5) ->保存('thumb_%05d.jpg');
您可以从视频创建图块。您可以调用exportTile
方法来指定应如何生成图块。在下面的示例中,每个生成的图像由 3x5 网格组成(因此包含 15 帧),每帧为 160x90 像素。视频中每 5 秒拍摄一帧。您也可以只传递其中之一,而不是同时传递宽度和高度。 FFmpeg 将尊重源的宽高比。
使用 ProtoneMediaLaravelFFMpegFiltersTileFactory; FFMpeg::open('steve_howe.mp4') ->exportTile(函数 (TileFactory $factory) {$factory->interval(5) ->规模(160, 90) ->网格(3, 5); }) ->保存('tile_%05d.jpg');
您也可以只传递其中之一,例如scale(160)
或scale(null, 90)
,而不是同时传递宽度和高度。将尊重宽高比。 TileFactory
也有margin
、 padding
、 width
和height
方法。还有一种quality
方法可以指定导出为有损格式(如 JPEG)时的质量。 JPEG 的范围是2-31
,其中2
是最好的质量, 31
是最差的。
该软件包还可以生成 WebVTT 文件以将预览缩略图添加到您的视频播放器。 JW 播放器对此提供开箱即用的支持,并且还有社区驱动的 Video.js 插件可用。您可以使用所需的文件名调用TileFactory
上的generateVTT
方法:
FFMpeg::open('steve_howe.mp4') ->exportTile(函数(TileFactory $factory) {$factory->间隔(10) ->规模(320, 180) ->网格(5, 5) ->generateVTT('缩略图.vtt'); }) ->保存('tile_%05d.jpg');
链接多个转换是有效的,因为MediaExporter
的save
方法返回MediaOpener
的新实例。您可以使用它来循环浏览项目,例如从一个视频导出多个帧:
$mediaOpener = FFMpeg::open('video.mp4');foreach ([5, 15, 25] as $key => $seconds) {$mediaOpener = $mediaOpener->getFrameFromSeconds($seconds) ->导出() ->保存(“thumb_{$key}.png”); }
MediaOpener
还附带了each
方法。上面的例子可以重构如下:
FFMpeg::open('video.mp4')->each([5, 15, 25], function ($ffmpeg, $seconds, $key) {$ffmpeg->getFrameFromSeconds($seconds)->export()- >保存(“thumb_{$key}.png”); });
您可以使用导出器上的asTimelapseWithFramerate
方法从一系列图像创建延时摄影
FFMpeg::open('feature_%04d.png') -> 导出() ->asTimelapseWithFramerate(1) ->inFormat(新X264) ->保存('timelapse.mp4');
您可以打开多个输入,甚至可以从不同的磁盘打开。这使用了 FFMpeg 的map
和filter_complex
功能。您可以通过使用数组链接open
方法来打开多个文件。您可以混合来自不同磁盘的输入。
FFMpeg::open('video1.mp4')->open('video2.mp4'); FFMpeg::open(['video1.mp4', 'video2.mp4']); FFMpeg::fromDisk('上传') ->打开('video1.mp4') ->fromDisk('存档') ->打开('video2.mp4');
当您打开多个输入时,您必须添加映射,以便 FFMpeg 知道如何路由它们。该包提供了addFormatOutputMapping
方法,该方法采用三个参数:格式、输出以及-filter_complex
部分的输出标签。
输出(第二个参数)应该是ProtoneMediaLaravelFFMpegFilesystemMedia
的实例。您可以使用make
方法实例化,并使用磁盘名称和路径调用它(请参阅示例)。
查看此示例,它将单独的视频和音频输入映射到一个输出。
FFMpeg::fromDisk('本地') ->open(['video.mp4', 'audio.m4a']) ->导出() ->addFormatOutputMapping(new X264, Media::make('local', 'new_video.mp4'), ['0:v', '1:a']) ->保存();
这是底层库的示例:
// 此代码采用 2 个输入视频,将它们水平堆叠在 1 个输出视频中,并且// 将第一个视频中的音频添加到这个新视频中。 (这是不可能的 // 使用只有 1 个输入和 1 个输出的简单过滤器图).FFMpeg::fromDisk('local') ->open(['video.mp4', 'video2.mp4']) ->导出() ->addFilter('[0:v][1:v]', 'hstack', '[v]') // $in, $parameters, $out->addFormatOutputMapping(new X264, Media::make('本地', 'stacked_video.mp4'), ['0:a', '[v]']) ->保存();
就像单个输入一样,您也可以将回调传递给addFilter
方法。这将为您提供一个FFMpegFiltersAdvancedMediaComplexFilters
实例:
使用 FFMpegFiltersAdvancedMediaComplexFilters; FFMpeg::open(['video.mp4', 'video2.mp4']) ->导出() ->addFilter(function(ComplexFilters $filters) {// $filters->watermark(...);});
从网络打开文件的工作原理类似。您可以将 URL 数组传递给openUrl
方法,还可以选择使用自定义 HTTP 标头。
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', ], ['授权' => '基本 YWRtaW46MTIzNA==', ]);
如果您想为每个 URL 使用另一组 HTTP 标头,您可以链接openUrl
方法:
FFMpeg::openUrl('https://videocoursebuilder.com/lesson-5.mp4', ['授权' => '基本 YWRtaW46MTIzNA==', ])->openUrl('https://videocoursebuilder.com/lesson-6.mp4', ['授权' => '基础 bmltZGE6NDMyMQ==', ]);
FFMpeg::fromDisk('本地') ->open(['video.mp4', 'video2.mp4']) ->导出() ->concatWithoutTranscoding() ->保存('concat.mp4');
FFMpeg::fromDisk('本地') ->open(['video.mp4', 'video2.mp4']) -> 导出() ->inFormat(新X264) ->concatWithTranscoding($hasVideo = true, $hasAudio = true) ->保存('concat.mp4');
使用Media
类,您可以确定文件的持续时间:
$media = FFMpeg::open('wwdc_2006.mp4');$durationInSeconds = $media->getDurationInSeconds(); // 返回一个 int$durationInMiliseconds = $media->getDurationInMiliseconds(); // 返回一个浮点数
从远程磁盘打开文件或将文件保存到远程磁盘时,将在您的服务器上创建临时文件。导出或处理完这些文件后,您可以通过调用cleanupTemporaryFiles()
方法来清理它们:
FFMpeg::cleanupTemporaryFiles();
默认情况下,临时目录的根由 PHP 的sys_get_temp_dir()
方法评估,但您可以通过将temporary_files_root
配置键设置为自定义路径来修改它。
您可以创建 M3U8 播放列表来执行 HLS。
$lowBitrate = (新 X264)->setKiloBitrate(250);$midBitrate = (新 X264)->setKiloBitrate(500);$highBitrate = (新 X264)->setKiloBitrate(1000); FFMpeg::fromDisk('视频') ->打开('steve_howe.mp4') ->exportForHLS() ->setSegmentLength(10) // 可选->setKeyFrameInterval(48) // 可选->addFormat($lowBitrate) ->addFormat($midBitrate) ->addFormat($highBitrate) ->保存('adaptive_steve.m3u8');
HLS 导出器的addFormat
方法采用可选的第二个参数,该参数可以是回调方法。这允许您为每种格式添加不同的过滤器。首先,查看多个输入部分以了解如何处理复杂的过滤器。
您可以使用addFilter
方法添加复杂的过滤器(请参阅$lowBitrate
示例)。由于scale
过滤器被大量使用,因此有一个辅助方法(请参阅$midBitrate
示例)。您还可以使用可调用对象来访问ComplexFilters
实例。该包提供了$in
和$out
参数,因此您不必担心它(请参阅$highBitrate
示例)。
HLS 导出是使用 FFMpeg 的map
和filter_complex
功能构建的。这是对早期版本 (1.x - 6.x) 的重大更改,早期版本对每种格式执行一次导出。如果您要升级,请将addFilter
调用替换为addLegacyFilter
调用并验证结果(请参阅$superBitrate
示例)。并非所有过滤器都能以这种方式工作,有些过滤器需要手动升级。
$lowBitrate = (新 X264)->setKiloBitrate(250);$midBitrate = (新 X264)->setKiloBitrate(500);$highBitrate = (新 X264)->setKiloBitrate(1000);$superBitrate = (新 X264)- >设置千比特率(1500); FFMpeg::open('steve_howe.mp4') ->exportForHLS() ->addFormat($lowBitrate, function($media) {$media->addFilter('scale=640:480'); }) ->addFormat($midBitrate, 函数($media) {$media->scale(960, 720); }) ->addFormat($highBitrate, function ($media) {$media->addFilter(function ($filters, $in, $out) {$filters->custom($in, 'scale=1920:1200', $out ); // $输入,$参数,$输出}); }) ->addFormat($superBitrate, function($media) {$media->addLegacyFilter(function ($filters) {$filters->resize(new FFMpegCooperativeDimension(2560, 1920)); }); }) ->保存('adaptive_steve.m3u8');
您可以使用自定义模式来命名片段和播放列表。 useSegmentFilenameGenerator
为您提供 5 个参数。第一个、第二个和第三个参数提供有关导出的基本名称、当前迭代的格式和当前迭代的键的信息。第四个参数是您应该使用段模式调用的回调。第五个参数是您应该使用播放列表模式调用的回调。请注意,这不是主播放列表的名称,而是每种格式的播放列表的名称。
FFMpeg::fromDisk('视频') ->打开('steve_howe.mp4') ->exportForHLS() ->useSegmentFilenameGenerator(function ($name, $format, $key, callable $segments, callable $playlist) {$segments("{$name}-{$format->getKiloBitrate()}-{$key}-%03d .ts");$playlist("{$name}-{$format->getKiloBitrate()}-{$key}.m3u8"); });
您可以使用 AES-128 加密来加密每个 HLS 段。为此,请使用密钥调用 HLS 导出器上的withEncryptionKey
方法。我们在HLSExporter
类上提供了generateEncryptionKey
辅助方法来生成密钥。请确保妥善存储密钥,因为如果没有密钥,导出的结果将毫无价值。默认情况下,密钥的文件名是secret.key
,但您可以使用withEncryptionKey
方法的可选第二个参数进行更改。
使用 ProtoneMediaLaravelFFMpegExportersHLSExporter;$encryptionKey = HLSExporter::generateEncryptionKey(); FFMpeg::open('steve_howe.mp4') ->exportForHLS() ->withEncryptionKey($加密密钥) ->addFormat($lowBitrate) ->addFormat($midBitrate) ->addFormat($highBitrate) ->保存('adaptive_steve.m3u8');
为了进一步保护您的 HLS 导出,您可以轮换每个导出段上的密钥。通过这样做,它将生成您需要存储的多个密钥。使用withRotatingEncryptionKey
方法启用此功能并提供实现密钥存储的回调。
FFMpeg::open('steve_howe.mp4') ->exportForHLS() ->withRotatingEncryptionKey(function ($filename, $contents) {$videoId = 1;// 使用此回调存储加密密钥Storage::disk('secrets')->put($videoId . '/' . $filename, $contents);// 或...DB::table('hls_secrets')->insert(['video_id' => $videoId,'filename' => $文件名,'内容' => $内容, ]); }) ->addFormat($lowBitrate) ->addFormat($midBitrate) ->addFormat($highBitrate) ->保存('adaptive_steve.m3u8');
withRotatingEncryptionKey
方法有一个可选的第二个参数,用于设置使用相同密钥的段数。默认为1
。
FFMpeg::open('steve_howe.mp4') ->exportForHLS() ->withRotatingEncryptionKey($callable, 10);
某些文件系统,尤其是廉价且缓慢的 VPS 上的文件系统,速度不够快,无法处理旋转密钥。这可能会导致编码异常,例如No key URI specified in key info file
。一种可能的解决方案是为密钥使用不同的存储,您可以使用temporary_files_encrypted_hls
配置密钥指定该存储。在基于 UNIX 的系统上,您可以使用tmpfs
文件系统来提高读/写速度:
// config/laravel-ffmpeg.phpreturn ['temporary_files_encrypted_hls' => '/dev/shm'];
为了更好地使用加密的 HLS,我们添加了一个DynamicHLSPlaylist
类,可以专门针对您的应用程序动态修改播放列表。这样,您可以添加身份验证和授权逻辑。由于我们使用普通的 Laravel 控制器,因此您可以使用 Gates 和中间件等功能。
在此示例中,我们已将 HLS 导出保存到public
磁盘,并将加密密钥存储到secrets
磁盘,该磁盘不公开。由于浏览器无法访问加密密钥,因此不会播放视频。每个播放列表都有加密密钥的路径,我们需要修改这些路径以指向可访问的端点。
该实现由两条路线组成。一种使用加密密钥进行响应,另一种使用修改后的播放列表进行响应。第一条路线 ( video.key
) 相对简单,您应该在此处添加额外的逻辑。
第二条路线 ( video.playlist
) 使用DynamicHLSPlaylist
类。调用FFMpeg
外观上的dynamicHLSPlaylist
方法,与打开媒体文件类似,您可以使用fromDisk
和open
方法打开播放列表。然后您必须提供三个回调。他们每个人都给你一个相对路径,并期望一个完整的路径作为回报。由于DynamicHLSPlaylist
类实现IlluminateContractsSupportResponsable
接口,因此您可以返回该实例。
第一个回调 (KeyUrlResolver) 为您提供加密密钥的相对路径。第二个回调 (MediaUrlResolver) 为您提供媒体段(.ts 文件)的相对路径。第三个回调 (PlaylistUrlResolver) 为您提供播放列表的相对路径。
现在,您可以使用 route Storage::disk('public')->url('adaptive_steve.m3u8')
route('video.playlist', ['playlist' => 'adaptive_steve.m3u8'])
。 DynamicHLSPlaylist
类负责处理所有路径和 url。
路线::get('/video/secret/{key}', function ($key) {return Storage::disk('secrets')->download($key); })->name('video.key'); 路线::get('/video/{playlist}', function ($playlist) {return FFMpeg::dynamicHLSPlaylist() ->fromDisk('公共') ->打开($播放列表) ->setKeyUrlResolver(function ($key) {返回路由('video.key', ['key' => $key]); }) ->setMediaUrlResolver(function ($mediaFilename) {return Storage::disk('public')->url($mediaFilename); }) ->setPlaylistUrlResolver(function ($playlistFilename) {返回路由('video.playlist', ['playlist' => $playlistFilename]); }); })->name('video.playlist');
在这里您可以找到有关 HLS 加密的实时编码会话:
https://www.youtube.com/watch?v=WlbzWoAcez4
您可以通过调用getProcessOutput
方法获取原始进程输出。尽管用例有限,但您可以使用它来分析文件(例如,使用volumedetect
过滤器)。它返回一个ProtoneMediaLaravelFFMpegSupportProcessOutput
类,该类具有三个方法: all
、 errors
和output
。每个方法都会返回一个包含相应行的数组。
$processOutput = FFMpeg::open('video.mp4') -> 导出() ->addFilter(['-filter:a', 'volumeDetect', '-f', 'null']) ->getProcessOutput();$processOutput->all();$processOutput->errors();$processOutput->out();
“打开”文件时获得的 Media 对象实际上保存属于底层驱动程序的 Media 对象。正如您在此处看到的,它处理动态方法调用。这样,底层驱动程序的所有方法仍然可供您使用。
// 这为您提供了一个 ProtoneMediaLaravelFFMpegMediaOpener$media = FFMpeg::fromDisk('videos')->open('video.mp4');// 'getStreams' 方法将在底层 Media 对象上调用,因为//该对象上不存在它。$codec = $media->getStreams()->first()->get('codec_name');
如果您想直接访问底层对象,请将该对象作为函数调用(调用):
// 这为您提供了一个 ProtoneMediaLaravelFFMpegMediaOpener$media = FFMpeg::fromDisk('videos')->open('video.mp4');// 这为您提供了一个 FFMpegMediaMediaTypeInterface$baseMedia = $media(); 的实例;
进度侦听器公开转码百分比,但底层包还有一个内部AbstractProgressListener
,它公开当前通道和当前时间。尽管用例有限,但您可能希望访问此侦听器实例。您可以通过使用ProgressListenerDecorator
装饰格式来做到这一点。此功能是高度实验性的,因此请确保在生产中使用它之前进行彻底的测试。
使用 FFMpegFormatProgressListenerAbstractProgressListener;使用 ProtoneMediaLaravelFFMpegFFMpegProgressListenerDecorator;$format = 新 FFMpegFormatVideoX264;$decoratedFormat = ProgressListenerDecorator::decorate($format); FFMpeg::open('视频.mp4') -> 导出() ->inFormat($decoratedFormat) ->onProgress(function () use ($decoratedFormat) {$listeners = $decoratedFormat->getListeners(); // 监听器数组$listener = $listeners[0]; // AbstractProgressListener 实例$listener->getCurrentPass() ;$listener->getTotalPass();$listener->getCurrentTime(); }) ->保存('new_video.mp4');
由于我们无法摆脱一些底层选项,因此您可以通过向导出器添加回调来与最终的 FFmpeg 命令进行交互。您可以使用beforeSaving
方法添加一个或多个回调:
FFMpeg::open('视频.mp4') -> 导出() ->inFormat(新X264) ->beforeSaving(function ($commands) {$commands[] = '-hello';return $commands; }) ->保存('concat.mp4');
注意:这不适用于串联和帧导出
这是一篇博客文章,可帮助您开始使用此软件包:
https://protone.media/en/blog/how-to-use-ffmpeg-in-your-laravel-projects
以下是如何开始使用 Video.js 的 20 分钟概述。它涵盖了从 CDN 包含 Video.js、使用 Laravel Mix (Webpack) 将其作为 ES6 模块导入以及构建可重用的 Vue.js 组件。
https://www.youtube.com/watch?v=nA1Jy8BPjys
定制过滤器
FFmpeg 执行命令失败
获取视频文件的尺寸
监控转码进度
无法加载FFProbe
请参阅变更日志以了解有关最近更改内容的更多信息。
$ 作曲家测试
详细信息请参阅贡献。
Inertia Table
:带有内置查询生成器的 Inertia.js 终极表。
Laravel Blade On Demand
:用于在内存中编译 Blade 模板的 Laravel 包。
Laravel Cross Eloquent Search
:Laravel 包用于搜索多个 Eloquent 模型。
Laravel Eloquent Scope as Select
:停止在 PHP 中重复 Eloquent 查询范围和约束。该包允许您通过将查询范围和约束添加为子查询来重复使用它们。
Laravel MinIO Testing Tools
:针对 MinIO S3 服务器运行测试。
Laravel Mixins
:Laravel 好东西的集合。
Laravel Paddle
:Laravel 的 Paddle.com API 集成,支持 webhooks/事件。
Laravel Task Runner
:编写像 Blade Components 这样的 Shell 脚本并在本地或远程服务器上运行它们。
Laravel Verify New Email
:此包添加了对验证新电子邮件地址的支持:当用户更新其电子邮件地址时,在验证新电子邮件地址之前,它不会替换旧电子邮件地址。
Laravel XSS Protection
:Laravel 中间件可保护您的应用程序免受跨站点脚本(XSS)的侵害。它清理请求输入,并且可以清理 Blade echo 语句。
如果您发现任何与安全相关的问题,请发送电子邮件至 [email protected],而不是使用问题跟踪器。请不要通过电子邮件发送任何问题,如果有问题请提出问题。
帕斯卡·巴尔杰特
所有贡献者
麻省理工学院许可证 (MIT)。请参阅许可证文件以获取更多信息。