Skip to content

Commit

Permalink
Merge branch 'PS-670-rendition-video_enhance1' of github.com:alchemy-…
Browse files Browse the repository at this point in the history
…fr/phraseanet-services into w2442
  • Loading branch information
nmaillat committed Oct 10, 2024
2 parents 9507b86 + 0eb9252 commit 2a54563
Show file tree
Hide file tree
Showing 8 changed files with 87 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@ services:
tags:
- { name: !php/const Alchemy\RenditionFactory\Transformer\TransformerModuleInterface::TAG }

Alchemy\RenditionFactory\Transformer\Video\VideoToFrameTransformerModule:
tags:
- { name: !php/const Alchemy\RenditionFactory\Transformer\TransformerModuleInterface::TAG }

Alchemy\RenditionFactory\Transformer\Document\DocumentToPdfTransformerModule:
tags:
- { name: !php/const Alchemy\RenditionFactory\Transformer\TransformerModuleInterface::TAG }
Expand Down
2 changes: 1 addition & 1 deletion lib/php/rendition-factory/src/Command/CreateCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ protected function configure(): void

$this->addArgument('src', InputArgument::REQUIRED, 'The source file');
$this->addArgument('build-config', InputArgument::REQUIRED, 'The build config YAML file');
$this->addOption('type', 't', InputOption::VALUE_OPTIONAL, 'Force the MIME type of file');
$this->addOption('type', 't', InputOption::VALUE_REQUIRED, 'Force the MIME type of file');
$this->addOption('working-dir', 'w', InputOption::VALUE_REQUIRED, 'The working directory. Defaults to system temp directory');
$this->addOption('output', 'o', InputOption::VALUE_REQUIRED, 'The output file name WITHOUT extension');
$this->addOption('debug', 'd', InputOption::VALUE_NONE, 'set to debug mode (keep files in working directory)');
Expand Down
1 change: 1 addition & 0 deletions lib/php/rendition-factory/src/Config/YamlLoader.php
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ private function parseTransformation(array $transformation): Transformation
{
return new Transformation(
$transformation['module'],
$transformation['enabled'] ?? true,
$transformation['options'] ?? [],
$transformation['description'] ?? null
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,10 @@ public function __construct(

public function getTransformations(): array
{
return $this->transformations;
return array_filter(
$this->transformations,
fn (Transformation $transformation) => $transformation->isEnabled()
);
}

public function getNormalization(): array
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
{
public function __construct(
private string $module,
private bool $enabled,
private array $options,
private ?string $description,
) {
Expand All @@ -25,4 +26,9 @@ public function getOptions(): array
{
return $this->options;
}

public function isEnabled(): bool
{
return $this->enabled;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -138,10 +138,11 @@ private function doVideo(string $format, string $extension, InputFileInterface $

$clip->save($ouputFormat, $outputPath);

unset($clip);
unset($video);
unset($clip, $video);
gc_collect_cycles();

$mimeType = $context->guessMimeTypeFromPath($outputPath);

$fileFamilyGuesser = new FileFamilyGuesser();
$family = $fileFamilyGuesser->getFamily($outputPath, $mimeType);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@
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;
use Alchemy\RenditionFactory\FileFamilyGuesser;
use Alchemy\RenditionFactory\Transformer\TransformerModuleInterface;
use FFMpeg;
use FFMpeg\Coordinate\TimeCode;
Expand Down Expand Up @@ -108,13 +108,19 @@ private function processVideo(string $format, string $extension, InputFileInterf

$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) {
$start = $i * $period;
$clip = $video->clip(TimeCode::fromSeconds($start), $clipDuration);
$clip->addFilter($removeAudioFilter);
$clipPath = $context->createTmpFilePath($clipsExtension);
$clip->save($clipsFormat, $clipPath);
unset($clip);
gc_collect_cycles();
$clipsFiles[] = realpath($clipPath);
}
unset($removeAudioFilter, $video);
gc_collect_cycles();

$outVideo = $ffmpeg->open($clipsFiles[0]);

Expand All @@ -127,6 +133,9 @@ private function processVideo(string $format, string $extension, InputFileInterf
->concat($clipsFiles)
->saveFromDifferentCodecs($outpuFormat, $outputPath);
}

unset($outVideo);
gc_collect_cycles();
} finally {
foreach ($clipsFiles as $clipFile) {
@unlink($clipFile);
Expand All @@ -137,11 +146,15 @@ private function processVideo(string $format, string $extension, InputFileInterf
throw new \RuntimeException(sprintf('Failed to create summary video'));
}

// TODO return the correct family and MIME type
$mimeType = $context->guessMimeTypeFromPath($outputPath);

$fileFamilyGuesser = new FileFamilyGuesser();
$family = $fileFamilyGuesser->getFamily($outputPath, $mimeType);

return new OutputFile(
$outputPath,
'application/octet-stream',
FamilyEnum::Unknown
$mimeType,
$family
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
<?php

namespace Alchemy\RenditionFactory\Transformer\Video;

use Alchemy\RenditionFactory\Context\TransformationContextInterface;
use Alchemy\RenditionFactory\DTO\InputFileInterface;
use Alchemy\RenditionFactory\DTO\OutputFile;
use Alchemy\RenditionFactory\DTO\OutputFileInterface;
use Alchemy\RenditionFactory\FileFamilyGuesser;
use Alchemy\RenditionFactory\Transformer\TransformerModuleInterface;
use FFMpeg;

final readonly class VideoToFrameTransformerModule implements TransformerModuleInterface
{
public function __construct()
{
}

public static function getName(): string
{
return 'video_to_frame';
}

public function transform(InputFileInterface $inputFile, array $options, TransformationContextInterface $context): OutputFileInterface
{
$ffmpeg = FFMpeg\FFMpeg::create(); // (new FFMpeg\FFMpeg)->open('/path/to/video');

$from_seconds = $options['from_seconds'] ?? 0;
$extension = $options['extension'] ?? '.jpg';

$video = $ffmpeg->open($inputFile->getPath());
$frame = $video->frame(FFMpeg\Coordinate\TimeCode::fromSeconds($from_seconds));
$outputPath = $context->createTmpFilePath($extension);

$frame->save($outputPath);

unset($frame, $video);
gc_collect_cycles();

$mimeType = $context->guessMimeTypeFromPath($outputPath);

$fileFamilyGuesser = new FileFamilyGuesser();
$family = $fileFamilyGuesser->getFamily($outputPath, $mimeType);

return new OutputFile(
$outputPath,
$mimeType,
$family
);
}
}

0 comments on commit 2a54563

Please sign in to comment.