|
| 1 | +<?php |
| 2 | + |
| 3 | +declare(strict_types=1); |
| 4 | + |
| 5 | +namespace Elegantly\Media\Definitions; |
| 6 | + |
| 7 | +use Closure; |
| 8 | +use Elegantly\Media\Definitions\Concerns\HasFilename; |
| 9 | +use Elegantly\Media\Enums\MediaType; |
| 10 | +use Elegantly\Media\Helpers\File; |
| 11 | +use Elegantly\Media\Models\Media; |
| 12 | +use Elegantly\Media\Models\MediaConversion; |
| 13 | +use Illuminate\Contracts\Filesystem\Filesystem; |
| 14 | +use ProtoneMedia\LaravelFFMpeg\Filters\TileFactory; |
| 15 | +use ProtoneMedia\LaravelFFMpeg\Support\FFMpeg; |
| 16 | +use Spatie\TemporaryDirectory\TemporaryDirectory as SpatieTemporaryDirectory; |
| 17 | + |
| 18 | +class MediaConversionSpritesheet extends MediaConversionDefinition |
| 19 | +{ |
| 20 | + use HasFilename; |
| 21 | + |
| 22 | + /** |
| 23 | + * @param float $interval in seconds |
| 24 | + * @param MediaConversionDefinition[] $conversions |
| 25 | + * @param null|bool|Closure(Media $media, ?MediaConversion $parent): bool $when |
| 26 | + */ |
| 27 | + public function __construct( |
| 28 | + public string $name, |
| 29 | + public null|bool|Closure $when = null, |
| 30 | + public ?Closure $onCompleted = null, |
| 31 | + public bool $immediate = true, |
| 32 | + public bool $queued = true, |
| 33 | + public ?string $queue = null, |
| 34 | + public array $conversions = [], |
| 35 | + public null|string|Closure $fileName = null, |
| 36 | + public float $interval = 3.0, |
| 37 | + public int $width = 180, |
| 38 | + ) { |
| 39 | + |
| 40 | + parent::__construct( |
| 41 | + name: $name, |
| 42 | + handle: fn () => null, |
| 43 | + when: $when, |
| 44 | + onCompleted: $onCompleted, |
| 45 | + immediate: $immediate, |
| 46 | + queued: $queued, |
| 47 | + queue: $queue, |
| 48 | + conversions: $conversions |
| 49 | + ); |
| 50 | + } |
| 51 | + |
| 52 | + public function shouldExecute(Media $media, ?MediaConversion $parent): bool |
| 53 | + { |
| 54 | + if ($this->when !== null) { |
| 55 | + return parent::shouldExecute($media, $parent); |
| 56 | + } |
| 57 | + |
| 58 | + $source = $parent ?? $media; |
| 59 | + |
| 60 | + return $source->type === MediaType::Video; |
| 61 | + } |
| 62 | + |
| 63 | + public function getDefaultFilename(Media $media, ?MediaConversion $parent): string |
| 64 | + { |
| 65 | + $source = $parent ?? $media; |
| 66 | + |
| 67 | + return "{$source->name}.jpg"; |
| 68 | + } |
| 69 | + |
| 70 | + public function handle( |
| 71 | + Media $media, |
| 72 | + ?MediaConversion $parent, |
| 73 | + ?string $file, |
| 74 | + Filesystem $filesystem, |
| 75 | + SpatieTemporaryDirectory $temporaryDirectory |
| 76 | + ): ?MediaConversion { |
| 77 | + if (! $file) { |
| 78 | + return null; |
| 79 | + } |
| 80 | + |
| 81 | + $newFile = $this->getFilename($media, $parent); |
| 82 | + |
| 83 | + $ffmpeg = FFMpeg::fromFilesystem($filesystem) |
| 84 | + ->open($file); |
| 85 | + |
| 86 | + // in ms |
| 87 | + $duration = File::duration($filesystem->path($file)) ?? 0.0; |
| 88 | + |
| 89 | + $count = (int) ceil(($duration / 1_000) / $this->interval); |
| 90 | + |
| 91 | + $ffmpeg = $ffmpeg->exportTile( |
| 92 | + fn (TileFactory $tileFactory) => $tileFactory |
| 93 | + ->interval($this->interval) |
| 94 | + ->grid(1, $count) |
| 95 | + ->scale($this->width) |
| 96 | + ); |
| 97 | + |
| 98 | + $ffmpeg->save($newFile); |
| 99 | + |
| 100 | + return $media->addConversion( |
| 101 | + file: $filesystem->path($newFile), |
| 102 | + conversionName: $this->name, |
| 103 | + parent: $parent, |
| 104 | + ); |
| 105 | + |
| 106 | + } |
| 107 | +} |
0 commit comments