fix(metadata): add support for vorbis tags/comments in FileSynchronizer

This commit is contained in:
Joey Vos 2022-08-31 23:27:40 +02:00 committed by Phan An
parent b6465c61e7
commit 4c7e2644a3
No known key found for this signature in database
GPG key ID: A81E4477F0BB6FDC
5 changed files with 71 additions and 19 deletions

View file

@ -49,14 +49,16 @@ class FileSynchronizer
public function getFileScanInformation(): ?SongScanInformation
{
$info = $this->getID3->analyze($this->filePath);
$this->syncError = Arr::get($info, 'error.0') ?: (Arr::get($info, 'playtime_seconds') ? null : 'Empty file');
$raw = $this->getID3->analyze($this->filePath);
$this->syncError = Arr::get($raw, 'error.0') ?: (Arr::get($raw, 'playtime_seconds') ? null : 'Empty file');
if ($this->syncError) {
return null;
}
$info = SongScanInformation::fromGetId3Info($info);
$this->getID3->CopyTagsToComments($raw);
$info = SongScanInformation::fromGetId3Info($raw);
$info->lyrics = $info->lyrics ?: $this->lrcReader->tryReadForMediaFile($this->filePath);
return $info;

View file

@ -28,7 +28,12 @@ final class SongScanInformation implements Arrayable
public static function fromGetId3Info(array $info): self
{
// We prefer ID3v2 tags over ID3v1 tags.
$tags = array_merge(Arr::get($info, 'tags.id3v1', []), Arr::get($info, 'tags.id3v2', []));
$tags = array_merge(
Arr::get($info, 'tags.id3v1', []),
Arr::get($info, 'tags.id3v2', []),
Arr::get($info, 'comments', []),
);
$comments = Arr::get($info, 'comments', []);
$albumArtistName = self::getTag($tags, ['albumartist', 'album_artist', 'band']);
@ -41,16 +46,28 @@ final class SongScanInformation implements Arrayable
$path = Arr::get($info, 'filenamepath');
$cover = [self::getTag($comments, 'cover', null)];
if ($cover[0] === null) {
$cover = self::getTag($comments, 'picture', []);
}
$lyrics = html_entity_decode(self::getTag($tags, [
'unsynchronised_lyric',
'unsychronised_lyric',
'unsyncedlyrics',
]));
return new self(
title: html_entity_decode(self::getTag($tags, 'title', pathinfo($path, PATHINFO_FILENAME))),
albumName: html_entity_decode(self::getTag($tags, 'album', Album::UNKNOWN_NAME)),
artistName: html_entity_decode(self::getTag($tags, 'artist', Artist::UNKNOWN_NAME)),
albumArtistName: html_entity_decode($albumArtistName),
track: (int) self::getTag($tags, ['track', 'tracknumber', 'track_number']),
disc: (int) self::getTag($tags, 'part_of_a_set', 1),
lyrics: html_entity_decode(self::getTag($tags, ['unsynchronised_lyric', 'unsychronised_lyric'])),
disc: (int) self::getTag($tags, ['discnumber', 'part_of_a_set'], 1),
lyrics: $lyrics,
length: (float) Arr::get($info, 'playtime_seconds'),
cover: self::getTag($comments, 'picture', []),
cover: $cover,
path: $path,
mTime: Helper::getModifiedTime($path),
);

View file

@ -47,6 +47,37 @@ class FileSynchronizerTest extends TestCase
self::assertEqualsWithDelta(10, $info->length, 0.1);
}
/** @test */
public function testGetFileInfoVorbisCommentsFlac(): void
{
$flacPath = __DIR__ . '/../../songs/full-vorbis-comments.flac';
$info = $this->fileSynchronizer->setFile($flacPath)->getFileScanInformation();
$expectedData = [
'artist' => 'Koel',
'album' => 'Koel Testing Vol. 1',
'albumartist' => 'Koel',
'title' => 'Amet',
'track' => 5,
'disc' => 3,
'lyrics' => "Foo\r\nbar",
'cover' => [
'data' => file_get_contents(__DIR__ . '/../../blobs/cover.png'),
'image_mime' => 'image/png',
'image_width' => 512,
'image_height' => 512,
'picturetype' => 'Other',
'datalength' => 7627,
],
'path' => realpath($flacPath),
'mtime' => filemtime($flacPath),
];
self::assertArraySubset($expectedData, $info->toArray());
self::assertEqualsWithDelta(10, $info->length, 0.1);
}
/** @test */
public function testSongWithoutTitleHasFileNameAsTitle(): void
{
$this->fileSynchronizer->setFile(__DIR__ . '/../../songs/blank.mp3');

View file

@ -219,22 +219,24 @@ class MediaSyncServiceTest extends TestCase
public function testHtmlEntities(): void
{
$path = $this->path('/songs/blank.mp3');
$analyzed = [
'filenamepath' => $path,
'tags' => [
'id3v2' => [
'title' => ['水谷広実'],
'album' => ['小岩井こ Random'],
'artist' => ['佐倉綾音 Unknown'],
],
],
'encoding' => 'UTF-8',
'playtime_seconds' => 100,
];
$this->swap(
getID3::class,
Mockery::mock(getID3::class, [
'analyze' => [
'filenamepath' => $path,
'tags' => [
'id3v2' => [
'title' => ['水谷広実'],
'album' => ['小岩井こ Random'],
'artist' => ['佐倉綾音 Unknown'],
],
],
'encoding' => 'UTF-8',
'playtime_seconds' => 100,
],
'CopyTagsToComments' => $analyzed,
'analyze' => $analyzed,
])
);

Binary file not shown.