Fixes #5595 -- Properly handle ogg container metadata.

This commit is contained in:
Buster "Silver Eagle" Neece 2022-08-11 13:50:52 -05:00
parent e087567a64
commit a4c214fe7a
No known key found for this signature in database
GPG Key ID: F1D2E64A0005E80E
1 changed files with 84 additions and 45 deletions

View File

@ -24,62 +24,64 @@ final class Reader
$ffprobe = FFProbe::create();
$format = $ffprobe->format($path);
$streams = $ffprobe->streams($path);
$metadata = new Metadata();
$metadata->setMimeType(MimeType::getMimeTypeFromFile($path));
if (is_numeric($format->get('duration'))) {
$metadata->setDuration(
Time::displayTimeToSeconds($format->get('duration')) ?? 0.0
);
$duration = $this->getDuration($format, $streams);
if (null !== $duration) {
$metadata->setDuration($duration);
}
$metadata->setTags($this->aggregateMetaTags(
$format,
$streams
));
$metadata->setArtwork($this->getAlbumArt(
$streams,
$path
));
$event->setMetadata($metadata);
}
private function getDuration(
FFProbe\DataMapping\Format $format,
FFProbe\DataMapping\StreamCollection $streams
): ?float {
$formatDuration = $format->get('duration');
if (is_numeric($formatDuration)) {
return Time::displayTimeToSeconds($formatDuration);
}
/** @var Stream $stream */
foreach ($streams->audios() as $stream) {
$duration = $stream->get('duration');
if (is_numeric($duration)) {
return Time::displayTimeToSeconds($duration);
}
}
return null;
}
private function aggregateMetaTags(
FFProbe\DataMapping\Format $format,
FFProbe\DataMapping\StreamCollection $streams
): array {
$toProcess = [
$format->get('comments'),
$format->get('tags'),
];
$metaTags = $this->aggregateMetaTags($toProcess);
$metadata->setTags($metaTags);
$metadata->setMimeType(MimeType::getMimeTypeFromFile($path));
try {
// Pull album art directly from relevant streams.
$ffmpeg = FFMpeg::create();
/** @var Stream[] $videoStreams */
$videoStreams = $ffprobe->streams($path)->videos()->all();
foreach ($videoStreams as $videoStream) {
$streamDisposition = $videoStream->get('disposition');
if (!isset($streamDisposition['attached_pic']) || 1 !== $streamDisposition['attached_pic']) {
continue;
}
$artOutput = File::generateTempPath('artwork.jpg');
@unlink($artOutput); // Ffmpeg won't overwrite the empty file.
$ffmpeg->getFFMpegDriver()->command([
'-i',
$path,
'-an',
'-vcodec',
'copy',
$artOutput,
]);
$metadata->setArtwork(file_get_contents($artOutput) ?: null);
@unlink($artOutput);
break;
}
} catch (Throwable) {
$metadata->setArtwork(null);
/** @var Stream $stream */
foreach ($streams->audios() as $stream) {
$toProcess[] = $stream->get('comments');
$toProcess[] = $stream->get('tags');
}
$event->setMetadata($metadata);
}
protected function aggregateMetaTags(array $toProcess): array
{
$metaTags = [];
foreach ($toProcess as $tagSet) {
@ -107,7 +109,44 @@ final class Reader
return $metaTags;
}
protected function cleanUpString(?string $original): string
private function getAlbumArt(
FFProbe\DataMapping\StreamCollection $streams,
string $path
): ?string {
// Pull album art directly from relevant streams.
$ffmpeg = FFMpeg::create();
try {
/** @var Stream $videoStream */
foreach ($streams->videos() as $videoStream) {
$streamDisposition = $videoStream->get('disposition');
if (!isset($streamDisposition['attached_pic']) || 1 !== $streamDisposition['attached_pic']) {
continue;
}
$artOutput = File::generateTempPath('artwork.jpg');
@unlink($artOutput); // Ffmpeg won't overwrite the empty file.
$ffmpeg->getFFMpegDriver()->command([
'-i',
$path,
'-an',
'-vcodec',
'copy',
$artOutput,
]);
$artContent = file_get_contents($artOutput) ?: null;
@unlink($artOutput);
return $artContent;
}
} catch (Throwable) {
}
return null;
}
private function cleanUpString(?string $original): string
{
$original ??= '';