73 lines
2.3 KiB
PHP
73 lines
2.3 KiB
PHP
<?php
|
|
declare(strict_types=1);
|
|
|
|
namespace Esun\Video\Model;
|
|
|
|
use Magento\Framework\Exception\LocalizedException;
|
|
use Symfony\Component\Process\Process;
|
|
|
|
class Ffprobe
|
|
{
|
|
public function __construct(private readonly Config $config)
|
|
{
|
|
}
|
|
|
|
public function inspect(string $absoluteFile): array
|
|
{
|
|
$process = new Process([
|
|
$this->config->getFfprobeBinary(),
|
|
'-v', 'error',
|
|
'-select_streams', 'v:0',
|
|
'-show_entries', 'format=format_name,duration,size:stream=width,height,codec_name',
|
|
'-of', 'json',
|
|
$absoluteFile,
|
|
]);
|
|
$process->setTimeout(60);
|
|
try {
|
|
$process->run();
|
|
} catch (\Throwable $e) {
|
|
throw new LocalizedException(__('Unable to run ffprobe: %1', $e->getMessage()));
|
|
}
|
|
|
|
if (!$process->isSuccessful()) {
|
|
throw new LocalizedException(
|
|
__('ffprobe failed: %1', trim($process->getErrorOutput()) ?: __('unknown error'))
|
|
);
|
|
}
|
|
|
|
$data = json_decode($process->getOutput(), true);
|
|
$stream = $data['streams'][0] ?? [];
|
|
$format = $data['format'] ?? [];
|
|
$formatName = strtolower((string)($format['format_name'] ?? ''));
|
|
if (!str_contains($formatName, 'mp4') && !str_contains($formatName, 'mov')) {
|
|
throw new LocalizedException(__('Only MP4 container files are supported.'));
|
|
}
|
|
$width = (int)($stream['width'] ?? 0);
|
|
$height = (int)($stream['height'] ?? 0);
|
|
if ($width <= 0 || $height <= 0) {
|
|
throw new LocalizedException(__('The MP4 file does not contain a readable video stream.'));
|
|
}
|
|
|
|
return [
|
|
'duration' => round((float)($format['duration'] ?? 0), 3),
|
|
'size' => (int)($format['size'] ?? filesize($absoluteFile)),
|
|
'width' => $width,
|
|
'height' => $height,
|
|
'resolution' => $this->getResolution($width, $height),
|
|
];
|
|
}
|
|
|
|
private function getResolution(int $width, int $height): string
|
|
{
|
|
$longEdge = max($width, $height);
|
|
$shortEdge = min($width, $height);
|
|
if ($longEdge >= 3840 || $shortEdge >= 2160) {
|
|
return '4K';
|
|
}
|
|
if ($longEdge >= 1920 || $shortEdge >= 1080) {
|
|
return '1080p';
|
|
}
|
|
return $shortEdge . 'p';
|
|
}
|
|
}
|