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); } }