diff --git a/lib/php/rendition-factory/src/Transformer/Video/FFMpegTransformerModule.php b/lib/php/rendition-factory/src/Transformer/Video/FFMpegTransformerModule.php index a590d811e..3ef19d0a5 100644 --- a/lib/php/rendition-factory/src/Transformer/Video/FFMpegTransformerModule.php +++ b/lib/php/rendition-factory/src/Transformer/Video/FFMpegTransformerModule.php @@ -23,6 +23,12 @@ public static function getName(): string public function transform(InputFileInterface $inputFile, array $options, TransformationContextInterface $context): OutputFileInterface { + $context->log("Applying '".self::getName()."' module"); + + if (FamilyEnum::Video !== $inputFile->getFamily()) { + throw new \InvalidArgumentException('Invalid input file family, should be video'); + } + $commonArgs = new ModuleCommonArgsDTO($this->formats, $options, $context, $this->optionsResolver); if (FamilyEnum::Video === $commonArgs->getOutputFormat()->getFamily()) { @@ -131,7 +137,6 @@ function ($filter) use ($resolverContext) { unset($clip, $video); gc_collect_cycles(); - printf("isProjection: %s\n", $isProjection ? 'true' : 'false'); return new OutputFile( $outputPath, @@ -199,7 +204,7 @@ private function preClip(Video $video, array $options, array $resolverContext, T $isProjection = false; } - $transformationContext->log(sprintf("Applying 'pre_clip' filter: start=%s, duration=%s", $startAsTimecode, $durationAsTimecode)); + $transformationContext->log(sprintf(" Applying 'pre_clip' filter: start=%s, duration=%s", $startAsTimecode, $durationAsTimecode)); return $video->clip($startAsTimecode, $durationAsTimecode); } @@ -207,7 +212,7 @@ private function preClip(Video $video, array $options, array $resolverContext, T private function remove_audio(Clip $clip, array $options, array $resolverContext, TransformationContextInterface $transformationContext, bool &$isProjection): void { $customFilter = '-an'; - $transformationContext->log("Applying 'remove_audio' filter"); + $transformationContext->log(" Applying 'remove_audio' filter"); $clip->addFilter(new FFMpeg\Filters\Audio\SimpleFilter([$customFilter])); } @@ -227,7 +232,7 @@ private function resize(Clip $clip, array $options, array $resolverContext, Tran throw new \InvalidArgumentException('Invalid mode for filter "resize"'); } - $transformationContext->log(sprintf("Applying 'resize' filter: dimension=[width=%s, height=%s], mode=%s", $dimension->getWidth(), $dimension->getHeight(), $mode)); + $transformationContext->log(sprintf(" Applying 'resize' filter: dimension=[width=%s, height=%s], mode=%s", $dimension->getWidth(), $dimension->getHeight(), $mode)); $clip->filters()->resize( $dimension, $mode @@ -248,7 +253,7 @@ private function rotate(Clip $clip, array $options, array $resolverContext, Tran throw new \InvalidArgumentException('Invalid rotation, must be 90, 180 or 270 for filter "rotate"'); } - $transformationContext->log(sprintf("Applying 'rotate' filter: angle=%d", $angle)); + $transformationContext->log(sprintf(" Applying 'rotate' filter: angle=%d", $angle)); $clip->filters()->rotate($rotations[$angle]); $isProjection = false; @@ -258,7 +263,7 @@ private function pad(Clip $clip, array $options, array $resolverContext, Transfo { $dimension = $this->getDimension($options, $resolverContext, 'pad'); - $transformationContext->log(sprintf("Applying 'pad' filter: dimension=%s", FFMpegHelper::dimensionAsText($dimension))); + $transformationContext->log(sprintf(" Applying 'pad' filter: dimension=%s", FFMpegHelper::dimensionAsText($dimension))); $clip->filters()->pad($dimension); $isProjection = false; @@ -274,7 +279,7 @@ private function crop(Clip $clip, array $options, array $resolverContext, Transf $point = new FFMpeg\Coordinate\Point((int) $x, (int) $y); $dimension = $this->getDimension($options, $resolverContext, 'crop'); - $transformationContext->log(sprintf("Applying 'crop' filter: point=%s, dimension=%s", FFMpegHelper::pointAsText($point), FFMpegHelper::dimensionAsText($dimension))); + $transformationContext->log(sprintf(" Applying 'crop' filter: point=%s, dimension=%s", FFMpegHelper::pointAsText($point), FFMpegHelper::dimensionAsText($dimension))); $clip->filters()->crop($point, $dimension); $isProjection = false; @@ -312,13 +317,13 @@ private function clip(Clip $clip, array $options, array $resolverContext, Transf $isProjection = false; } - $transformationContext->log(sprintf("Applying 'clip' filter: start=%s, duration=%s", $startAsTimecode, $durationAsTimecode)); + $transformationContext->log(sprintf(" Applying 'clip' filter: start=%s, duration=%s", $startAsTimecode, $durationAsTimecode)); $clip->filters()->clip($startAsTimecode, $durationAsTimecode); } private function synchronize(Clip $clip, array $options, array $resolverContext, TransformationContextInterface $transformationContext, bool &$isProjection): void { - $transformationContext->log("Applying 'synchronize' filter"); + $transformationContext->log(" Applying 'synchronize' filter"); $clip->filters()->synchronize(); } @@ -344,7 +349,7 @@ private function watermark(Clip $clip, array $options, array $resolverContext, T array_walk($coord, fn (&$v) => $v = (int) $this->optionsResolver->resolveOption($v, $resolverContext)); - $transformationContext->log(sprintf("Applying 'watermark' filter: path=%s, coord=%s", $path, FFMpegHelper::coordAsText($coord))); + $transformationContext->log(sprintf(" Applying 'watermark' filter: path=%s, coord=%s", $path, FFMpegHelper::coordAsText($coord))); $clip->filters()->watermark($path, $coord); } @@ -356,7 +361,7 @@ private function framerate(Clip $clip, array $options, array $resolverContext, T } $gop = (int) ($options['gop'] ?? 0); - $transformationContext->log(sprintf("Applying 'framerate' filter: framerate=%d, gop=%d", $framerate, $gop)); + $transformationContext->log(sprintf(" Applying 'framerate' filter: framerate=%d, gop=%d", $framerate, $gop)); $clip->filters()->framerate(new FFMpeg\Coordinate\FrameRate($framerate), $gop); } diff --git a/lib/php/rendition-factory/src/Transformer/Video/VideoSummaryTransformerModule.php b/lib/php/rendition-factory/src/Transformer/Video/VideoSummaryTransformerModule.php index 8a9c07f54..0b833d07c 100644 --- a/lib/php/rendition-factory/src/Transformer/Video/VideoSummaryTransformerModule.php +++ b/lib/php/rendition-factory/src/Transformer/Video/VideoSummaryTransformerModule.php @@ -3,6 +3,7 @@ namespace Alchemy\RenditionFactory\Transformer\Video; use Alchemy\RenditionFactory\Context\TransformationContextInterface; +use Alchemy\RenditionFactory\DTO\FamilyEnum; use Alchemy\RenditionFactory\DTO\InputFileInterface; use Alchemy\RenditionFactory\DTO\OutputFile; use Alchemy\RenditionFactory\DTO\OutputFileInterface; @@ -26,6 +27,12 @@ public static function getName(): string */ public function transform(InputFileInterface $inputFile, array $options, TransformationContextInterface $context): OutputFileInterface { + $context->log("Applying '".self::getName()."' module"); + + if (FamilyEnum::Video !== $inputFile->getFamily()) { + throw new \InvalidArgumentException('Invalid input file family, should be video'); + } + $commonArgs = new ModuleCommonArgsDTO($this->formats, $options, $context, $this->optionsResolver); $outputFormat = $commonArgs->getOutputFormat(); $format = $outputFormat->getFormat(); @@ -47,6 +54,8 @@ public function transform(InputFileInterface $inputFile, array $options, Transfo throw new \InvalidArgumentException(sprintf('Invalid duration for module "%s"', self::getName())); } + $context->log(sprintf(' period: %d, duration: %d', $period, $clipDuration)); + /** @var VideoInterface $FFMpegOutputFormat */ $FFMpegOutputFormat = $outputFormat->getFFMpegFormat(); if ($videoCodec = $this->optionsResolver->resolveOption($options['video_codec'] ?? null, $resolverContext)) { @@ -69,7 +78,7 @@ public function transform(InputFileInterface $inputFile, array $options, Transfo $inputDuration = $video->getFFProbe()->format($inputFile->getPath())->get('duration'); $nClips = ceil($inputDuration / $period); - $context->log(sprintf('Duration duration: %s, extracting %d clips of %d seconds', $inputDuration, $nClips, $clipDuration)); + $context->log(sprintf(' Duration duration: %s, extracting %d clips of %d seconds', $inputDuration, $nClips, $clipDuration)); $clipDuration = TimeCode::fromSeconds($clipDuration); $removeAudioFilter = new FFMpeg\Filters\Audio\SimpleFilter(['-an']); for ($i = 0; $i < $nClips; ++$i) { diff --git a/lib/php/rendition-factory/src/Transformer/Video/VideoToAnimationTransformerModule.php b/lib/php/rendition-factory/src/Transformer/Video/VideoToAnimationTransformerModule.php index 07a0e4ea8..58c8a320a 100644 --- a/lib/php/rendition-factory/src/Transformer/Video/VideoToAnimationTransformerModule.php +++ b/lib/php/rendition-factory/src/Transformer/Video/VideoToAnimationTransformerModule.php @@ -3,6 +3,7 @@ namespace Alchemy\RenditionFactory\Transformer\Video; use Alchemy\RenditionFactory\Context\TransformationContextInterface; +use Alchemy\RenditionFactory\DTO\FamilyEnum; use Alchemy\RenditionFactory\DTO\InputFileInterface; use Alchemy\RenditionFactory\DTO\OutputFile; use Alchemy\RenditionFactory\DTO\OutputFileInterface; @@ -18,6 +19,12 @@ public static function getName(): string public function transform(InputFileInterface $inputFile, array $options, TransformationContextInterface $context): OutputFileInterface { + $context->log("Applying '".self::getName()."' module"); + + if (FamilyEnum::Video !== $inputFile->getFamily()) { + throw new \InvalidArgumentException('Invalid input file family, should be video'); + } + $commonArgs = new ModuleCommonArgsDTO($this->formats, $options, $context, $this->optionsResolver); $outputFormat = $commonArgs->getOutputFormat(); @@ -29,7 +36,7 @@ public function transform(InputFileInterface $inputFile, array $options, Transfo 'input' => $video->getStreams()->videos()->first()->all(), ]; - $fromSeconds = FFMpeg\Coordinate\TimeCode::fromSeconds($this->optionsResolver->resolveOption($options['from_seconds'] ?? 0, $resolverContext)); + $from = FFMpeg\Coordinate\TimeCode::fromSeconds($this->optionsResolver->resolveOption($options['from_seconds'] ?? 0, $resolverContext)); $duration = $this->optionsResolver->resolveOption($options['duration'] ?? null, $resolverContext); if (null !== $duration && ($duration = (int) $duration) <= 0) { @@ -67,18 +74,26 @@ public function transform(InputFileInterface $inputFile, array $options, Transfo throw new \InvalidArgumentException('Invalid resize mode'); } + $context->log(sprintf(' from=%s, duration=%s, fps=%s, width=%d, height=%d', $from, $duration, $fps, $width, $height)); + $commands = [ '-i', $inputFile->getPath(), '-ss', - $fromSeconds, + $from, ]; if (null !== $duration) { $commands[] = '-t'; $commands[] = $duration; } $commands[] = '-vf'; - $commands[] = 'fps='.$fps.',scale='.$width.':'.$height.':flags=lanczos,split[s0][s1];[s0]palettegen[p];[s1][p]paletteuse'; + + $c = 'fps='.$fps; + if (-1 !== $width || -1 !== $height) { + $c .= ',scale='.$width.':'.$height.':flags=lanczos'; + } + $c .= ',split[s0][s1];[s0]palettegen[p];[s1][p]paletteuse'; + $commands[] = $c; $commands[] = '-loop'; $commands[] = '0'; diff --git a/lib/php/rendition-factory/src/Transformer/Video/VideoToFrameTransformerModule.php b/lib/php/rendition-factory/src/Transformer/Video/VideoToFrameTransformerModule.php index 8a8df28e1..7ae40e41c 100644 --- a/lib/php/rendition-factory/src/Transformer/Video/VideoToFrameTransformerModule.php +++ b/lib/php/rendition-factory/src/Transformer/Video/VideoToFrameTransformerModule.php @@ -3,6 +3,7 @@ namespace Alchemy\RenditionFactory\Transformer\Video; use Alchemy\RenditionFactory\Context\TransformationContextInterface; +use Alchemy\RenditionFactory\DTO\FamilyEnum; use Alchemy\RenditionFactory\DTO\InputFileInterface; use Alchemy\RenditionFactory\DTO\OutputFile; use Alchemy\RenditionFactory\DTO\OutputFileInterface; @@ -19,6 +20,12 @@ public static function getName(): string public function transform(InputFileInterface $inputFile, array $options, TransformationContextInterface $context): OutputFileInterface { + $context->log("Applying '".self::getName()."' module"); + + if (FamilyEnum::Video !== $inputFile->getFamily()) { + throw new \InvalidArgumentException('Invalid input file family, should be video'); + } + $commonArgs = new ModuleCommonArgsDTO($this->formats, $options, $context, $this->optionsResolver); $outputFormat = $commonArgs->getOutputFormat(); @@ -30,9 +37,11 @@ public function transform(InputFileInterface $inputFile, array $options, Transfo 'input' => $video->getStreams()->videos()->first()->all(), ]; - $fromSeconds = $this->optionsResolver->resolveOption($options['from_seconds'] ?? 0, $resolverContext); + $from = FFMpeg\Coordinate\TimeCode::fromSeconds($this->optionsResolver->resolveOption($options['from_seconds'] ?? 0, $resolverContext)); + + $context->log(sprintf(' from=%s', $from)); - $frame = $video->frame(FFMpeg\Coordinate\TimeCode::fromSeconds($fromSeconds)); + $frame = $video->frame($from); $outputPath = $context->createTmpFilePath($commonArgs->getExtension()); $frame->save($outputPath);