From 2e5e04c0913538cc0575898321b747e5c8461203 Mon Sep 17 00:00:00 2001 From: jygaulier Date: Thu, 17 Oct 2024 16:04:37 +0200 Subject: [PATCH] doc ; factorization of common options : timeout, threads) --- lib/php/rendition-factory/README.md | 173 ++++++++++++++++++ .../src/Transformer/Video/FFMpegHelper.php | 29 +++ .../Video/FFMpegTransformerModule.php | 15 +- .../Video/VideoSummaryTransformerModule.php | 3 +- .../VideoToAnimationTransformerModule.php | 3 +- .../Video/VideoToFrameTransformerModule.php | 2 +- 6 files changed, 208 insertions(+), 17 deletions(-) create mode 100644 lib/php/rendition-factory/README.md create mode 100644 lib/php/rendition-factory/src/Transformer/Video/FFMpegHelper.php diff --git a/lib/php/rendition-factory/README.md b/lib/php/rendition-factory/README.md new file mode 100644 index 000000000..3dd2347c6 --- /dev/null +++ b/lib/php/rendition-factory/README.md @@ -0,0 +1,173 @@ +# Rendition Factory for video-input modules (wip) + +## Common options + +### `enabled` (optional) + +Used to disable a whole module from the build chain. + +__default__: true + +### `format` (mandatory) + +A format defines the output file : +- family (image, video, audio, animation, document, unknown) +- mime type (unique mime type for this type of file) +- extension (possible extenstion(s) for this type of file) + +For a specific module, only a subset of formats may be available, e.g.: +Since `video_to_frame` extracts one image from the video, the only supported output format(s) +are ones of family=image. + +see below "Output formats" for the list of available formats. + +### `extension` (optional) + +For the file formats that support multiple extensions, e.g.: +`image/jpeg` : [`jpg`, `jpeg`], the prefered extension can be set to override the default (first) one. + +__default__: first value in the list of extensions. + +### `timeout` (optional) + +maximum duration of the ffmpeg command in seconds. + +__default__: 3600 seconds + +### `threads` (optional) + +set the number of threads used by ffmpeg. + +__default__: depends on cpu (usually high), so the setting in most usefull to limit the cpu usage + +## Common options for video output formats + +### `video_kilobitrate`, `audio_kilobitrate` (optionals - advanced -) + +For video and audio output formats, change bitrate. + +__default__: depends on the output format. + +### `video_codec`, `audio_codec`, `passes` (optionals - advanced -) + +Video output formats use internaly a "ffmpeg-format" which itself may support multiple codecs. + +e.g. `video-mpeg4` uses ffmpeg-format `X264`, which supports many audio codecs like `aac`, `libmp3lame`, ... + +One can change the default ffmpeg codec(s) by setting `video_codec` and/or `audio_codec`. + +__default__: depends on the output format, if it uses internally a "ffmpeg-format" like X264, Ogg, ... + + + +-------------------------------------------- + +# Modules + +## video_to_frame +Extracts a frame (image) from a video. + +- `from_seconds` time in the video where the frame is extracted. + +```yaml +# example +video: + normalization: ~ + transformations: + - + module: video_to_frame + enabled: true + options: + timeout: 3600 + threads: 4 + format: image-jpeg + from_seconds: 4 + extension: jpeg +``` + +## video_to_animation +Build an animation from a video. + +- `from_seconds` time in the video where the animation begins. +- `duration` duration of the animation in seconds. +- `fps` frames per second of the animation. +- `width`, `height` size of the animation (see below "resize modes"). +- `mode` default to `inset` (see below "resize modes"). + +```yaml + module: video_to_animation + options: + format: animated-gif + from_seconds: 25 + duration: 5 + fps: 5 + width: 200 + height: 100 + mode: inset +``` + +## video_summary +Build a video made from extracts of the input video. + +- `period` period in seconds between each extract. +- `duration` duration of each extract in seconds. + +```yaml + module: video_summary + options: + format: video-quicktime + period: 30 + duration: 2 +``` + +## ffmpeg +Generic module to chain ffmpeg "filters" in a single command. + +- `filters` list of ffmpeg filters to apply. + +Each "filter" has a name and a list of specific options. + +```yaml + module: ffmpeg + options: + format: video-quicktime + filters: + - + name: resize + width: 320 + height: 240 + mode: inset + - + name: watermark + # only local files are supported for now + path: "/var/workspace/my_watermarks/google_PNG.png" + position: relative + bottom: 50 + right: 50 +``` + + +-------------------------------------------- + +## Output formats + +| format | family | mime type | extension(s) | +|-----------------|-----------|------------------|--------------| +| animated-gif | Animation | image/gif | gif | +| animated-png | Animation | image/png | apng, png | +| animated-webp | Animation | image/webp | webp | +| image-jpeg | Image | image/jpeg | jpg, jpeg | +| video-mkv | Video | video/x-matroska | mkv | +| video-mpeg4 | Video | video/mp4 | mp4 | +| video-mpeg | Video | video/mpeg | mpeg | +| video-quicktime | Video | video/quicktime | mov | +| video-webm | Video | video/webm | webm | + +-------------------------------------------- + +## Resize modes +### `inset` +The output is garanteed to fit in the requested size (width, height) and the aspect ratio is kept. +- If only one dimension is provided, the other is computed. +- If both dimensions are provided, the output is resize so the biggest dimension fits into the rectangle. +- If no dimension is provided, the output is the same size as the input. diff --git a/lib/php/rendition-factory/src/Transformer/Video/FFMpegHelper.php b/lib/php/rendition-factory/src/Transformer/Video/FFMpegHelper.php new file mode 100644 index 000000000..029ecd1b9 --- /dev/null +++ b/lib/php/rendition-factory/src/Transformer/Video/FFMpegHelper.php @@ -0,0 +1,29 @@ +getLogger()); + } +} diff --git a/lib/php/rendition-factory/src/Transformer/Video/FFMpegTransformerModule.php b/lib/php/rendition-factory/src/Transformer/Video/FFMpegTransformerModule.php index fa53886d1..48b1f0aeb 100644 --- a/lib/php/rendition-factory/src/Transformer/Video/FFMpegTransformerModule.php +++ b/lib/php/rendition-factory/src/Transformer/Video/FFMpegTransformerModule.php @@ -117,20 +117,7 @@ private function doVideo(FormatInterface $ouputFormat, string $extension, InputF $FFMpegFormat->setPasses($passes); } - $ffmpegOptions = []; - if ($timeout = $options['timeout'] ?? null) { - if (!is_int($timeout)) { - throw new InvalidArgumentException('Invalid timeout'); - } - $ffmpegOptions['timeout'] = $timeout; - } - if ($threads = $options['threads'] ?? null) { - if (!is_int($threads) || $threads < 1) { - throw new InvalidArgumentException('Invalid threads count'); - } - $ffmpegOptions['ffmpeg.threads'] = $threads; - } - $ffmpeg = FFMpeg\FFMpeg::create($ffmpegOptions, $context->getLogger()); + $ffmpeg = FFMpegHelper::createFFMpeg($options, $context); /** @var Video $video */ $video = $ffmpeg->open($inputFile->getPath()); diff --git a/lib/php/rendition-factory/src/Transformer/Video/VideoSummaryTransformerModule.php b/lib/php/rendition-factory/src/Transformer/Video/VideoSummaryTransformerModule.php index 5e87d190c..a09d8930f 100644 --- a/lib/php/rendition-factory/src/Transformer/Video/VideoSummaryTransformerModule.php +++ b/lib/php/rendition-factory/src/Transformer/Video/VideoSummaryTransformerModule.php @@ -86,9 +86,10 @@ public function transform(InputFileInterface $inputFile, array $options, Transfo $clipsExtension = ($outputFormat->getAllowedExtensions())[0]; + $ffmpeg = FFMpegHelper::createFFMpeg($options, $context); + $clipsFiles = []; try { - $ffmpeg = FFMpeg\FFMpeg::create([], $context->getLogger()); /** @var FFMpeg\Media\Video $video */ $video = $ffmpeg->open($inputFile->getPath()); diff --git a/lib/php/rendition-factory/src/Transformer/Video/VideoToAnimationTransformerModule.php b/lib/php/rendition-factory/src/Transformer/Video/VideoToAnimationTransformerModule.php index dc4497a0f..e61b6701a 100644 --- a/lib/php/rendition-factory/src/Transformer/Video/VideoToAnimationTransformerModule.php +++ b/lib/php/rendition-factory/src/Transformer/Video/VideoToAnimationTransformerModule.php @@ -108,7 +108,8 @@ public function transform(InputFileInterface $inputFile, array $options, Transfo $outputPath = $context->createTmpFilePath($extension); $commands[] = $outputPath; - $ffmpeg = FFMpeg\FFMpeg::create(); + $ffmpeg = FFMpegHelper::createFFMpeg($options, $context); + $ffmpeg->getFFMpegDriver()->command($commands); if(!file_exists($outputPath)) { diff --git a/lib/php/rendition-factory/src/Transformer/Video/VideoToFrameTransformerModule.php b/lib/php/rendition-factory/src/Transformer/Video/VideoToFrameTransformerModule.php index 99f094668..706b8072e 100644 --- a/lib/php/rendition-factory/src/Transformer/Video/VideoToFrameTransformerModule.php +++ b/lib/php/rendition-factory/src/Transformer/Video/VideoToFrameTransformerModule.php @@ -50,7 +50,7 @@ public function transform(InputFileInterface $inputFile, array $options, Transfo $extension = ($outputFormat->getAllowedExtensions())[0]; } - $ffmpeg = FFMpeg\FFMpeg::create(); // (new FFMpeg\FFMpeg)->open('/path/to/video'); + $ffmpeg = FFMpegHelper::createFFMpeg($options, $context); $from_seconds = $options['from_seconds'] ?? 0;