mirror of
https://github.com/AnimeThemes/animethemes-server.git
synced 2026-07-11 01:24:46 +02:00
2e930b17ff
* feat: initial migration to Laravel 10 * style: fix StyleCI findings
199 lines
4.6 KiB
PHP
199 lines
4.6 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace App\Rules\Wiki\Submission;
|
|
|
|
use FFMpeg\FFProbe\DataMapping\Format;
|
|
use FFMpeg\FFProbe\DataMapping\StreamCollection;
|
|
use FFMpeg\FFProbe\Mapper;
|
|
use Illuminate\Contracts\Validation\DataAwareRule;
|
|
use Illuminate\Contracts\Validation\Rule;
|
|
use Illuminate\Contracts\Validation\ValidatorAwareRule;
|
|
use Illuminate\Http\UploadedFile;
|
|
use Illuminate\Support\Arr;
|
|
use Illuminate\Support\Str;
|
|
use Illuminate\Validation\Validator;
|
|
use ProtoneMedia\LaravelFFMpeg\FFMpeg\FFProbe;
|
|
use ProtoneMedia\LaravelFFMpeg\Support\FFMpeg;
|
|
|
|
/**
|
|
* Class SubmissionRule.
|
|
*/
|
|
abstract class SubmissionRule implements DataAwareRule, Rule, ValidatorAwareRule
|
|
{
|
|
/**
|
|
* The data under validation.
|
|
*
|
|
* @var array
|
|
*/
|
|
protected array $data = [];
|
|
|
|
/**
|
|
* Set the data under validation.
|
|
*
|
|
* @param array $data
|
|
* @return $this
|
|
*/
|
|
public function setData($data): self
|
|
{
|
|
$this->data = $data;
|
|
|
|
return $this;
|
|
}
|
|
|
|
/**
|
|
* Set the current validator.
|
|
*
|
|
* @param Validator $validator
|
|
* @return $this
|
|
*/
|
|
public function setValidator($validator): self
|
|
{
|
|
/** @var UploadedFile|null $file */
|
|
$file = Arr::get($validator->getData(), 'file');
|
|
|
|
$ffprobeData = Arr::get($validator->getData(), 'ffprobeData');
|
|
if ($ffprobeData === null && $file !== null) {
|
|
$validator->setValue('ffprobeData', $this->getFFprobeData($file));
|
|
}
|
|
|
|
$loudnessStats = Arr::get($validator->getData(), 'loudnessStats');
|
|
if ($loudnessStats === null && $file !== null) {
|
|
$validator->setValue('loudnessStats', $this->getLoudnessStats($file));
|
|
}
|
|
|
|
return $this;
|
|
}
|
|
|
|
/**
|
|
* Get the FFprobe data for the uploaded file.
|
|
*
|
|
* @param UploadedFile $file
|
|
* @return array
|
|
*/
|
|
private function getFFprobeData(UploadedFile $file): array
|
|
{
|
|
$commands = [
|
|
$file->path(),
|
|
'-v',
|
|
'quiet',
|
|
'-print_format',
|
|
'json',
|
|
'-show_streams',
|
|
'-show_format',
|
|
'-show_chapters',
|
|
];
|
|
|
|
$output = FFProbe::create(app('laravel-ffmpeg-configuration'))
|
|
->getFFProbeDriver()
|
|
->command($commands);
|
|
|
|
return json_decode($output, true);
|
|
}
|
|
|
|
/**
|
|
* Get the loudness stats for the uploaded file.
|
|
*
|
|
* @param UploadedFile $file
|
|
* @return array
|
|
*/
|
|
private function getLoudnessStats(UploadedFile $file): array
|
|
{
|
|
$filter = [
|
|
'-hide_banner',
|
|
'-nostats',
|
|
'-vn',
|
|
'-sn',
|
|
'-dn',
|
|
'-filter:a',
|
|
'loudnorm=I=-16:LRA=20:TP=-1:dual_mono=true:linear=true:print_format=json',
|
|
'-f',
|
|
'null',
|
|
];
|
|
|
|
$output = FFMpeg::open($file)
|
|
->export()
|
|
->addFilter($filter)
|
|
->getProcessOutput();
|
|
|
|
$output = Arr::join($output->all(), '');
|
|
$loudness = Str::match('/{[^}]*}/m', $output);
|
|
|
|
return json_decode($loudness, true);
|
|
}
|
|
|
|
/**
|
|
* Get submission streams.
|
|
*
|
|
* @return StreamCollection
|
|
*/
|
|
protected function streams(): StreamCollection
|
|
{
|
|
$ffprobeData = Arr::get($this->data, 'ffprobeData');
|
|
|
|
$mapper = new Mapper();
|
|
|
|
return $mapper->map('streams', $ffprobeData);
|
|
}
|
|
|
|
/**
|
|
* Get submission format.
|
|
*
|
|
* @return Format
|
|
*/
|
|
protected function format(): Format
|
|
{
|
|
$ffprobeData = Arr::get($this->data, 'ffprobeData');
|
|
|
|
$mapper = new Mapper();
|
|
|
|
return $mapper->map('format', $ffprobeData);
|
|
}
|
|
|
|
/**
|
|
* Get submission chapters.
|
|
*
|
|
* @return array
|
|
*/
|
|
protected function chapters(): array
|
|
{
|
|
return Arr::get($this->data, 'ffprobeData.chapters');
|
|
}
|
|
|
|
/**
|
|
* Get the submission loudness stats.
|
|
*
|
|
* @return array
|
|
*/
|
|
protected function loudness(): array
|
|
{
|
|
return Arr::get($this->data, 'loudnessStats');
|
|
}
|
|
|
|
/**
|
|
* For WebMs, tags will be contained in the format object.
|
|
* For Audios, tags will be contained in the stream object.
|
|
*
|
|
* @return array
|
|
*/
|
|
protected function tags(): array
|
|
{
|
|
$format = $this->format()->all();
|
|
if (Arr::has($format, 'tags')) {
|
|
$tags = Arr::get($format, 'tags');
|
|
|
|
return array_change_key_case($tags);
|
|
}
|
|
|
|
$audio = $this->streams()
|
|
->audios()
|
|
->first()
|
|
->all();
|
|
|
|
$tags = Arr::get($audio, 'tags', []);
|
|
|
|
return array_change_key_case($tags);
|
|
}
|
|
}
|