diff --git a/.github/workflows/phpstan-php-code.yml b/.github/workflows/phpstan-php-code.yml
new file mode 100644
index 0000000..a222dfc
--- /dev/null
+++ b/.github/workflows/phpstan-php-code.yml
@@ -0,0 +1,14 @@
+name: PHPStan PHP code issues
+
+on: [push]
+
+jobs:
+ build-test:
+ runs-on: ubuntu-latest
+
+ steps:
+ - uses: actions/checkout@v4
+ - uses: php-actions/composer@v6
+ - uses: php-actions/phpstan@v3
+ with:
+ path: src/
diff --git a/.gitignore b/.gitignore
index 7c784c0..9ee9c98 100644
--- a/.gitignore
+++ b/.gitignore
@@ -10,3 +10,5 @@ psalm.xml
vendor
.php-cs-fixer.cache
.DS_Store
+.phpunit.cache
+version-draft.md
diff --git a/README.md b/README.md
index 2951778..de072b5 100644
--- a/README.md
+++ b/README.md
@@ -413,41 +413,33 @@ You want to add a format? [See FAQ](#faq)
`Audio::class` convert some properties to be more readable.
-| ID3 type | Original | New property |
-| :-------------: | :---------------------: | :------------------: |
-| `id3v2` | `band` | `albumArtist` |
-| `id3v2` | `track_number` | `trackNumber` |
-| `id3v2` | `part_of_a_set` | `discNumber` |
-| `id3v2` | `part_of_a_compilation` | `isCompilation` |
-| `quicktime` | `track_number` | `trackNumber` |
-| `quicktime` | `disc_number` | `discNumber` |
-| `quicktime` | `compilation` | `isCompilation` |
-| `quicktime` | `creation_date` | `creationDate` |
-| `quicktime` | `album_artist` | `albumArtist` |
-| `quicktime` | `encoded_by` | `encodingBy` |
-| `quicktime` | `encoding_tool` | `encoding` |
-| `quicktime` | `description_long` | `podcastDescription` |
-| `asf` | `albumartist` | `albumArtist` |
-| `asf` | `partofset` | `discNumber` |
-| `asf` | `track_number` | `trackNumber` |
-| `asf` | `encodingsettings` | `encoding` |
-| `vorbiscomment` | `encoder` | `encoding` |
-| `vorbiscomment` | `albumartist` | `albumArtist` |
-| `vorbiscomment` | `discnumber` | `discNumber` |
-| `vorbiscomment` | `compilation` | `isCompilation` |
-| `vorbiscomment` | `tracknumber` | `trackNumber` |
-| `matroska` | `album_artist` | `albumArtist` |
-| `matroska` | `disc` | `discNumber` |
-| `matroska` | `part_number` | `trackNumber` |
-| `matroska` | `date` | `year` |
-| `matroska` | `compilation` | `isCompilation` |
-| `matroska` | `encoder` | `encoding` |
-| `ape` | `album_artist` | `albumArtist` |
-| `ape` | `disc` | `discNumber` |
-| `ape` | `compilation` | `isCompilation` |
-| `ape` | `track` | `trackNumber` |
-| `ape` | `date` | `year` |
-| `ape` | `encoder` | `encoding` |
+| ID3 type | Original | New property |
+| :-------------: | :---------------------: | :--------------: |
+| `id3v2` | `band` | `album_artist` |
+| `id3v2` | `part_of_a_set` | `disc_number` |
+| `id3v2` | `part_of_a_compilation` | `is_compilation` |
+| `quicktime` | `compilation` | `is_compilation` |
+| `quicktime` | `encoded_by` | `encoding_by` |
+| `quicktime` | `encoding_tool` | `encoding` |
+| `quicktime` | `description_long` | `synopsis` |
+| `asf` | `albumartist` | `album_artist` |
+| `asf` | `partofset` | `disc_number` |
+| `asf` | `encodingsettings` | `encoding` |
+| `vorbiscomment` | `encoder` | `encoding` |
+| `vorbiscomment` | `albumartist` | `album_artist` |
+| `vorbiscomment` | `discnumber` | `disc_number` |
+| `vorbiscomment` | `compilation` | `is_compilation` |
+| `vorbiscomment` | `tracknumber` | `track_number` |
+| `matroska` | `disc` | `disc_number` |
+| `matroska` | `part_number` | `track_number` |
+| `matroska` | `date` | `year` |
+| `matroska` | `compilation` | `is_compilation` |
+| `matroska` | `encoder` | `encoding` |
+| `ape` | `disc` | `disc_number` |
+| `ape` | `compilation` | `is_compilation` |
+| `ape` | `track` | `track_number` |
+| `ape` | `date` | `year` |
+| `ape` | `encoder` | `encoding` |
## Testing
diff --git a/composer.json b/composer.json
index 5033e57..2c74a7b 100644
--- a/composer.json
+++ b/composer.json
@@ -1,7 +1,7 @@
{
"name": "kiwilan/php-audio",
"description": "PHP package to parse and update audio files metadata, with `JamesHeinrich/getID3`.",
- "version": "3.0.08",
+ "version": "4.0.0",
"keywords": [
"audio",
"php",
@@ -41,10 +41,11 @@
],
"require": {
"php": "^8.1",
- "james-heinrich/getid3": "^1.9"
+ "james-heinrich/getid3": "^v1.9.22"
},
"require-dev": {
- "pestphp/pest": "^1.20",
+ "pestphp/pest": "^2.0",
+ "phpstan/phpstan": "^1.12",
"laravel/pint": "^1.2",
"spatie/ray": "^1.28"
},
diff --git a/phpstan.neon b/phpstan.neon
new file mode 100644
index 0000000..e5b7e20
--- /dev/null
+++ b/phpstan.neon
@@ -0,0 +1,8 @@
+parameters:
+ tmpDir: public/build/.phpstan
+
+ paths:
+ - src
+
+ # The level 9 is the highest level
+ level: 5
diff --git a/phpunit.xml.dist b/phpunit.xml.dist
index a7e9c48..966c25d 100644
--- a/phpunit.xml.dist
+++ b/phpunit.xml.dist
@@ -1,14 +1,10 @@
@@ -24,16 +21,18 @@
-
- ./src
-
-
-
-
+
+
+
-
+
-
+
+
+ ./src
+
+
+
\ No newline at end of file
diff --git a/src/Audio.php b/src/Audio.php
index 4bf8e65..1c7a7b6 100755
--- a/src/Audio.php
+++ b/src/Audio.php
@@ -2,78 +2,51 @@
namespace Kiwilan\Audio;
+use Kiwilan\Audio\Core\AudioCore;
use Kiwilan\Audio\Enums\AudioFormatEnum;
use Kiwilan\Audio\Enums\AudioTypeEnum;
-use Kiwilan\Audio\Models\AudioCore;
+use Kiwilan\Audio\Id3\Id3Reader;
use Kiwilan\Audio\Models\AudioCover;
use Kiwilan\Audio\Models\AudioMetadata;
-use Kiwilan\Audio\Models\AudioStat;
-use Kiwilan\Audio\Models\Id3Reader;
-use Kiwilan\Audio\Models\Id3Writer;
class Audio
{
- protected ?string $title = null;
-
- protected ?string $artist = null;
-
- protected ?string $album = null;
-
- protected ?string $genre = null;
-
- protected ?int $year = null;
-
- protected ?string $trackNumber = null;
-
- protected ?string $comment = null;
-
- protected ?string $albumArtist = null;
-
- protected ?string $composer = null;
-
- protected ?string $discNumber = null;
-
- protected bool $isCompilation = false;
-
- protected ?string $creationDate = null;
-
- protected ?string $copyright = null;
-
- protected ?string $encodingBy = null;
-
- protected ?string $encoding = null;
-
- protected ?string $description = null;
-
- protected ?string $podcastDescription = null;
-
- protected ?string $language = null;
-
- protected ?string $lyrics = null;
-
- protected ?string $stik = null;
-
- protected ?float $duration = null;
-
- protected array $extras = [];
-
- protected ?AudioMetadata $audio = null;
-
- protected bool $hasCover = false;
-
- protected ?AudioCover $cover = null;
-
- protected bool $isValid = false;
-
- protected ?AudioTypeEnum $type = null;
-
+ /**
+ * @param array $raw_tags_all
+ */
protected function __construct(
protected string $path,
protected string $extension,
protected AudioFormatEnum $format,
- protected AudioStat $stat,
- protected Id3Reader $reader,
- protected ?Id3Writer $writer = null,
+ protected ?AudioTypeEnum $type = null,
+ protected ?AudioMetadata $metadata = null,
+ protected ?AudioCover $cover = null,
+ protected ?float $duration = null,
+ protected bool $is_writable = false,
+ protected bool $is_valid = false,
+ protected bool $has_cover = false,
+ //
+ protected ?string $title = null,
+ protected ?string $artist = null,
+ protected ?string $album = null,
+ protected ?string $genre = null,
+ protected ?int $year = null,
+ protected ?string $track_number = null,
+ protected ?string $comment = null,
+ protected ?string $album_artist = null,
+ protected ?string $composer = null,
+ protected ?string $disc_number = null,
+ protected bool $is_compilation = false,
+ protected ?string $creation_date = null,
+ protected ?string $copyright = null,
+ protected ?string $encoding_by = null,
+ protected ?string $encoding = null,
+ protected ?string $description = null,
+ protected ?string $synopsis = null,
+ protected ?string $language = null,
+ protected ?string $lyrics = null,
+
+ protected array $raw_tags_all = [],
) {}
public static function get(string $path): self
@@ -91,303 +64,382 @@ public static function get(string $path): self
path: $path,
extension: $extension,
format: $format ? $format : AudioFormatEnum::unknown,
- stat: AudioStat::make($path),
- reader: Id3Reader::make($path),
);
- if ($self->reader->isWritable()) {
- $self->writer = Id3Writer::make($self);
+
+ try {
+ $id3_reader = Id3Reader::make($path);
+
+ $self->metadata = AudioMetadata::make($self, $id3_reader);
+ $self->duration = (float) number_format((float) $self->metadata->getDurationSeconds(), 2, '.', '');
+ $self->is_writable = $id3_reader->isWritable();
+
+ $self->parseTags($id3_reader);
+ } catch (\Throwable $th) {
+ error_log($th->getMessage());
}
- $self->audio = AudioMetadata::make($self);
- $self->parse();
return $self;
}
/**
- * Update metadata of audio file.
+ * Get audio file path, like `/path/to/audio.mp3`.
*/
- public function update(): Id3Writer
+ public function getPath(): string
{
- return $this->writer;
+ return $this->path;
}
/**
- * Get the value of `stat` method.
+ * Get audio file extension, like `mp3`.
*/
- public function getStat(): ?AudioStat
+ public function getExtension(): string
{
- return $this->stat;
+ return $this->extension;
}
/**
- * `Id3Reader` with metadata.
+ * Get audio format if recognized, like `AudioFormatEnum::mp3`.
*/
- public function getReader(): Id3Reader
+ public function getFormat(): AudioFormatEnum
{
- return $this->reader;
+ return $this->format;
}
/**
- * `Id3Writer` to update metadata.
+ * Get audio type if recognized, like `AudioTypeEnum::id3`.
*/
- public function getWriter(): ?Id3Writer
+ public function getType(): ?AudioTypeEnum
{
- return $this->writer;
+ return $this->type;
}
/**
- * Get `title` metadata.
+ * Get audio metadata.
*/
- public function getTitle(): ?string
+ public function getMetadata(): ?AudioMetadata
{
- return $this->title;
+ return $this->metadata;
}
/**
- * Get `artist` metadata.
+ * Get audio cover.
*/
- public function getArtist(): ?string
+ public function getCover(): ?AudioCover
{
- return $this->artist;
+ return $this->cover;
+ }
+
+ public function getId3Reader(): ?Id3Reader
+ {
+ return Id3Reader::make($this->path);
}
/**
- * Get `album` metadata.
+ * Get duration of the audio file in seconds, limited to 2 decimals, like `180.66`
+ *
+ * To get exact duration, use `getMetadata()->getDurationSeconds()` instead.
*/
- public function getAlbum(): ?string
+ public function getDuration(): ?float
{
- return $this->album;
+ return $this->duration;
}
/**
- * Get `genre` metadata.
+ * Get duration of the audio file in human readable format, like `00:03:00`
*/
- public function getGenre(): ?string
+ public function getDurationHuman(): ?string
{
- return $this->genre;
+ return gmdate('H:i:s', intval($this->duration));
}
/**
- * Get `year` metadata.
+ * To know if the audio file is writable.
*/
- public function getYear(): ?int
+ public function isWritable(): bool
{
- return $this->year;
+ return $this->is_writable;
}
/**
- * Get `trackNumber` metadata.
+ * To know if the audio file is valid.
*/
- public function getTrackNumber(): ?string
+ public function isValid(): bool
{
- return $this->trackNumber;
+ return $this->is_valid;
}
/**
- * Get `comment` metadata.
+ * To know if the audio file has cover.
*/
- public function getComment(): ?string
+ public function hasCover(): bool
{
- return $this->comment;
+ return $this->has_cover;
}
/**
- * Get `albumArtist` metadata.
+ * Get `title` tag, like `Another Brick In The Wall`.
*/
- public function getAlbumArtist(): ?string
+ public function getTitle(): ?string
{
- return $this->albumArtist;
+ return $this->title;
}
/**
- * Get `composer` metadata.
+ * Get `artist` tag, like `Pink Floyd`.
*/
- public function getComposer(): ?string
+ public function getArtist(): ?string
{
- return $this->composer;
+ return $this->artist;
}
/**
- * Get `discNumber` metadata.
+ * Get `album` tag, like `The Wall`.
*/
- public function getDiscNumber(): ?string
+ public function getAlbum(): ?string
{
- return $this->discNumber;
+ return $this->album;
}
/**
- * Know if audio file is a compilation.
+ * Get `genre` tag, like `Rock`.
*/
- public function isCompilation(): bool
+ public function getGenre(): ?string
{
- return $this->isCompilation;
+ return $this->genre;
}
/**
- * Get `creationDate` metadata for audiobook.
+ * Get `year` tag, like `1979`.
+ *
+ * - For `matroska` format: `date` tag.
+ * - For `ape` format: `date` tag.
*/
- public function getCreationDate(): ?string
+ public function getYear(): ?int
{
- return $this->creationDate;
+ return $this->year;
}
/**
- * Get `encodingBy` metadata for audiobook.
+ * Get `track_number` tag, like `1`.
+ *
+ * - For `vorbiscomment` format: `track_number` tag.
+ * - For `matroska` format: `part_number` tag.
+ * - For `ape` format: `track` tag.
*/
- public function getEncodingBy(): ?string
+ public function getTrackNumber(): ?string
{
- return $this->encodingBy;
+ return $this->track_number;
}
/**
- * Get `encoding` metadata for audiobook.
+ * Get `track_number` tag as integer, like `1`.
*/
- public function getEncoding(): ?string
+ public function getTrackNumberInt(): ?int
{
- return $this->encoding;
+ return $this->track_number ? intval($this->track_number) : null;
}
/**
- * Get `encoding` metadata for audiobook.
+ * Get `comment` tag, like `Recorded at Abbey Road Studios`.
*/
- public function getCopyright(): ?string
+ public function getComment(): ?string
{
- return $this->copyright;
+ return $this->comment;
}
/**
- * Get `description` metadata for audiobook.
+ * Get `album_artist` tag, like `Pink Floyd`.
+ *
+ * - For `id3v2` format: `band` tag.
+ * - For `asf` format: `albumartist` tag.
+ * - For `vorbiscomment` format: `albumartist` tag.
*/
- public function getDescription(): ?string
+ public function getAlbumArtist(): ?string
{
- return $this->description;
+ return $this->album_artist;
}
/**
- * Get `podcastDescription` metadata for audiobook.
+ * Get `composer` tag, like `Roger Waters`.
*/
- public function getPodcastDescription(): ?string
+ public function getComposer(): ?string
{
- return $this->podcastDescription;
+ return $this->composer;
}
/**
- * Get `language` metadata for audiobook.
+ * Get `disc_number` tag, like `1`.
+ *
+ * - For `id3v2` format: `part_of_a_set` tag.
+ * - For `asf` format: `partofset` tag.
+ * - For `vorbiscomment` format: `discnumber` tag.
+ * - For `matroska` format: `disc` tag.
+ * - For `ape` format: `disc` tag.
*/
- public function getLanguage(): ?string
+ public function getDiscNumber(): ?string
{
- return $this->language;
+ return $this->disc_number;
}
/**
- * Get `lyrics` metadata for audiobook.
+ * Get `disc_number` tag as integer, like `1`.
*/
- public function getLyrics(): ?string
+ public function getDiscNumberInt(): ?int
{
- return $this->lyrics;
+ if (str_contains($this->disc_number, '/')) {
+ $disc_number = explode('/', $this->disc_number);
+
+ return intval($disc_number[0]);
+ }
+
+ return $this->disc_number ? intval($this->disc_number) : null;
}
/**
- * Get `stik` metadata for audiobook.
+ * To know if the audio file is a compilation.
+ *
+ * - For `id3v2` format: `part_of_a_compilation` tag.
+ * - For `quicktime` format: `compilation` tag.
+ * - For `vorbiscomment` format: `compilation` tag.
+ * - For `matroska` format: `compilation` tag.
+ * - For `ape` format: `compilation` tag.
*/
- public function getStik(): ?string
+ public function isCompilation(): bool
{
- return $this->stik;
+ return $this->is_compilation;
}
/**
- * Get `duration` in seconds.
+ * Get `creation_date` tag, like `1979-11-30`.
+ *
+ * - For `matroska` format: `date` tag.
+ * - For `ape` format: `date` tag.
*/
- public function getDuration(): ?float
+ public function getCreationDate(): ?string
{
- return $this->duration;
+ return $this->creation_date;
}
/**
- * Get `duration` in human readable format: `00:00:00`.
+ * Get `encoding_by` tag, like `EAC`.
*/
- public function getDurationHumanReadable(): ?string
+ public function getEncodingBy(): ?string
{
- return gmdate('H:i:s', intval($this->duration));
+ return $this->encoding_by;
}
/**
- * Know if audio file is valid.
+ * Get `encoding` tag, like `LAME`.
*/
- public function isValid(): bool
+ public function getEncoding(): ?string
{
- return $this->isValid;
+ return $this->encoding;
}
/**
- * Get `extras` with raw metadata.
+ * Get `copyright` tag, like `© 1979 Pink Floyd`.
*/
- public function getExtras(): array
+ public function getCopyright(): ?string
{
- return $this->extras;
+ return $this->copyright;
}
/**
- * Get `audio` metadata with some audio information.
+ * Get `description` tag, like `The Wall is the eleventh studio album by the English rock band Pink Floyd`.
*/
- public function getAudio(): ?AudioMetadata
+ public function getDescription(): ?string
{
- return $this->audio;
+ return $this->description;
}
/**
- * Know if audio file has cover.
+ * Get `synopsis` tag, like `The Wall is the eleventh studio album by the English rock band Pink Floyd`.
+ *
+ * `description` and `synopsis` are not the same tag, but for many formats, they are the same.
*/
- public function hasCover(): bool
+ public function getSynopsis(): ?string
{
- return $this->hasCover;
+ return $this->synopsis;
}
/**
- * Get `cover` metadata with some cover information.
+ * Get `language` tag, like `en`.
*/
- public function getCover(): ?AudioCover
+ public function getLanguage(): ?string
{
- return $this->cover;
+ return $this->language;
}
/**
- * Get `path` of audio file.
+ * Get `lyrics` tag, like `We don't need no education`.
*/
- public function getPath(): string
+ public function getLyrics(): ?string
{
- return $this->path;
+ return $this->lyrics;
}
/**
- * Get `extension` of audio file.
+ * Get raw tags as array with all formats.
+ *
+ * For example, for `mp3` format: `['id3v1' => [...], 'id3v2' => [...]]`.
*/
- public function getgetExtension(): string
+ public function getRawTagsAll(): array
{
- return $this->extension;
+ return $this->raw_tags_all;
}
/**
- * Get `format` of audio file.
+ * Get raw tags as array with main format.
+ *
+ * For example, for `mp3` format, `id3v2` entry will be returned.
+ *
+ * @param string|null $format If not provided, main format will be returned.
+ * @return string[]
*/
- public function getFormat(): AudioFormatEnum
+ public function getRawTags(?string $format = null): ?array
{
- return $this->format;
+ if ($format) {
+ return $this->raw_tags_all[$format] ?? null;
+ }
+
+ $tags = match ($this->type) {
+ AudioTypeEnum::id3 => $this->raw_tags_all['id3v2'] ?? [],
+ AudioTypeEnum::vorbiscomment => $this->raw_tags_all['vorbiscomment'] ?? [],
+ AudioTypeEnum::quicktime => $this->raw_tags_all['quicktime'] ?? [],
+ AudioTypeEnum::matroska => $this->raw_tags_all['matroska'] ?? [],
+ AudioTypeEnum::ape => $this->raw_tags_all['ape'] ?? [],
+ AudioTypeEnum::asf => $this->raw_tags_all['asf'] ?? [],
+ default => [],
+ };
+
+ return $tags;
}
/**
- * Get `type` of audio file.
+ * Get raw tags key from main format.
+ *
+ * @param string $key Key name.
+ * @param string|null $format If not provided, main format will be used.
*/
- public function getType(): ?AudioTypeEnum
+ public function getRawTagsKey(string $key, ?string $format = null): ?string
{
- return $this->type;
+ $tags = $this->getRawTags($format);
+
+ return $tags[$key] ?? null;
}
- private function parse(): self
+ /**
+ * Get raw tags as array with main format, same as `getRawTags()`.
+ *
+ * @return string[]
+ */
+ public function getExtras(): array
{
- $raw = $this->getReader()->getRaw();
- $reader = $this->getReader();
+ return $this->getRawTags();
+ }
+ private function parseTags(?\Kiwilan\Audio\Id3\Id3Reader $id3_reader): self
+ {
$this->type = match ($this->format) {
AudioFormatEnum::aac => null,
AudioFormatEnum::aif => AudioTypeEnum::id3,
@@ -412,58 +464,42 @@ private function parse(): self
default => null,
};
- $tags = $reader->getTags();
- if (! $tags) {
+ $tags = $id3_reader->getTags();
+ if (! $tags || $tags->isEmpty()) {
return $this;
}
- $core = null;
- if ($this->type === AudioTypeEnum::id3) {
- $core = AudioCore::fromId3($tags->id3v1(), $tags->id3v2());
- $this->isValid = true;
- }
-
- if ($this->type === AudioTypeEnum::quicktime) {
- $core = AudioCore::fromQuicktime($tags->quicktime());
- $this->isValid = true;
- }
-
- if ($this->type === AudioTypeEnum::vorbiscomment) {
- $core = AudioCore::fromVorbisComment($tags->vorbiscomment());
- $this->isValid = true;
- }
-
- if ($this->type === AudioTypeEnum::asf) {
- $core = AudioCore::fromAsf($tags->asf());
- $this->isValid = true;
+ $raw_tags = $id3_reader->getRaw()['tags'] ?? [];
+ foreach ($raw_tags as $name => $raw_tag) {
+ $this->raw_tags_all[$name] = Id3Reader::cleanTags($raw_tag);
}
- if ($this->type === AudioTypeEnum::matroska) {
- $core = AudioCore::fromMatroska($tags->matroska());
- $this->isValid = true;
- }
+ $core = match ($this->type) {
+ AudioTypeEnum::id3 => AudioCore::fromId3($tags->id3v1(), $tags->id3v2()),
+ AudioTypeEnum::vorbiscomment => AudioCore::fromVorbisComment($tags->vorbiscomment()),
+ AudioTypeEnum::quicktime => AudioCore::fromQuicktime($tags->quicktime()),
+ AudioTypeEnum::matroska => AudioCore::fromMatroska($tags->matroska()),
+ AudioTypeEnum::ape => AudioCore::fromApe($tags->ape()),
+ AudioTypeEnum::asf => AudioCore::fromAsf($tags->asf()),
+ default => null,
+ };
- if ($this->type === AudioTypeEnum::ape) {
- $core = AudioCore::fromApe($tags->ape());
- $this->isValid = true;
+ if (! $core) {
+ return $this;
}
- $this->coreToProperties($core);
- $this->extras = $raw['tags'] ?? [];
-
- $this->audio = AudioMetadata::make($this);
- $this->cover = AudioCover::make($reader->getComments());
+ $this->convertCore($core);
+ $this->is_valid = true;
+ $this->cover = AudioCover::make($id3_reader->getComments());
if ($this->cover?->getContents()) {
- $this->hasCover = true;
+ $this->has_cover = true;
}
- $this->duration = number_format((float) $this->audio->getDurationSeconds(), 2, '.', '');
-
return $this;
}
- private function coreToProperties(?AudioCore $core): self
+ private function convertCore(?AudioCore $core): self
{
if (! $core) {
return $this;
@@ -474,66 +510,21 @@ private function coreToProperties(?AudioCore $core): self
$this->album = $core->getAlbum();
$this->genre = $core->getGenre();
$this->year = $core->getYear();
- $this->trackNumber = $core->getTrackNumber();
+ $this->track_number = $core->getTrackNumber();
$this->comment = $core->getComment();
- $this->albumArtist = $core->getAlbumArtist();
+ $this->album_artist = $core->getAlbumArtist();
$this->composer = $core->getComposer();
- $this->discNumber = $core->getDiscNumber();
- $this->isCompilation = $core->isCompilation();
- $this->creationDate = $core->getCreationDate();
- $this->encodingBy = $core->getEncodingBy();
+ $this->disc_number = $core->getDiscNumber();
+ $this->is_compilation = $core->isCompilation();
+ $this->creation_date = $core->getCreationDate();
+ $this->encoding_by = $core->getEncodingBy();
$this->encoding = $core->getEncoding();
$this->copyright = $core->getCopyright();
$this->description = $core->getDescription();
- $this->podcastDescription = $core->getPodcastDescription();
+ $this->synopsis = $core->getSynopsis();
$this->language = $core->getLanguage();
$this->lyrics = $core->getLyrics();
- $this->stik = $core->getStik();
return $this;
}
-
- /**
- * Get a specific tag.
- *
- * @param string $tag Tag name.
- * @param string|null $audioFormat Get a specific format, default format is format with maximum tags.
- */
- public function getTag(string $tag, ?string $audioFormat = null): ?string
- {
- $tags = $this->reader->toTags($audioFormat);
-
- return $tags[$tag] ?? null;
- }
-
- /**
- * Get all tags as array.
- *
- * @param string|null $tag Get a specific format, default format is format with maximum tags.
- * @return array
- */
- public function getTags(?string $audioFormat = null): array
- {
- return $this->reader->toTags($audioFormat);
- }
-
- /**
- * Get all audio formats as array, with tags.
- *
- * @return array>
- */
- public function getAudioFormats(): array
- {
- return $this->reader->toAudioFormats();
- }
-
- /**
- * Get all raw metadata as array.
- *
- * @return array
- */
- public function toArray(): array
- {
- return $this->reader->toArray();
- }
}
diff --git a/src/Core/AudioCore.php b/src/Core/AudioCore.php
new file mode 100644
index 0000000..79c7657
--- /dev/null
+++ b/src/Core/AudioCore.php
@@ -0,0 +1,624 @@
+title;
+ }
+
+ public function getArtist(): ?string
+ {
+ return $this->artist;
+ }
+
+ public function getAlbum(): ?string
+ {
+ return $this->album;
+ }
+
+ public function getGenre(): ?string
+ {
+ return $this->genre;
+ }
+
+ public function getYear(): ?int
+ {
+ return $this->year;
+ }
+
+ public function getTrackNumber(): ?string
+ {
+ return $this->track_number;
+ }
+
+ public function getComment(): ?string
+ {
+ return $this->comment;
+ }
+
+ public function getAlbumArtist(): ?string
+ {
+ return $this->album_artist;
+ }
+
+ public function getComposer(): ?string
+ {
+ return $this->composer;
+ }
+
+ public function getDiscNumber(): ?string
+ {
+ return $this->disc_number;
+ }
+
+ public function isCompilation(): bool
+ {
+ if ($this->is_compilation === null) {
+ return false;
+ }
+
+ return $this->is_compilation;
+ }
+
+ public function getCreationDate(): ?string
+ {
+ return $this->creation_date;
+ }
+
+ public function getCopyright(): ?string
+ {
+ return $this->copyright;
+ }
+
+ public function getEncodingBy(): ?string
+ {
+ return $this->encoding_by;
+ }
+
+ public function getEncoding(): ?string
+ {
+ return $this->encoding;
+ }
+
+ public function getDescription(): ?string
+ {
+ return $this->description;
+ }
+
+ public function getSynopsis(): ?string
+ {
+ return $this->synopsis;
+ }
+
+ public function getLanguage(): ?string
+ {
+ return $this->language;
+ }
+
+ public function getLyrics(): ?string
+ {
+ return $this->lyrics;
+ }
+
+ public function hasCover(): bool
+ {
+ return $this->has_cover;
+ }
+
+ public function getCover(): ?AudioCoreCover
+ {
+ return $this->cover;
+ }
+
+ public function setTitle(?string $title): self
+ {
+ $this->title = $title;
+
+ return $this;
+ }
+
+ public function setArtist(?string $artist): self
+ {
+ $this->artist = $artist;
+
+ return $this;
+ }
+
+ public function setAlbum(?string $album): self
+ {
+ $this->album = $album;
+
+ return $this;
+ }
+
+ public function setGenre(?string $genre): self
+ {
+ $this->genre = $genre;
+
+ return $this;
+ }
+
+ public function setYear(int $year): self
+ {
+ $this->year = $year;
+
+ return $this;
+ }
+
+ public function setTrackNumber(?string $track_number): self
+ {
+ $this->track_number = $track_number;
+
+ return $this;
+ }
+
+ public function setComment(?string $comment): self
+ {
+ $this->comment = $comment;
+
+ return $this;
+ }
+
+ public function setAlbumArtist(?string $album_artist): self
+ {
+ $this->album_artist = $album_artist;
+
+ return $this;
+ }
+
+ public function setComposer(?string $composer): self
+ {
+ $this->composer = $composer;
+
+ return $this;
+ }
+
+ public function setDiscNumber(?string $disc_number): self
+ {
+ $this->disc_number = $disc_number;
+
+ return $this;
+ }
+
+ public function setIsCompilation(bool $is_compilation): self
+ {
+ $this->is_compilation = $is_compilation;
+
+ return $this;
+ }
+
+ public function setCreationDate(?string $creation_date): self
+ {
+ $this->creation_date = $creation_date;
+
+ return $this;
+ }
+
+ public function setCopyright(?string $copyright): self
+ {
+ $this->copyright = $copyright;
+
+ return $this;
+ }
+
+ public function setEncodingBy(?string $encoding_by): self
+ {
+ $this->encoding_by = $encoding_by;
+
+ return $this;
+ }
+
+ public function setEncoding(?string $encoding): self
+ {
+ $this->encoding = $encoding;
+
+ return $this;
+ }
+
+ public function setDescription(?string $description): self
+ {
+ $this->description = $description;
+
+ return $this;
+ }
+
+ public function setPodcastDescription(?string $synopsis): self
+ {
+ $this->synopsis = $synopsis;
+
+ return $this;
+ }
+
+ public function setLanguage(?string $language): self
+ {
+ $this->language = $language;
+
+ return $this;
+ }
+
+ public function setLyrics(?string $lyrics): self
+ {
+ $this->lyrics = $lyrics;
+
+ return $this;
+ }
+
+ public function setHasCover(bool $has_cover): self
+ {
+ $this->has_cover = $has_cover;
+
+ return $this;
+ }
+
+ public function setCover(string $pathOrData): self
+ {
+ $this->cover = AudioCoreCover::make($pathOrData);
+
+ return $this;
+ }
+
+ public function toArray(): array
+ {
+ return [
+ 'title' => $this->title,
+ 'artist' => $this->artist,
+ 'album' => $this->album,
+ 'genre' => $this->genre,
+ 'year' => $this->year,
+ 'track_number' => $this->track_number,
+ 'comment' => $this->comment,
+ 'album_artist' => $this->album_artist,
+ 'composer' => $this->composer,
+ 'disc_number' => $this->disc_number,
+ 'is_compilation' => $this->is_compilation,
+ 'creation_date' => $this->creation_date,
+ 'encoding_by' => $this->encoding_by,
+ 'encoding' => $this->encoding,
+ 'description' => $this->description,
+ 'synopsis' => $this->synopsis,
+ 'language' => $this->language,
+ 'lyrics' => $this->lyrics,
+ 'has_cover' => $this->has_cover,
+ 'cover' => $this->cover?->toArray(),
+ ];
+ }
+
+ public static function toId3v2(AudioCore $core): Tag\Id3TagAudioV2
+ {
+ return new Tag\Id3TagAudioV2(
+ album: $core->getAlbum(),
+ artist: $core->getArtist(),
+ band: $core->getAlbumArtist(),
+ comment: $core->getComment(),
+ composer: $core->getComposer(),
+ part_of_a_set: $core->getDiscNumber(),
+ genre: $core->getGenre(),
+ part_of_a_compilation: $core->isCompilation() ? '1' : '0',
+ title: $core->getTitle(),
+ track_number: $core->getTrackNumber(),
+ year: (string) $core->getYear(),
+ copyright: $core->getCopyright(),
+ text: $core->getSynopsis(),
+ unsynchronised_lyric: $core->getLyrics(),
+ language: $core->getLanguage(),
+ );
+ }
+
+ public static function toId3v1(AudioCore $core): Tag\Id3TagAudioV1
+ {
+ return new Tag\Id3TagAudioV1(
+ album: $core->getAlbum(),
+ artist: $core->getArtist(),
+ comment: $core->getComment(),
+ genre: $core->getGenre(),
+ title: $core->getTitle(),
+ track_number: $core->getTrackNumber(),
+ year: (string) $core->getYear(),
+ );
+ }
+
+ public static function toVorbisComment(AudioCore $core): Tag\Id3TagVorbisComment
+ {
+ return new Tag\Id3TagVorbisComment(
+ album: $core->getAlbum(),
+ artist: $core->getArtist(),
+ albumartist: $core->getAlbumArtist(),
+ comment: $core->getComment(),
+ composer: $core->getComposer(),
+ compilation: $core->isCompilation() ? '1' : '0',
+ discnumber: $core->getDiscNumber(),
+ genre: $core->getGenre(),
+ title: $core->getTitle(),
+ tracknumber: $core->getTrackNumber(),
+ date: (string) $core->getYear(),
+ encoder: $core->getEncoding(),
+ description: $core->getDescription(),
+ );
+ }
+
+ public static function toQuicktime(AudioCore $core): Tag\Id3TagQuicktime
+ {
+ return new Tag\Id3TagQuicktime(
+ title: $core->getTitle(),
+ track_number: $core->getTrackNumber(),
+ disc_number: $core->getDiscNumber(),
+ compilation: $core->isCompilation() ? '1' : '0',
+ album: $core->getAlbum(),
+ genre: $core->getGenre(),
+ composer: $core->getComposer(),
+ creation_date: $core->getCreationDate(),
+ copyright: $core->getCopyright(),
+ artist: $core->getArtist(),
+ album_artist: $core->getAlbumArtist(),
+ encoded_by: $core->getEncoding(),
+ encoding_tool: $core->getEncoding(),
+ description: $core->getDescription(),
+ description_long: $core->getSynopsis(),
+ lyrics: $core->getLyrics(),
+ comment: $core->getComment(),
+ );
+ }
+
+ public static function toMatroska(AudioCore $core): Tag\Id3TagMatroska
+ {
+ return new Tag\Id3TagMatroska(
+ title: $core->getTitle(),
+ album: $core->getAlbum(),
+ artist: $core->getArtist(),
+ album_artist: $core->getAlbumArtist(),
+ comment: $core->getComment(),
+ composer: $core->getComposer(),
+ disc: $core->getDiscNumber(),
+ compilation: $core->isCompilation() ? '1' : '0',
+ genre: $core->getGenre(),
+ part_number: $core->getTrackNumber(),
+ date: (string) $core->getYear(),
+ encoder: $core->getEncoding(),
+ );
+ }
+
+ public static function toApe(AudioCore $core): Tag\Id3TagApe
+ {
+ return new Tag\Id3TagApe(
+ album: $core->getAlbum(),
+ artist: $core->getArtist(),
+ album_artist: $core->getAlbumArtist(),
+ comment: $core->getComment(),
+ composer: $core->getComposer(),
+ disc: $core->getDiscNumber(),
+ compilation: $core->isCompilation() ? '1' : '0',
+ genre: $core->getGenre(),
+ title: $core->getTitle(),
+ track: $core->getTrackNumber(),
+ date: (string) $core->getYear(),
+ encoder: $core->getEncoding(),
+ );
+ }
+
+ public static function toAsf(AudioCore $core): Tag\Id3TagAsf
+ {
+ return new Tag\Id3TagAsf(
+ album: $core->getAlbum(),
+ artist: $core->getArtist(),
+ albumartist: $core->getAlbumArtist(),
+ composer: $core->getComposer(),
+ partofset: $core->getDiscNumber(),
+ genre: $core->getGenre(),
+ track_number: $core->getTrackNumber(),
+ year: (string) $core->getYear(),
+ encodingsettings: $core->getEncoding(),
+ );
+ }
+
+ public static function fromId3(?Tag\Id3TagAudioV1 $v1, ?Tag\Id3TagAudioV2 $v2): AudioCore
+ {
+ if (! $v1) {
+ $v1 = new Tag\Id3TagAudioV1;
+ }
+
+ if (! $v2) {
+ $v2 = new Tag\Id3TagAudioV2;
+ }
+
+ return new AudioCore(
+ album: $v2->album ?? $v1->album,
+ artist: $v2->artist ?? $v1->artist,
+ album_artist: $v2->band ?? null,
+ comment: $v2->comment ?? $v1->comment,
+ composer: $v2->composer ?? null,
+ disc_number: $v2->part_of_a_set ?? null,
+ genre: $v2->genre ?? $v1->genre,
+ is_compilation: $v2->part_of_a_compilation === '1',
+ title: $v2->title ?? $v1->title,
+ track_number: $v2->track_number ?? $v1->track_number,
+ year: (int) ($v2->year ?? $v1->year),
+ copyright: $v2->copyright ?? null,
+ description: $v2->text ?? null,
+ lyrics: $v2->unsynchronised_lyric ?? null,
+ language: $v2->language ?? null,
+ );
+ }
+
+ public static function fromId3v2(Tag\Id3TagAudioV2 $tag): AudioCore
+ {
+ return new AudioCore(
+ album: $tag->album,
+ artist: $tag->artist,
+ album_artist: $tag->band,
+ comment: $tag->comment,
+ composer: $tag->composer,
+ disc_number: $tag->part_of_a_set,
+ genre: $tag->genre,
+ is_compilation: $tag->part_of_a_compilation === '1',
+ title: $tag->title,
+ track_number: $tag->track_number,
+ year: (int) $tag->year,
+ );
+ }
+
+ public static function fromId3v1(Tag\Id3TagAudioV1 $tag): AudioCore
+ {
+ return new AudioCore(
+ album: $tag->album,
+ artist: $tag->artist,
+ comment: $tag->comment,
+ genre: $tag->genre,
+ title: $tag->title,
+ track_number: $tag->track_number,
+ year: (int) $tag->year,
+ );
+ }
+
+ public static function fromQuicktime(Tag\Id3TagQuicktime $tag): AudioCore
+ {
+ $creation_date = $tag->creation_date;
+ $description = $tag->description;
+ $description_long = $tag->description_long;
+
+ $core = new AudioCore(
+ title: $tag->title,
+ artist: $tag->artist,
+ album: $tag->album,
+ genre: $tag->genre,
+ track_number: $tag->track_number,
+ disc_number: $tag->disc_number,
+ composer: $tag->composer,
+ is_compilation: $tag->compilation === '1',
+ comment: $tag->comment,
+ album_artist: $tag->album_artist,
+ encoding_by: $tag->encoded_by,
+ encoding: $tag->encoding_tool,
+ language: $tag->language,
+ );
+
+ if ($creation_date) {
+ if (strlen($creation_date) === 4) {
+ $core->setYear((int) $creation_date);
+ } else {
+ try {
+ $parsedCreationDate = new \DateTimeImmutable($creation_date);
+ } catch (\Exception $e) {
+ // ignore the issue so the rest of the data will be available
+ }
+
+ if (! empty($parsedCreationDate)) {
+ $core->setCreationDate($parsedCreationDate->format('Y-m-d\TH:i:s\Z'));
+ $core->setYear((int) $parsedCreationDate->format('Y'));
+ }
+ }
+ }
+
+ $core->setCopyright($tag->copyright);
+ $core->setDescription($description);
+ $core->setPodcastDescription($description_long);
+ $core->setLyrics($tag->lyrics);
+
+ return $core;
+ }
+
+ public static function fromVorbisComment(Tag\Id3TagVorbisComment $tag): AudioCore
+ {
+ return new AudioCore(
+ title: $tag->title,
+ artist: $tag->artist,
+ album: $tag->album,
+ genre: $tag->genre,
+ track_number: $tag->tracknumber,
+ comment: $tag->comment,
+ album_artist: $tag->albumartist,
+ composer: $tag->composer,
+ disc_number: $tag->discnumber,
+ is_compilation: $tag->compilation === '1',
+ year: (int) $tag->date,
+ encoding: $tag->encoder,
+ description: $tag->description,
+ );
+ }
+
+ public static function fromAsf(Tag\Id3TagAsf $tag): AudioCore
+ {
+ return new AudioCore(
+ title: $tag->title,
+ artist: $tag->artist,
+ album: $tag->album,
+ album_artist: $tag->albumartist,
+ composer: $tag->composer,
+ disc_number: $tag->partofset,
+ genre: $tag->genre,
+ track_number: $tag->track_number,
+ year: (int) $tag->year,
+ encoding: $tag->encodingsettings,
+ );
+ }
+
+ public static function fromMatroska(Tag\Id3TagMatroska $tag): AudioCore
+ {
+ return new AudioCore(
+ title: $tag->title,
+ album: $tag->album,
+ artist: $tag->artist,
+ album_artist: $tag->album_artist,
+ comment: $tag->comment,
+ composer: $tag->composer,
+ disc_number: $tag->disc,
+ genre: $tag->genre,
+ is_compilation: $tag->compilation === 'true',
+ track_number: $tag->part_number,
+ year: (int) $tag->date,
+ encoding: $tag->encoder,
+ );
+ }
+
+ public static function fromApe(Tag\Id3TagApe $tag): AudioCore
+ {
+ return new AudioCore(
+ album: $tag->album,
+ artist: $tag->artist,
+ album_artist: $tag->album_artist,
+ comment: $tag->comment,
+ composer: $tag->composer,
+ disc_number: $tag->disc,
+ genre: $tag->genre,
+ is_compilation: $tag->compilation === '1',
+ title: $tag->title,
+ track_number: $tag->track,
+ creation_date: $tag->date,
+ year: $tag->year ?? (int) $tag->date,
+ encoding: $tag->encoder,
+ description: $tag->description,
+ copyright: $tag->copyright,
+ lyrics: $tag->lyrics,
+ synopsis: $tag->podcastdesc,
+ language: $tag->language,
+ );
+ }
+}
diff --git a/src/Core/AudioCoreCover.php b/src/Core/AudioCoreCover.php
new file mode 100644
index 0000000..574b188
--- /dev/null
+++ b/src/Core/AudioCoreCover.php
@@ -0,0 +1,66 @@
+data = base64_encode(file_get_contents($pathOrData));
+ $self->picture_type_id = $image[2];
+ $self->description = 'cover';
+ $self->mime = $image['mime'];
+
+ return $self;
+ }
+
+ $image = getimagesizefromstring($pathOrData);
+ $self->data = base64_encode($pathOrData);
+ $self->picture_type_id = $image[2];
+ $self->mime = $image['mime'];
+ $self->description = 'cover';
+
+ return $self;
+ }
+
+ public function data(): ?string
+ {
+ return $this->data;
+ }
+
+ public function pictureTypeId(): ?int
+ {
+ return $this->picture_type_id;
+ }
+
+ public function description(): ?string
+ {
+ return $this->description;
+ }
+
+ public function mime(): ?string
+ {
+ return $this->mime;
+ }
+
+ public function toArray(): array
+ {
+ return [
+ 'data' => $this->data,
+ 'picture_type_id' => $this->picture_type_id,
+ 'description' => $this->description,
+ 'mime' => $this->mime,
+ ];
+ }
+}
diff --git a/src/Id3/Id3Reader.php b/src/Id3/Id3Reader.php
new file mode 100644
index 0000000..eae4a5e
--- /dev/null
+++ b/src/Id3/Id3Reader.php
@@ -0,0 +1,240 @@
+raw = $self->instance->analyze($path);
+ $self->is_writable = $self->instance->is_writable($path);
+ $metadata = $self->raw;
+
+ $audio = Id3Audio::make($metadata['audio'] ?? null);
+ $video = Id3Video::make($metadata['video'] ?? null);
+ $tags = Id3AudioTag::make($metadata['tags'] ?? null);
+ $comments = Id3Comments::make($metadata['comments'] ?? null);
+
+ $bitrate = $metadata['bitrate'] ?? null;
+ if ($bitrate) {
+ $bitrate = intval($bitrate);
+ }
+
+ $self->version = $metadata['GETID3_VERSION'] ?? null;
+ $self->file_size = $metadata['filesize'] ?? null;
+ $self->file_path = $metadata['filepath'] ?? null;
+ $self->filename = $metadata['filename'] ?? null;
+ $self->filename_path = $metadata['filenamepath'] ?? null;
+ $self->av_data_offset = $metadata['avdataoffset'] ?? null;
+ $self->av_data_end = $metadata['avdataend'] ?? null;
+ $self->file_format = $metadata['fileformat'] ?? null;
+ $self->audio = $audio;
+ $self->video = $video;
+ $self->tags = $tags;
+ $self->comments = $comments;
+ $self->encoding = $metadata['encoding'] ?? null;
+ $self->mime_type = $metadata['mime_type'] ?? null;
+ $self->mpeg = $metadata['mpeg'] ?? null;
+ $self->playtime_seconds = $metadata['playtime_seconds'] ?? null;
+ $self->bitrate = $bitrate;
+ $self->playtime_string = $metadata['playtime_string'] ?? null;
+
+ return $self;
+ }
+
+ public function getInstance(): getID3
+ {
+ return $this->instance;
+ }
+
+ public function getVersion(): ?string
+ {
+ return $this->version;
+ }
+
+ public function getFileSize(): ?int
+ {
+ return $this->file_size;
+ }
+
+ public function getFilePath(): ?string
+ {
+ return $this->file_path;
+ }
+
+ public function getFilename(): ?string
+ {
+ return $this->filename;
+ }
+
+ public function getFilenamePath(): ?string
+ {
+ return $this->filename_path;
+ }
+
+ public function getAvDataOffset(): ?int
+ {
+ return $this->av_data_offset;
+ }
+
+ public function getAvDataEnd(): ?int
+ {
+ return $this->av_data_end;
+ }
+
+ public function getFileFormat(): ?string
+ {
+ return $this->file_format;
+ }
+
+ public function getAudio(): ?Id3Audio
+ {
+ return $this->audio;
+ }
+
+ public function getTags(): ?Id3AudioTag
+ {
+ return $this->tags;
+ }
+
+ public function getComments(): ?Id3Comments
+ {
+ return $this->comments;
+ }
+
+ public function getEncoding(): ?string
+ {
+ return $this->encoding;
+ }
+
+ public function getMimeType(): ?string
+ {
+ return $this->mime_type;
+ }
+
+ public function getMpeg(): mixed
+ {
+ return $this->mpeg;
+ }
+
+ public function getPlaytimeSeconds(): ?float
+ {
+ return $this->playtime_seconds;
+ }
+
+ public function getBitrate(): ?float
+ {
+ return $this->bitrate;
+ }
+
+ public function getPlaytimeString(): ?string
+ {
+ return $this->playtime_string;
+ }
+
+ public function isWritable(): bool
+ {
+ return $this->is_writable;
+ }
+
+ public function getRaw(): array
+ {
+ return $this->raw;
+ }
+
+ public function toTags(?string $audioFormat = null): array
+ {
+ $rawTags = $this->raw['tags_html'] ?? [];
+
+ if (count($rawTags) === 0) {
+ return [];
+ }
+
+ $tagsItems = [];
+ if ($audioFormat) {
+ $tagsItems = $rawTags[$audioFormat] ?? [];
+ } else {
+ if (count($rawTags) > 1) {
+ $entries = [];
+ foreach ($rawTags as $key => $keyTags) {
+ $entries[$key] = count($keyTags);
+ }
+ $maxKey = array_search(max($entries), $entries);
+ $tagsItems = $rawTags[$maxKey] ?? [];
+ } else {
+ $tagsItems = reset($rawTags);
+ }
+ }
+
+ return Id3Reader::cleanTags($tagsItems);
+ }
+
+ public static function cleanTags(?array $tagsItems): array
+ {
+ if (! $tagsItems) {
+ return [];
+ }
+
+ $temp = [];
+ foreach ($tagsItems as $k => $v) {
+ $temp[$k] = $v[0] ?? null;
+ }
+
+ $items = [];
+ foreach ($temp as $k => $v) {
+ $k = strtolower($k);
+ $k = str_replace(' ', '_', $k);
+ $items[$k] = $v;
+ }
+
+ return $items;
+ }
+
+ public function toAudioFormats(): array
+ {
+ return $this->raw['tags_html'] ?? [];
+ }
+
+ public function toArray(): array
+ {
+ $raw = $this->raw;
+ $raw['id3v2']['APIC'] = null;
+ $raw['ape']['items']['cover art (front)'] = null;
+ $raw['comments'] = null;
+
+ return $raw;
+ }
+}
diff --git a/src/Id3/Reader/Id3Audio.php b/src/Id3/Reader/Id3Audio.php
new file mode 100644
index 0000000..348bd27
--- /dev/null
+++ b/src/Id3/Reader/Id3Audio.php
@@ -0,0 +1,94 @@
+streams = $streams;
+
+ return $self;
+ }
+
+ /** @return Id3Stream[] */
+ public function streams(): array
+ {
+ return $this->streams;
+ }
+
+ public function dataFormat(): ?string
+ {
+ return $this->data_format;
+ }
+
+ public function channels(): ?int
+ {
+ return $this->channels;
+ }
+
+ public function sampleRate(): ?int
+ {
+ return $this->sample_rate;
+ }
+
+ public function bitrate(): ?float
+ {
+ return $this->bitrate;
+ }
+
+ public function channelMode(): ?string
+ {
+ return $this->channel_mode;
+ }
+
+ public function bitrateMode(): ?string
+ {
+ return $this->bitrate_mode;
+ }
+
+ public function codec(): ?string
+ {
+ return $this->codec;
+ }
+
+ public function encoder(): ?string
+ {
+ return $this->encoder;
+ }
+
+ public function lossless(): bool
+ {
+ return $this->lossless;
+ }
+
+ public function encoderOptions(): ?string
+ {
+ return $this->encoder_options;
+ }
+
+ public function compressionRatio(): ?float
+ {
+ return $this->compression_ratio;
+ }
+
+ public function stream(): ?Id3Stream
+ {
+ return $this->streams[0] ?? null;
+ }
+}
diff --git a/src/Id3/Reader/Id3AudioBase.php b/src/Id3/Reader/Id3AudioBase.php
new file mode 100644
index 0000000..0a97dfb
--- /dev/null
+++ b/src/Id3/Reader/Id3AudioBase.php
@@ -0,0 +1,102 @@
+data_format = $metadata['dataformat'] ?? null;
+ $this->channels = $metadata['channels'] ?? null;
+ $this->sample_rate = $metadata['sample_rate'] ?? null;
+ $this->bitrate = $metadata['bitrate'] ?? null;
+ $this->channel_mode = $metadata['channelmode'] ?? null;
+ $this->bitrate_mode = $metadata['bitrate_mode'] ?? null;
+ $this->codec = $metadata['codec'] ?? null;
+ $this->encoder = $metadata['encoder'] ?? null;
+ $this->lossless = $metadata['lossless'] ?? false;
+ $this->encoder_options = $metadata['encoder_options'] ?? null;
+ $this->compression_ratio = $metadata['compression_ratio'] ?? null;
+ }
+
+ public function dataFormat(): ?string
+ {
+ return $this->data_format;
+ }
+
+ public function channels(): ?int
+ {
+ return $this->channels;
+ }
+
+ public function sampleRate(): ?int
+ {
+ return $this->sample_rate;
+ }
+
+ public function bitrate(): ?float
+ {
+ return $this->bitrate;
+ }
+
+ public function channelMode(): ?string
+ {
+ return $this->channel_mode;
+ }
+
+ public function bitrateMode(): ?string
+ {
+ return $this->bitrate_mode;
+ }
+
+ public function codec(): ?string
+ {
+ return $this->codec;
+ }
+
+ public function encoder(): ?string
+ {
+ return $this->encoder;
+ }
+
+ public function lossless(): bool
+ {
+ return $this->lossless;
+ }
+
+ public function encoderOptions(): ?string
+ {
+ return $this->encoder_options;
+ }
+
+ public function compressionRatio(): ?float
+ {
+ return $this->compression_ratio;
+ }
+}
diff --git a/src/Id3/Reader/Id3AudioTag.php b/src/Id3/Reader/Id3AudioTag.php
new file mode 100644
index 0000000..53ee36d
--- /dev/null
+++ b/src/Id3/Reader/Id3AudioTag.php
@@ -0,0 +1,99 @@
+id3v1 && ! $self->id3v2 && ! $self->quicktime && ! $self->asf && ! $self->vorbiscomment && ! $self->riff && ! $self->matroska && ! $self->ape) {
+ $self->is_empty = true;
+ }
+
+ return $self;
+ }
+
+ public function id3v1(): ?Tag\Id3TagAudioV1
+ {
+ return $this->id3v1;
+ }
+
+ public function id3v2(): ?Tag\Id3TagAudioV2
+ {
+ return $this->id3v2;
+ }
+
+ public function quicktime(): ?Tag\Id3TagQuicktime
+ {
+ return $this->quicktime;
+ }
+
+ public function asf(): ?Tag\Id3TagAsf
+ {
+ return $this->asf;
+ }
+
+ public function vorbiscomment(): ?Tag\Id3TagVorbisComment
+ {
+ return $this->vorbiscomment;
+ }
+
+ public function riff(): ?Tag\Id3TagRiff
+ {
+ return $this->riff;
+ }
+
+ public function matroska(): ?Tag\Id3TagMatroska
+ {
+ return $this->matroska;
+ }
+
+ public function ape(): ?Tag\Id3TagApe
+ {
+ return $this->ape;
+ }
+
+ public function isEmpty(): bool
+ {
+ return $this->is_empty;
+ }
+}
diff --git a/src/Id3/Reader/Id3Comments.php b/src/Id3/Reader/Id3Comments.php
new file mode 100644
index 0000000..c0156f9
--- /dev/null
+++ b/src/Id3/Reader/Id3Comments.php
@@ -0,0 +1,28 @@
+title;
- }
-
- public function getArtist(): ?string
- {
- return $this->artist;
- }
-
- public function getAlbum(): ?string
- {
- return $this->album;
- }
-
- public function getGenre(): ?string
- {
- return $this->genre;
- }
-
- public function getYear(): ?int
- {
- return $this->year;
- }
-
- public function getTrackNumber(): ?string
- {
- return $this->trackNumber;
- }
-
- public function getComment(): ?string
- {
- return $this->comment;
- }
-
- public function getAlbumArtist(): ?string
- {
- return $this->albumArtist;
- }
-
- public function getComposer(): ?string
- {
- return $this->composer;
- }
-
- public function getDiscNumber(): ?string
- {
- return $this->discNumber;
- }
-
- public function isCompilation(): bool
- {
- if ($this->isCompilation === null) {
- return false;
- }
-
- return $this->isCompilation;
- }
-
- public function getCreationDate(): ?string
- {
- return $this->creationDate;
- }
-
- public function getCopyright(): ?string
- {
- return $this->copyright;
- }
-
- public function getEncodingBy(): ?string
- {
- return $this->encodingBy;
- }
-
- public function getEncoding(): ?string
- {
- return $this->encoding;
- }
-
- public function getDescription(): ?string
- {
- return $this->description;
- }
-
- public function getPodcastDescription(): ?string
- {
- return $this->podcastDescription;
- }
-
- public function getLanguage(): ?string
- {
- return $this->language;
- }
-
- public function getLyrics(): ?string
- {
- return $this->lyrics;
- }
-
- public function getStik(): ?string
- {
- return $this->stik;
- }
-
- public function hasCover(): bool
- {
- return $this->hasCover;
- }
-
- public function getCover(): ?AudioCoreCover
- {
- return $this->cover;
- }
-
- public function setTitle(?string $title): self
- {
- $this->title = $title;
-
- return $this;
- }
-
- public function setArtist(?string $artist): self
- {
- $this->artist = $artist;
-
- return $this;
- }
-
- public function setAlbum(?string $album): self
- {
- $this->album = $album;
-
- return $this;
- }
-
- public function setGenre(?string $genre): self
- {
- $this->genre = $genre;
-
- return $this;
- }
-
- public function setYear(int $year): self
- {
- $this->year = $year;
-
- return $this;
- }
-
- public function setTrackNumber(?string $trackNumber): self
- {
- $this->trackNumber = $trackNumber;
-
- return $this;
- }
-
- public function setComment(?string $comment): self
- {
- $this->comment = $comment;
-
- return $this;
- }
-
- public function setAlbumArtist(?string $albumArtist): self
- {
- $this->albumArtist = $albumArtist;
-
- return $this;
- }
-
- public function setComposer(?string $composer): self
- {
- $this->composer = $composer;
-
- return $this;
- }
-
- public function setDiscNumber(?string $discNumber): self
- {
- $this->discNumber = $discNumber;
-
- return $this;
- }
-
- public function setIsCompilation(bool $isCompilation): self
- {
- $this->isCompilation = $isCompilation;
-
- return $this;
- }
-
- public function setCreationDate(?string $creationDate): self
- {
- $this->creationDate = $creationDate;
-
- return $this;
- }
-
- public function setCopyright(?string $copyright): self
- {
- $this->copyright = $copyright;
-
- return $this;
- }
-
- public function setEncodingBy(?string $encodingBy): self
- {
- $this->encodingBy = $encodingBy;
-
- return $this;
- }
-
- public function setEncoding(?string $encoding): self
- {
- $this->encoding = $encoding;
-
- return $this;
- }
-
- public function setDescription(?string $description): self
- {
- $this->description = $description;
-
- return $this;
- }
-
- public function setPodcastDescription(?string $podcastDescription): self
- {
- $this->podcastDescription = $podcastDescription;
-
- return $this;
- }
-
- public function setLanguage(?string $language): self
- {
- $this->language = $language;
-
- return $this;
- }
-
- public function setLyrics(?string $lyrics): self
- {
- $this->lyrics = $lyrics;
-
- return $this;
- }
-
- public function setStik(?string $stik): self
- {
- $this->stik = $stik;
-
- return $this;
- }
-
- public function setHasCover(bool $hasCover): self
- {
- $this->hasCover = $hasCover;
-
- return $this;
- }
-
- public function setCover(string $pathOrData): self
- {
- $this->cover = AudioCoreCover::make($pathOrData);
-
- return $this;
- }
-
- public function toArray(): array
- {
- return [
- 'title' => $this->title,
- 'artist' => $this->artist,
- 'album' => $this->album,
- 'genre' => $this->genre,
- 'year' => $this->year,
- 'trackNumber' => $this->trackNumber,
- 'comment' => $this->comment,
- 'albumArtist' => $this->albumArtist,
- 'composer' => $this->composer,
- 'discNumber' => $this->discNumber,
- 'isCompilation' => $this->isCompilation,
- 'creationDate' => $this->creationDate,
- 'encodingBy' => $this->encodingBy,
- 'encoding' => $this->encoding,
- 'description' => $this->description,
- 'podcastDescription' => $this->podcastDescription,
- 'language' => $this->language,
- 'lyrics' => $this->lyrics,
- 'stik' => $this->stik,
- 'hasCover' => $this->hasCover,
- 'cover' => $this->cover?->toArray(),
- ];
- }
-
- public static function toId3v2(AudioCore $core): Id3AudioTagV2
- {
- return new Id3AudioTagV2(
- album: $core->getAlbum(),
- artist: $core->getArtist(),
- band: $core->getAlbumArtist(),
- comment: $core->getComment(),
- composer: $core->getComposer(),
- part_of_a_set: $core->getDiscNumber(),
- genre: $core->getGenre(),
- part_of_a_compilation: $core->isCompilation() ? '1' : '0',
- title: $core->getTitle(),
- track_number: $core->getTrackNumber(),
- year: $core->getYear(),
- copyright: $core->getCopyright(),
- text: $core->getPodcastDescription(),
- unsynchronised_lyric: $core->getLyrics(),
- language: $core->getLanguage(),
- );
- }
-
- public static function toId3v1(AudioCore $core): Id3AudioTagV1
- {
- return new Id3AudioTagV1(
- album: $core->getAlbum(),
- artist: $core->getArtist(),
- comment: $core->getComment(),
- genre: $core->getGenre(),
- title: $core->getTitle(),
- track_number: $core->getTrackNumber(),
- year: $core->getYear(),
- );
- }
-
- public static function toVorbisComment(AudioCore $core): Id3TagVorbisComment
- {
- return new Id3TagVorbisComment(
- album: $core->getAlbum(),
- artist: $core->getArtist(),
- albumartist: $core->getAlbumArtist(),
- comment: $core->getComment(),
- composer: $core->getComposer(),
- compilation: $core->isCompilation() ? '1' : '0',
- discnumber: $core->getDiscNumber(),
- genre: $core->getGenre(),
- title: $core->getTitle(),
- tracknumber: $core->getTrackNumber(),
- date: $core->getYear(),
- encoder: $core->getEncoding(),
- description: $core->getDescription(),
- );
- }
-
- public static function toQuicktime(AudioCore $core): Id3TagQuicktime
- {
- return new Id3TagQuicktime(
- title: $core->getTitle(),
- track_number: $core->getTrackNumber(),
- disc_number: $core->getDiscNumber(),
- compilation: $core->isCompilation() ? '1' : '0',
- album: $core->getAlbum(),
- genre: $core->getGenre(),
- composer: $core->getComposer(),
- creation_date: $core->getCreationDate(),
- copyright: $core->getCopyright(),
- artist: $core->getArtist(),
- album_artist: $core->getAlbumArtist(),
- encoded_by: $core->getEncoding(),
- encoding_tool: $core->getEncoding(),
- description: $core->getDescription(),
- description_long: $core->getPodcastDescription(),
- lyrics: $core->getLyrics(),
- comment: $core->getComment(),
- stik: $core->getStik(),
- );
- }
-
- public static function toMatroska(AudioCore $core): Id3TagMatroska
- {
- return new Id3TagMatroska(
- title: $core->getTitle(),
- album: $core->getAlbum(),
- artist: $core->getArtist(),
- album_artist: $core->getAlbumArtist(),
- comment: $core->getComment(),
- composer: $core->getComposer(),
- disc: $core->getDiscNumber(),
- compilation: $core->isCompilation() ? '1' : '0',
- genre: $core->getGenre(),
- part_number: $core->getTrackNumber(),
- date: $core->getYear(),
- encoder: $core->getEncoding(),
- );
- }
-
- public static function toApe(AudioCore $core): Id3TagApe
- {
- return new Id3TagApe(
- album: $core->getAlbum(),
- artist: $core->getArtist(),
- album_artist: $core->getAlbumArtist(),
- comment: $core->getComment(),
- composer: $core->getComposer(),
- disc: $core->getDiscNumber(),
- compilation: $core->isCompilation() ? '1' : '0',
- genre: $core->getGenre(),
- title: $core->getTitle(),
- track: $core->getTrackNumber(),
- date: $core->getYear(),
- encoder: $core->getEncoding(),
- );
- }
-
- public static function toAsf(AudioCore $core): Id3TagAsf
- {
- return new Id3TagAsf(
- album: $core->getAlbum(),
- artist: $core->getArtist(),
- albumartist: $core->getAlbumArtist(),
- composer: $core->getComposer(),
- partofset: $core->getDiscNumber(),
- genre: $core->getGenre(),
- track_number: $core->getTrackNumber(),
- year: $core->getYear(),
- encodingsettings: $core->getEncoding(),
- );
- }
-
- public static function fromId3(?Id3AudioTagV1 $v1, ?Id3AudioTagV2 $v2): AudioCore
- {
- if (! $v1) {
- $v1 = new Id3AudioTagV1;
- }
-
- if (! $v2) {
- $v2 = new Id3AudioTagV2;
- }
-
- return new AudioCore(
- album: $v2->album() ?? $v1->album(),
- artist: $v2->artist() ?? $v1->artist(),
- albumArtist: $v2->band() ?? null,
- comment: $v2->comment() ?? $v1->comment(),
- composer: $v2->composer() ?? null,
- discNumber: $v2->part_of_a_set() ?? null,
- genre: $v2->genre() ?? $v1->genre(),
- isCompilation: $v2->part_of_a_compilation() === '1',
- title: $v2->title() ?? $v1->title(),
- trackNumber: $v2->track_number() ?? $v1->track_number(),
- year: $v2->year() ?? $v1->year(),
- copyright: $v2->copyright() ?? null,
- description: $v2->text() ?? null,
- lyrics: $v2->unsynchronised_lyric() ?? null,
- language: $v2->language() ?? null,
- );
- }
-
- public static function fromId3v2(Id3AudioTagV2 $tag): AudioCore
- {
- return new AudioCore(
- album: $tag->album(),
- artist: $tag->artist(),
- albumArtist: $tag->band(),
- comment: $tag->comment(),
- composer: $tag->composer(),
- discNumber: $tag->part_of_a_set(),
- genre: $tag->genre(),
- isCompilation: $tag->part_of_a_compilation() === '1',
- title: $tag->title(),
- trackNumber: $tag->track_number(),
- year: $tag->year(),
- );
- }
-
- public static function fromId3v1(Id3AudioTagV1 $tag): AudioCore
- {
- return new AudioCore(
- album: $tag->album(),
- artist: $tag->artist(),
- comment: $tag->comment(),
- genre: $tag->genre(),
- title: $tag->title(),
- trackNumber: $tag->track_number(),
- year: $tag->year(),
- );
- }
-
- public static function fromQuicktime(Id3TagQuicktime $tag): AudioCore
- {
-
- $creation_date = $tag->creation_date();
- $description = $tag->description();
- $description_long = $tag->description_long();
-
- $core = new AudioCore(
- title: $tag->title(),
- artist: $tag->artist(),
- album: $tag->album(),
- genre: $tag->genre(),
- trackNumber: $tag->track_number(),
- discNumber: $tag->disc_number(),
- composer: $tag->composer(),
- isCompilation: $tag->compilation() === '1',
- comment: $tag->comment(),
- albumArtist: $tag->album_artist(),
- encodingBy: $tag->encoded_by(),
- encoding: $tag->encoding_tool(),
- language: $tag->language(),
- );
-
- if ($creation_date) {
- if (strlen($creation_date) === 4) {
- $core->setYear((int) $creation_date);
- } else {
- try {
- $parsedCreationDate = new \DateTimeImmutable($creation_date);
- } catch (\Exception $e) {
- // ignore the issue so the rest of the data will be available
- }
-
- if (! empty($parsedCreationDate)) {
- $core->setCreationDate($parsedCreationDate->format('Y-m-d\TH:i:s\Z'));
- $core->setYear((int) $parsedCreationDate->format('Y'));
- }
- }
- }
-
- $core->setCopyright($tag->copyright());
- $core->setDescription($description);
- $core->setPodcastDescription($description_long);
- $core->setLyrics($tag->lyrics());
- $core->setStik($tag->stik());
-
- return $core;
- }
-
- public static function fromVorbisComment(Id3TagVorbisComment $tag): AudioCore
- {
- return new AudioCore(
- title: $tag->title(),
- artist: $tag->artist(),
- album: $tag->album(),
- genre: $tag->genre(),
- trackNumber: $tag->trackNumber(),
- comment: $tag->comment(),
- albumArtist: $tag->albumartist(),
- composer: $tag->composer(),
- discNumber: $tag->discNumber(),
- isCompilation: $tag->compilation() === '1',
- year: (int) $tag->date(),
- encoding: $tag->encoder(),
- description: $tag->description(),
- );
- }
-
- public static function fromAsf(Id3TagAsf $tag): AudioCore
- {
- return new AudioCore(
- title: $tag->title(),
- artist: $tag->artist(),
- album: $tag->album(),
- albumArtist: $tag->albumartist(),
- composer: $tag->composer(),
- discNumber: $tag->partofset(),
- genre: $tag->genre(),
- trackNumber: $tag->track_number(),
- year: (int) $tag->year(),
- encoding: $tag->encodingsettings(),
- );
- }
-
- public static function fromMatroska(Id3TagMatroska $tag): AudioCore
- {
- return new AudioCore(
- title: $tag->title(),
- album: $tag->album(),
- artist: $tag->artist(),
- albumArtist: $tag->album_artist(),
- comment: $tag->comment(),
- composer: $tag->composer(),
- discNumber: $tag->disc(),
- genre: $tag->genre(),
- isCompilation: $tag->compilation(),
- trackNumber: $tag->part_number(),
- year: (int) $tag->date(),
- encoding: $tag->encoder(),
- );
- }
-
- public static function fromApe(Id3TagApe $tag): AudioCore
- {
- return new AudioCore(
- album: $tag->album(),
- artist: $tag->artist(),
- albumArtist: $tag->album_artist(),
- comment: $tag->comment(),
- composer: $tag->composer(),
- discNumber: $tag->disc(),
- genre: $tag->genre(),
- isCompilation: $tag->compilation() === '1',
- title: $tag->title(),
- trackNumber: $tag->track(),
- creationDate: $tag->date(),
- year: $tag->year() ?? (int) $tag->date(),
- encoding: $tag->encoder(),
- description: $tag->description(),
- copyright: $tag->copyright(),
- lyrics: $tag->lyrics(),
- podcastDescription: $tag->podcastdesc(),
- language: $tag->language(),
- );
- }
-}
-
-class AudioCoreCover
-{
- public function __construct(
- protected ?string $data = null,
- protected ?string $picturetypeid = null,
- protected ?string $description = null,
- protected ?string $mime = null,
- ) {}
-
- public static function make(string $pathOrData): self
- {
- $self = new self;
-
- if (file_exists($pathOrData)) {
- $image = getimagesize($pathOrData);
- $self->data = base64_encode(file_get_contents($pathOrData));
- $self->picturetypeid = $image[2];
- $self->description = 'cover';
- $self->mime = $image['mime'];
-
- return $self;
- }
-
- $image = getimagesizefromstring($pathOrData);
- $self->data = base64_encode($pathOrData);
- $self->picturetypeid = $image[2];
- $self->mime = $image['mime'];
- $self->description = 'cover';
-
- return $self;
- }
-
- public function data(): ?string
- {
- return $this->data;
- }
-
- public function picturetypeid(): ?string
- {
- return $this->picturetypeid;
- }
-
- public function description(): ?string
- {
- return $this->description;
- }
-
- public function mime(): ?string
- {
- return $this->mime;
- }
-
- public function toArray(): array
- {
- return [
- 'data' => $this->data,
- 'picturetypeid' => $this->picturetypeid,
- 'description' => $this->description,
- 'mime' => $this->mime,
- ];
- }
-}
diff --git a/src/Models/AudioCover.php b/src/Models/AudioCover.php
index 201c119..24ff8df 100644
--- a/src/Models/AudioCover.php
+++ b/src/Models/AudioCover.php
@@ -2,55 +2,66 @@
namespace Kiwilan\Audio\Models;
+use Kiwilan\Audio\Id3\Reader\Id3Comments;
+
class AudioCover
{
- protected ?string $contents = null;
-
- protected ?string $mimeType = null;
-
- protected ?int $width = null;
-
- protected ?int $height = null;
+ protected function __construct(
+ protected ?string $contents = null,
+ protected ?string $mime_type = null,
+ protected ?int $width = null,
+ protected ?int $height = null,
+ ) {}
public static function make(?Id3Comments $comments): ?self
{
- if (! $comments) {
+ if (! $comments || ! $comments->picture) {
return null;
}
$self = new self;
- $self->contents = $comments->picture()->data();
- $self->mimeType = $comments->picture()->image_mime();
- $self->width = $comments->picture()->image_width();
- $self->height = $comments->picture()->image_height();
+ $self->contents = base64_encode($comments->picture->data);
+ $self->mime_type = $comments->picture->image_mime;
+ $self->width = $comments->picture->image_width;
+ $self->height = $comments->picture->image_height;
return $self;
}
/**
- * @deprecated Use `getContents()` instead.
+ * Get the contents of the cover
+ *
+ * By default, the contents are decoded from base64, but you can get the raw contents by passing `true` as the first argument.
*/
- public function getContent(): ?string
+ public function getContents(bool $base64 = false): ?string
{
- return $this->contents;
- }
+ if (! $this->contents) {
+ return null;
+ }
- public function getContents(): ?string
- {
- return $this->contents;
+ return $base64 ? $this->contents : base64_decode($this->contents);
}
+ /**
+ * Get the MIME type of the cover
+ */
public function getMimeType(): ?string
{
- return $this->mimeType;
+ return $this->mime_type;
}
+ /**
+ * Get the width of the cover
+ */
public function getWidth(): ?int
{
return $this->width;
}
+ /**
+ * Get the height of the cover
+ */
public function getHeight(): ?int
{
return $this->height;
diff --git a/src/Models/AudioMetadata.php b/src/Models/AudioMetadata.php
index 0e04738..909bec8 100644
--- a/src/Models/AudioMetadata.php
+++ b/src/Models/AudioMetadata.php
@@ -2,125 +2,264 @@
namespace Kiwilan\Audio\Models;
+use DateTime;
use Kiwilan\Audio\Audio;
+use Kiwilan\Audio\Id3\Id3Reader;
class AudioMetadata
{
protected function __construct(
- protected ?string $path = null,
- protected ?int $filesize = null,
- protected ?string $extension = null,
- protected ?string $dataformat = null,
+ protected ?int $file_size = null,
+ protected ?string $data_format = null,
protected ?string $encoding = null,
- protected ?string $mimeType = null,
- protected ?float $durationSeconds = null,
- protected ?string $durationReadable = null,
+ protected ?string $mime_type = null,
+ protected ?float $duration_seconds = null,
protected ?int $bitrate = null,
- protected ?string $bitrateMode = null,
- protected ?int $sampleRate = null,
+ protected ?string $bitrate_mode = null,
+ protected ?int $sample_rate = null,
protected ?int $channels = null,
- protected ?string $channelMode = null,
- protected bool $lossless = false,
- protected ?float $compressionRatio = null,
+ protected ?string $channel_mode = null,
+ protected bool $is_lossless = false,
+ protected ?float $compression_ratio = null,
+ protected ?string $codec = null,
+ protected ?string $encoder_options = null,
+ protected ?string $version = null,
+ protected ?int $av_data_offset = null,
+ protected ?int $av_data_end = null,
+ protected ?string $file_path = null,
+ protected ?string $filename = null,
+ protected ?DateTime $last_access_at = null,
+ protected ?DateTime $created_at = null,
+ protected ?DateTime $modified_at = null,
) {}
- public static function make(Audio $audio): self
+ public static function make(Audio $audio, Id3Reader $id3_reader): self
{
$path = $audio->getPath();
- $reader = $audio->getReader();
- $audio = $reader->getAudio();
+ $audio = $id3_reader->getAudio();
+ $stat = stat($path);
return new self(
- path: $path,
- filesize: $reader->getFilesize(),
- extension: pathinfo($path, PATHINFO_EXTENSION),
- dataformat: $audio?->dataformat(),
- encoding: $reader->getEncoding(),
- mimeType: $reader->getMimeType(),
- durationSeconds: $reader->getPlaytimeSeconds(),
- durationReadable: $reader->getPlaytimeString(),
- bitrate: $reader->getBitrate(),
- bitrateMode: $audio?->bitrate_mode(),
- sampleRate: $audio?->sample_rate(),
+ file_size: $id3_reader->getFileSize(),
+ data_format: $audio?->dataFormat(),
+ encoding: $id3_reader->getEncoding(),
+ mime_type: $id3_reader->getMimeType(),
+ duration_seconds: $id3_reader->getPlaytimeSeconds(),
+ bitrate: intval($id3_reader->getBitrate()),
+ bitrate_mode: $audio?->bitrateMode(),
+ sample_rate: $audio?->sampleRate(),
channels: $audio?->channels(),
- channelMode: $audio?->channelmode(),
- lossless: $audio?->lossless() ?? false,
- compressionRatio: $audio?->compression_ratio(),
+ channel_mode: $audio?->channelMode(),
+ is_lossless: $audio?->lossless() ?? false,
+ compression_ratio: $audio?->compressionRatio(),
+ codec: $audio?->codec(),
+ encoder_options: $audio?->encoderOptions(),
+ version: $id3_reader->getVersion(),
+ av_data_offset: $id3_reader->getAvDataOffset(),
+ av_data_end: $id3_reader->getAvDataEnd(),
+ file_path: $id3_reader->getFilePath(),
+ filename: $id3_reader->getFilename(),
+ last_access_at: $stat['atime'] ? new DateTime('@'.$stat['atime']) : null,
+ created_at: $stat['ctime'] ? new DateTime('@'.$stat['ctime']) : null,
+ modified_at: $stat['mtime'] ? new DateTime('@'.$stat['mtime']) : null,
);
}
- public function getPath(): ?string
+ /**
+ * Get size of the audio file in bytes, like `180664`
+ */
+ public function getFileSize(): ?int
{
- return $this->path;
+ return $this->file_size;
}
- public function getFilesize(): ?int
+ /**
+ * Get size of the audio file in human readable format, like `175.99 KB`
+ */
+ public function getSizeHuman(int $decimals = 2): ?string
{
- return $this->filesize;
- }
+ $file_size = (string) $this->file_size;
+ $size = ['B', 'KB', 'MB', 'GB', 'TB', 'PB'];
+ $factor = floor((strlen($file_size) - 1) / 3);
- public function getExtension(): ?string
- {
- return $this->extension;
+ return sprintf("%.{$decimals}f", $file_size / pow(1024, $factor)).' '.$size[$factor];
}
- public function getDataformat(): ?string
+ /**
+ * Get data format of the audio file, like `mp3`, `wav`, `etc`
+ */
+ public function getDataFormat(): ?string
{
- return $this->dataformat;
+ return $this->data_format;
}
+ /**
+ * Get encoding of the audio file, like `UTF-8`, `ISO-8859-1`, `etc`
+ */
public function getEncoding(): ?string
{
return $this->encoding;
}
+ /**
+ * Get mime type of the audio file, like `audio/x-matroska`, `audio/mpeg`, `etc`
+ */
public function getMimeType(): ?string
{
- return $this->mimeType;
+ return $this->mime_type;
}
- public function getDurationSeconds(): ?float
+ /**
+ * Get duration of the audio file in seconds, like `11.05`
+ */
+ public function getDurationSeconds(?int $decimals = null): ?float
{
- return $this->durationSeconds;
- }
+ if ($decimals !== null) {
+ return round($this->duration_seconds, $decimals);
+ }
- public function getDurationReadable(): ?string
- {
- return $this->durationReadable;
+ return $this->duration_seconds;
}
+ /**
+ * Get bitrate of the audio file in bits per second, like `128000`
+ */
public function getBitrate(): ?int
{
return $this->bitrate;
}
+ /**
+ * Get bitrate mode of the audio file, like `cbr`, `vbr`, `etc`
+ */
public function getBitrateMode(): ?string
{
- return $this->bitrateMode;
+ return $this->bitrate_mode;
}
+ /**
+ * Get sample rate of the audio file in hertz, like `44100`
+ */
public function getSampleRate(): ?int
{
- return $this->sampleRate;
+ return $this->sample_rate;
}
+ /**
+ * Get channels of the audio file, like `2`
+ */
public function getChannels(): ?int
{
return $this->channels;
}
+ /**
+ * Get channel mode of the audio file, like `joint stereo`, `stereo`, `etc`
+ */
public function getChannelMode(): ?string
{
- return $this->channelMode;
+ return $this->channel_mode;
+ }
+
+ /**
+ * Get lossless status of the audio file, like `false`
+ */
+ public function isLossless(): bool
+ {
+ return $this->is_lossless;
+ }
+
+ /**
+ * Get compression ratio of the audio file, like `0.1`
+ */
+ public function getCompressionRatio(?int $decimals = null): ?float
+ {
+ if ($decimals !== null) {
+ return round($this->compression_ratio, $decimals);
+ }
+
+ return $this->compression_ratio;
+ }
+
+ /**
+ * Get codec of the audio file, like `LAME`
+ */
+ public function getCodec(): ?string
+ {
+ return $this->codec;
+ }
+
+ /**
+ * Get encoder options of the audio file, like `CBR`, `VBR`, `etc`
+ */
+ public function getEncoderOptions(): ?string
+ {
+ return $this->encoder_options;
+ }
+
+ /**
+ * Get version of `JamesHeinrich/getID3`, like `1.9.23-202310190849`
+ *
+ * @docs https://github.com/JamesHeinrich/getID3
+ */
+ public function getVersion(): ?string
+ {
+ return $this->version;
+ }
+
+ /**
+ * Get audio/video data offset of the audio file, like `25808`
+ */
+ public function getAvDataOffset(): ?int
+ {
+ return $this->av_data_offset;
+ }
+
+ /**
+ * Get audio/video data end of the audio file, like `1214046`
+ */
+ public function getAvDataEnd(): ?int
+ {
+ return $this->av_data_end;
+ }
+
+ /**
+ * Get path of audio file directory, like `/path/to`
+ */
+ public function getFilePath(): ?string
+ {
+ return $this->file_path;
+ }
+
+ /**
+ * Get filename of the audio file, like `audio.mp3`
+ */
+ public function getFilename(): ?string
+ {
+ return $this->filename;
+ }
+
+ /**
+ * Get last access time of the audio file, like `2021-09-01 00:00:00`
+ */
+ public function getLastAccessAt(): ?DateTime
+ {
+ return $this->last_access_at;
}
- public function getLossless(): bool
+ /**
+ * Get created time of the audio file, like `2021-09-01 00:00:00`
+ */
+ public function getCreatedAt(): ?DateTime
{
- return $this->lossless;
+ return $this->created_at;
}
- public function getCompressionRatio(): ?float
+ /**
+ * Get modified time of the audio file, like `2021-09-01 00:00:00`
+ */
+ public function getModifiedAt(): ?DateTime
{
- return $this->compressionRatio;
+ return $this->modified_at;
}
}
diff --git a/src/Models/AudioStat.php b/src/Models/AudioStat.php
deleted file mode 100644
index 3e70105..0000000
--- a/src/Models/AudioStat.php
+++ /dev/null
@@ -1,147 +0,0 @@
-deviceNumber = $stat['dev'] ?? null;
- $self->inodeNumber = $stat['ino'] ?? null;
- $self->inodeProtectionMode = $stat['mode'] ?? null;
- $self->numberOfLinks = $stat['nlink'] ?? null;
- $self->userId = $stat['uid'] ?? null;
- $self->groupId = $stat['gid'] ?? null;
- $self->deviceType = $stat['rdev'] ?? null;
- $self->size = $stat['size'] ?? null;
- $self->lastAccessAt = $stat['atime'] ? new DateTime('@'.$stat['atime']) : null;
- $self->createdAt = $stat['ctime'] ? new DateTime('@'.$stat['ctime']) : null;
- $self->modifiedAt = $stat['mtime'] ? new DateTime('@'.$stat['mtime']) : null;
- $self->blockSize = $stat['blksize'] ?? null;
- $self->numberOfBlocks = $stat['blocks'] ?? null;
-
- return $self;
- }
-
- public function getPath(): string
- {
- return $this->path;
- }
-
- public function getDeviceNumber(): ?int
- {
- return $this->deviceNumber;
- }
-
- public function getInodeNumber(): ?int
- {
- return $this->inodeNumber;
- }
-
- public function getInodeProtectionMode(): ?int
- {
- return $this->inodeProtectionMode;
- }
-
- public function getNumberOfLinks(): ?int
- {
- return $this->numberOfLinks;
- }
-
- public function getUserId(): ?int
- {
- return $this->userId;
- }
-
- public function getGroupId(): ?int
- {
- return $this->groupId;
- }
-
- public function getDeviceType(): ?int
- {
- return $this->deviceType;
- }
-
- public function getSize(): ?int
- {
- return $this->size;
- }
-
- public function getLastAccessAt(): ?DateTime
- {
- return $this->lastAccessAt;
- }
-
- public function getCreatedAt(): ?DateTime
- {
- return $this->createdAt;
- }
-
- public function getModifiedAt(): ?DateTime
- {
- return $this->modifiedAt;
- }
-
- public function getBlockSize(): ?int
- {
- return $this->blockSize;
- }
-
- public function getNumberOfBlocks(): ?int
- {
- return $this->numberOfBlocks;
- }
-
- public function toArray(): array
- {
- return [
- 'path' => $this->path,
- 'deviceNumber' => $this->deviceNumber,
- 'inodeNumber' => $this->inodeNumber,
- 'inodeProtectionMode' => $this->inodeProtectionMode,
- 'numberOfLinks' => $this->numberOfLinks,
- 'userId' => $this->userId,
- 'groupId' => $this->groupId,
- 'deviceType' => $this->deviceType,
- 'size' => $this->size,
- 'lastAccessAt' => $this->lastAccessAt?->format('Y-m-d H:i:s'),
- 'createdAt' => $this->createdAt?->format('Y-m-d H:i:s'),
- 'modifiedAt' => $this->modifiedAt?->format('Y-m-d H:i:s'),
- 'blockSize' => $this->blockSize,
- 'numberOfBlocks' => $this->numberOfBlocks,
- ];
- }
-
- public function toJson(): string
- {
- return json_encode($this->toArray());
- }
-
- public function __toString(): string
- {
- return $this->toJson();
- }
-}
diff --git a/src/Models/Id3Reader.php b/src/Models/Id3Reader.php
deleted file mode 100644
index ed23da6..0000000
--- a/src/Models/Id3Reader.php
+++ /dev/null
@@ -1,1792 +0,0 @@
-raw = $self->instance->analyze($path);
- $self->is_writable = $self->instance->is_writable($path);
- $metadata = $self->raw;
-
- $audio = Id3Audio::make($metadata['audio'] ?? null);
- $video = Id3Video::make($metadata['video'] ?? null);
- $tags = Id3AudioTag::make($metadata['tags'] ?? null);
- $comments = Id3Comments::make($metadata['comments'] ?? null);
- $tags_html = Id3TagsHtml::make($metadata['tags_html'] ?? null);
- $bitrate = $metadata['bitrate'] ?? null;
- if ($bitrate) {
- $bitrate = intval($bitrate);
- }
-
- $self->version = $metadata['GETID3_VERSION'] ?? null;
- $self->filesize = $metadata['filesize'] ?? null;
- $self->filepath = $metadata['filepath'] ?? null;
- $self->filename = $metadata['filename'] ?? null;
- $self->filenamepath = $metadata['filenamepath'] ?? null;
- $self->avdataoffset = $metadata['avdataoffset'] ?? null;
- $self->avdataend = $metadata['avdataend'] ?? null;
- $self->fileformat = $metadata['fileformat'] ?? null;
- $self->audio = $audio;
- $self->video = $video;
- $self->tags = $tags;
- $self->comments = $comments;
- $self->encoding = $metadata['encoding'] ?? null;
- $self->mime_type = $metadata['mime_type'] ?? null;
- $self->mpeg = $metadata['mpeg'] ?? null;
- $self->playtime_seconds = $metadata['playtime_seconds'] ?? null;
- $self->tags_html = $tags_html;
- $self->bitrate = $bitrate;
- $self->playtime_string = $metadata['playtime_string'] ?? null;
-
- return $self;
- }
-
- public function getInstance(): getID3
- {
- return $this->instance;
- }
-
- public function getVersion(): ?string
- {
- return $this->version;
- }
-
- public function getFilesize(): ?int
- {
- return $this->filesize;
- }
-
- public function getFilepath(): ?string
- {
- return $this->filepath;
- }
-
- public function getFilename(): ?string
- {
- return $this->filename;
- }
-
- public function getFilenamepath(): ?string
- {
- return $this->filenamepath;
- }
-
- public function getAvdataoffset(): ?int
- {
- return $this->avdataoffset;
- }
-
- public function getAvdataend(): ?int
- {
- return $this->avdataend;
- }
-
- public function getFileformat(): ?string
- {
- return $this->fileformat;
- }
-
- public function getAudio(): ?Id3Audio
- {
- return $this->audio;
- }
-
- public function getTags(): ?Id3AudioTag
- {
- return $this->tags;
- }
-
- public function getComments(): ?Id3Comments
- {
- return $this->comments;
- }
-
- public function getEncoding(): ?string
- {
- return $this->encoding;
- }
-
- public function getMimeType(): ?string
- {
- return $this->mime_type;
- }
-
- public function getMpeg(): mixed
- {
- return $this->mpeg;
- }
-
- public function getPlaytimeSeconds(): ?float
- {
- return $this->playtime_seconds;
- }
-
- public function getTagsHtml(): ?Id3TagsHtml
- {
- return $this->tags_html;
- }
-
- public function getBitrate(): ?float
- {
- return $this->bitrate;
- }
-
- public function getPlaytimeString(): ?string
- {
- return $this->playtime_string;
- }
-
- public function isWritable(): bool
- {
- return $this->is_writable;
- }
-
- public function getRaw(): array
- {
- return $this->raw;
- }
-
- public function toTags(?string $audioFormat = null): array
- {
- $rawTags = $this->raw['tags_html'] ?? [];
-
- if (count($rawTags) === 0) {
- return [];
- }
-
- $tagsItems = [];
- if ($audioFormat) {
- $tagsItems = $rawTags[$audioFormat] ?? [];
- } else {
- if (count($rawTags) > 1) {
- $entries = [];
- foreach ($rawTags as $key => $keyTags) {
- $entries[$key] = count($keyTags);
- }
- $maxKey = array_search(max($entries), $entries);
- $tagsItems = $rawTags[$maxKey] ?? [];
- } else {
- $tagsItems = reset($rawTags);
- }
- }
-
- return Id3Reader::cleanTags($tagsItems);
- }
-
- public static function cleanTags(?array $tagsItems): array
- {
- if (! $tagsItems) {
- return [];
- }
-
- $temp = [];
- foreach ($tagsItems as $k => $v) {
- $temp[$k] = $v[0] ?? null;
- }
-
- $items = [];
- foreach ($temp as $k => $v) {
- $k = strtolower($k);
- $k = str_replace(' ', '_', $k);
- $items[$k] = $v;
- }
-
- return $items;
- }
-
- public function toAudioFormats(): array
- {
- return $this->raw['tags_html'] ?? [];
- }
-
- public function toArray(): array
- {
- $raw = $this->raw;
- $raw['id3v2']['APIC'] = null;
- $raw['ape']['items']['cover art (front)'] = null;
- $raw['comments'] = null;
-
- return $raw;
- }
-}
-
-class Id3Audio
-{
- /** @var Id3Stream[] */
- protected array $streams = [];
-
- protected function __construct(
- protected ?string $dataformat = null,
- protected ?int $channels = null,
- protected ?int $sample_rate = null,
- protected ?float $bitrate = null,
- protected ?string $channelmode = null,
- protected ?string $bitrate_mode = null,
- protected ?string $codec = null,
- protected ?string $encoder = null,
- protected bool $lossless = false,
- protected ?string $encoder_options = null,
- protected ?float $compression_ratio = null,
- ) {}
-
- public static function make(?array $metadata): ?self
- {
- if (! $metadata) {
- return null;
- }
-
- $streams = [];
- if (array_key_exists('streams', $metadata)) {
- foreach ($metadata['streams'] as $stream) {
- $streams[] = Id3Stream::make($stream);
- }
- }
-
- $self = new self(
- dataformat: $metadata['dataformat'] ?? null,
- channels: $metadata['channels'] ?? null,
- sample_rate: $metadata['sample_rate'] ?? null,
- bitrate: $metadata['bitrate'] ?? null,
- channelmode: $metadata['channelmode'] ?? null,
- bitrate_mode: $metadata['bitrate_mode'] ?? null,
- codec: $metadata['codec'] ?? null,
- encoder: $metadata['encoder'] ?? null,
- lossless: $metadata['lossless'] ?? false,
- encoder_options: $metadata['encoder_options'] ?? null,
- compression_ratio: $metadata['compression_ratio'] ?? null,
- );
- $self->streams = $streams;
-
- return $self;
- }
-
- /** @return Id3Stream[] */
- public function streams(): array
- {
- return $this->streams;
- }
-
- public function dataformat(): ?string
- {
- return $this->dataformat;
- }
-
- public function channels(): ?int
- {
- return $this->channels;
- }
-
- public function sample_rate(): ?int
- {
- return $this->sample_rate;
- }
-
- public function bitrate(): ?float
- {
- return $this->bitrate;
- }
-
- public function channelmode(): ?string
- {
- return $this->channelmode;
- }
-
- public function bitrate_mode(): ?string
- {
- return $this->bitrate_mode;
- }
-
- public function codec(): ?string
- {
- return $this->codec;
- }
-
- public function encoder(): ?string
- {
- return $this->encoder;
- }
-
- public function lossless(): bool
- {
- return $this->lossless;
- }
-
- public function encoder_options(): ?string
- {
- return $this->encoder_options;
- }
-
- public function compression_ratio(): ?float
- {
- return $this->compression_ratio;
- }
-
- public function stream(): ?Id3Stream
- {
- return $this->streams[0] ?? null;
- }
-}
-
-class Id3Video
-{
- protected function __construct(
- protected ?string $dataformat = null,
- protected ?int $rotate = null,
- protected ?float $resolution_x = null,
- protected ?float $resolution_y = null,
- protected ?float $frame_rate = null,
- ) {}
-
- public static function make(?array $metadata): ?self
- {
- if (! $metadata) {
- return null;
- }
-
- $self = new self(
- dataformat: $metadata['dataformat'] ?? null,
- rotate: $metadata['rotate'] ?? null,
- resolution_x: $metadata['resolution_x'] ?? null,
- resolution_y: $metadata['resolution_y'] ?? null,
- frame_rate: $metadata['frame_rate'] ?? null,
- );
-
- return $self;
- }
-
- public function dataformat(): ?string
- {
- return $this->dataformat;
- }
-
- public function rotate(): ?int
- {
- return $this->rotate;
- }
-
- public function resolution_x(): ?float
- {
- return $this->resolution_x;
- }
-
- public function resolution_y(): ?float
- {
- return $this->resolution_y;
- }
-
- public function frame_rate(): ?float
- {
- return $this->frame_rate;
- }
-}
-
-class Id3Stream
-{
- protected function __construct(
- protected ?string $dataformat = null,
- protected ?int $channels = null,
- protected ?int $sample_rate = null,
- protected ?float $bitrate = null,
- protected ?string $channelmode = null,
- protected ?string $bitrate_mode = null,
- protected ?string $codec = null,
- protected ?string $encoder = null,
- protected bool $lossless = false,
- protected ?string $encoder_options = null,
- protected ?float $compression_ratio = null,
- ) {}
-
- public static function make(?array $metadata): ?self
- {
- if (! $metadata) {
- return null;
- }
-
- $self = new self(
- dataformat: $metadata['dataformat'] ?? null,
- channels: $metadata['channels'] ?? null,
- sample_rate: $metadata['sample_rate'] ?? null,
- bitrate: $metadata['bitrate'] ?? null,
- channelmode: $metadata['channelmode'] ?? null,
- bitrate_mode: $metadata['bitrate_mode'] ?? null,
- codec: $metadata['codec'] ?? null,
- encoder: $metadata['encoder'] ?? null,
- lossless: $metadata['lossless'] ?? false,
- encoder_options: $metadata['encoder_options'] ?? null,
- compression_ratio: $metadata['compression_ratio'] ?? null,
- );
-
- return $self;
- }
-
- public function dataformat(): ?string
- {
- return $this->dataformat;
- }
-
- public function channels(): ?int
- {
- return $this->channels;
- }
-
- public function sample_rate(): ?int
- {
- return $this->sample_rate;
- }
-
- public function bitrate(): ?float
- {
- return $this->bitrate;
- }
-
- public function channelmode(): ?string
- {
- return $this->channelmode;
- }
-
- public function bitrate_mode(): ?string
- {
- return $this->bitrate_mode;
- }
-
- public function codec(): ?string
- {
- return $this->codec;
- }
-
- public function encoder(): ?string
- {
- return $this->encoder;
- }
-
- public function lossless(): bool
- {
- return $this->lossless;
- }
-
- public function encoder_options(): ?string
- {
- return $this->encoder_options;
- }
-
- public function compression_ratio(): ?float
- {
- return $this->compression_ratio;
- }
-}
-
-class Id3AudioTag
-{
- protected function __construct(
- protected ?Id3AudioTagV1 $id3v1 = null,
- protected ?Id3AudioTagV2 $id3v2 = null,
- protected ?Id3TagQuicktime $quicktime = null,
- protected ?Id3TagAsf $asf = null,
- protected ?Id3TagVorbisComment $vorbiscomment = null,
- protected ?Id3TagRiff $riff = null,
- protected ?Id3TagMatroska $matroska = null,
- protected ?Id3TagApe $ape = null,
- ) {}
-
- public static function make(?array $metadata): ?self
- {
- if (! $metadata) {
- return null;
- }
-
- $id3v1 = Id3Reader::cleanTags($metadata['id3v1'] ?? null);
- $id3v2 = Id3Reader::cleanTags($metadata['id3v2'] ?? null);
- $quicktime = Id3Reader::cleanTags($metadata['quicktime'] ?? null);
- $asf = Id3Reader::cleanTags($metadata['asf'] ?? null);
- $vorbiscomment = Id3Reader::cleanTags($metadata['vorbiscomment'] ?? null);
- $riff = Id3Reader::cleanTags($metadata['riff'] ?? null);
- $matroska = Id3Reader::cleanTags($metadata['matroska'] ?? null);
- $ape = Id3Reader::cleanTags($metadata['ape'] ?? null);
-
- $self = new self(
- id3v1: Id3AudioTagV1::make($id3v1),
- id3v2: Id3AudioTagV2::make($id3v2),
- quicktime: Id3TagQuicktime::make($quicktime),
- asf: Id3TagAsf::make($asf),
- vorbiscomment: Id3TagVorbisComment::make($vorbiscomment),
- riff: Id3TagRiff::make($riff),
- matroska: Id3TagMatroska::make($matroska),
- ape: Id3TagApe::make($ape),
- );
-
- return $self;
- }
-
- public function id3v1(): ?Id3AudioTagV1
- {
- return $this->id3v1;
- }
-
- public function id3v2(): ?Id3AudioTagV2
- {
- return $this->id3v2;
- }
-
- public function quicktime(): ?Id3TagQuicktime
- {
- return $this->quicktime;
- }
-
- public function asf(): ?Id3TagAsf
- {
- return $this->asf;
- }
-
- public function vorbiscomment(): ?Id3TagVorbisComment
- {
- return $this->vorbiscomment;
- }
-
- public function riff(): ?Id3TagRiff
- {
- return $this->riff;
- }
-
- public function matroska(): ?Id3TagMatroska
- {
- return $this->matroska;
- }
-
- public function ape(): ?Id3TagApe
- {
- return $this->ape;
- }
-}
-
-class Id3AudioTagV1
-{
- public function __construct(
- protected ?string $title = null,
- protected ?string $artist = null,
- protected ?string $album = null,
- protected ?string $year = null,
- protected ?string $genre = null,
- protected ?string $comment = null,
- protected ?string $track_number = null,
- ) {}
-
- public static function make(?array $metadata): ?self
- {
- if (! $metadata) {
- return null;
- }
-
- $self = new self(
- title: $metadata['title'] ?? null,
- artist: $metadata['artist'] ?? null,
- album: $metadata['album'] ?? null,
- year: $metadata['year'] ?? null,
- genre: $metadata['genre'] ?? null,
- comment: $metadata['comment'] ?? null,
- track_number: $metadata['track_number'] ?? null,
- );
-
- return $self;
- }
-
- public function title(): ?string
- {
- return $this->title;
- }
-
- public function artist(): ?string
- {
- return $this->artist;
- }
-
- public function album(): ?string
- {
- return $this->album;
- }
-
- public function year(): ?string
- {
- return $this->year;
- }
-
- public function genre(): ?string
- {
- return $this->genre;
- }
-
- public function comment(): ?string
- {
- return $this->comment;
- }
-
- public function track_number(): ?string
- {
- return $this->track_number;
- }
-
- public function toArray(): array
- {
- return [
- 'title' => $this->title,
- 'artist' => $this->artist,
- 'album' => $this->album,
- 'year' => $this->year,
- 'genre' => $this->genre,
- 'comment' => $this->comment,
- 'track_number' => $this->track_number,
- ];
- }
-}
-
-class Id3AudioTagV2
-{
- public function __construct(
- protected ?string $album = null,
- protected ?string $artist = null,
- protected ?string $band = null,
- protected ?string $comment = null,
- protected ?string $composer = null,
- protected ?string $part_of_a_set = null,
- protected ?string $genre = null,
- protected ?string $part_of_a_compilation = null,
- protected ?string $title = null,
- protected ?string $track_number = null,
- protected ?string $year = null,
- protected ?string $copyright = null,
- protected ?string $text = null,
- protected ?string $unsynchronised_lyric = null,
- protected ?string $language = null,
- ) {}
-
- public static function make(?array $metadata): ?self
- {
- if (! $metadata) {
- return null;
- }
-
- $self = new self(
- album: $metadata['album'] ?? null,
- artist: $metadata['artist'] ?? null,
- band: $metadata['band'] ?? null,
- comment: $metadata['comment'] ?? null,
- composer: $metadata['composer'] ?? null,
- part_of_a_set: $metadata['part_of_a_set'] ?? null,
- genre: $metadata['genre'] ?? null,
- part_of_a_compilation: $metadata['part_of_a_compilation'] ?? null,
- title: $metadata['title'] ?? null,
- track_number: $metadata['track_number'] ?? null,
- year: $metadata['year'] ?? null,
- copyright: $metadata['copyright_message'] ?? null,
- text: $metadata['text'] ?? null,
- unsynchronised_lyric: $metadata['unsynchronised_lyric'] ?? null,
- language: $metadata['language'] ?? null,
- );
-
- return $self;
- }
-
- public function album(): ?string
- {
- return $this->album;
- }
-
- public function artist(): ?string
- {
- return $this->artist;
- }
-
- public function band(): ?string
- {
- return $this->band;
- }
-
- public function comment(): ?string
- {
- return $this->comment;
- }
-
- public function composer(): ?string
- {
- return $this->composer;
- }
-
- public function part_of_a_set(): ?string
- {
- return $this->part_of_a_set;
- }
-
- public function genre(): ?string
- {
- return $this->genre;
- }
-
- public function part_of_a_compilation(): ?string
- {
- return $this->part_of_a_compilation;
- }
-
- public function title(): ?string
- {
- return $this->title;
- }
-
- public function track_number(): ?string
- {
- return $this->track_number;
- }
-
- public function year(): ?string
- {
- return $this->year;
- }
-
- public function copyright(): ?string
- {
- return $this->copyright;
- }
-
- public function text(): ?string
- {
- return $this->text;
- }
-
- public function unsynchronised_lyric(): ?string
- {
- return $this->unsynchronised_lyric;
- }
-
- public function language(): ?string
- {
- return $this->language;
- }
-
- public function toArray(): array
- {
- return [
- 'album' => $this->album,
- 'artist' => $this->artist,
- 'band' => $this->band,
- 'comment' => $this->comment,
- 'composer' => $this->composer,
- 'part_of_a_set' => $this->part_of_a_set,
- 'genre' => $this->genre,
- 'part_of_a_compilation' => $this->part_of_a_compilation,
- 'title' => $this->title,
- 'track_number' => $this->track_number,
- 'year' => $this->year,
- 'copyright' => $this->copyright,
- 'text' => $this->text,
- 'unsynchronised_lyric' => $this->unsynchronised_lyric,
- 'language' => $this->language,
- ];
- }
-}
-
-class Id3Comments
-{
- protected function __construct(
- protected ?string $language = null,
- protected ?Id3CommentsPicture $picture = null,
- ) {}
-
- public static function make(?array $metadata): ?self
- {
- if (! $metadata) {
- return null;
- }
-
- $language = $metadata['language'][0] ?? null;
- $picture = Id3CommentsPicture::make($metadata['picture'][0] ?? null);
-
- $self = new self(
- language: $language,
- picture: $picture,
- );
-
- return $self;
- }
-
- public function picture(): ?Id3CommentsPicture
- {
- return $this->picture;
- }
-}
-
-class Id3CommentsPicture
-{
- protected function __construct(
- protected ?string $data = null,
- protected ?string $image_mime = null,
- protected ?int $image_width = null,
- protected ?int $image_height = null,
- protected ?string $picturetype = null,
- protected ?string $description = null,
- protected ?int $datalength = null,
- ) {}
-
- public static function make(?array $metadata): ?self
- {
- if (! $metadata) {
- return null;
- }
-
- $self = new self(
- data: $metadata['data'] ?? null,
- image_mime: $metadata['image_mime'] ?? null,
- image_width: $metadata['image_width'] ?? null,
- image_height: $metadata['image_height'] ?? null,
- picturetype: $metadata['picturetype'] ?? null,
- description: $metadata['description'] ?? null,
- datalength: $metadata['datalength'] ?? null,
- );
-
- return $self;
- }
-
- public function data(): ?string
- {
- return $this->data;
- }
-
- public function image_mime(): ?string
- {
- return $this->image_mime;
- }
-
- public function image_width(): ?int
- {
- return $this->image_width;
- }
-
- public function image_height(): ?int
- {
- return $this->image_height;
- }
-
- public function picturetype(): ?string
- {
- return $this->picturetype;
- }
-
- public function description(): ?string
- {
- return $this->description;
- }
-
- public function datalength(): ?int
- {
- return $this->datalength;
- }
-}
-
-class Id3TagQuicktime
-{
- public function __construct(
- protected ?string $title = null,
- protected ?string $track_number = null,
- protected ?string $disc_number = null,
- protected ?string $compilation = null,
- protected ?string $album = null,
- protected ?string $genre = null,
- protected ?string $composer = null,
- protected ?string $creation_date = null,
- protected ?string $copyright = null,
- protected ?string $artist = null,
- protected ?string $album_artist = null,
- protected ?string $encoded_by = null,
- protected ?string $encoding_tool = null,
- protected ?string $description = null,
- protected ?string $description_long = null,
- protected ?string $language = null,
- protected ?string $lyrics = null,
- protected ?string $comment = null,
- protected ?string $stik = null,
- ) {}
-
- public static function make(?array $metadata): ?self
- {
- if (! $metadata) {
- return null;
- }
-
- $self = new self(
- title: $metadata['title'] ?? null,
- track_number: $metadata['track_number'] ?? null,
- disc_number: $metadata['disc_number'] ?? null,
- compilation: $metadata['compilation'] ?? null,
- album: $metadata['album'] ?? null,
- genre: $metadata['genre'] ?? null,
- composer: $metadata['composer'] ?? null,
- creation_date: $metadata['creation_date'] ?? null,
- copyright: $metadata['copyright'] ?? null,
- artist: $metadata['artist'] ?? null,
- album_artist: $metadata['album_artist'] ?? null,
- encoded_by: $metadata['encoded_by'] ?? null,
- encoding_tool: $metadata['encoding_tool'] ?? null,
- description: $metadata['description'] ?? null,
- description_long: $metadata['description_long'] ?? null,
- language: $metadata['language'] ?? null,
- lyrics: $metadata['lyrics'] ?? null,
- comment: $metadata['comment'] ?? null,
- stik: $metadata['stik'] ?? null,
- );
-
- return $self;
- }
-
- public function title(): ?string
- {
- return $this->title;
- }
-
- public function track_number(): ?string
- {
- return $this->track_number;
- }
-
- public function disc_number(): ?string
- {
- return $this->disc_number;
- }
-
- public function compilation(): ?string
- {
- return $this->compilation;
- }
-
- public function album(): ?string
- {
- return $this->album;
- }
-
- public function genre(): ?string
- {
- return $this->genre;
- }
-
- public function composer(): ?string
- {
- return $this->composer;
- }
-
- public function creation_date(): ?string
- {
- return $this->creation_date;
- }
-
- public function copyright(): ?string
- {
- return $this->copyright;
- }
-
- public function artist(): ?string
- {
- return $this->artist;
- }
-
- public function album_artist(): ?string
- {
- return $this->album_artist;
- }
-
- public function encoded_by(): ?string
- {
- return $this->encoded_by;
- }
-
- public function encoding_tool(): ?string
- {
- return $this->encoding_tool;
- }
-
- public function description(): ?string
- {
- return $this->description;
- }
-
- public function description_long(): ?string
- {
- return $this->description_long;
- }
-
- public function language(): ?string
- {
- return $this->language;
- }
-
- public function lyrics(): ?string
- {
- return $this->lyrics;
- }
-
- public function comment(): ?string
- {
- return $this->comment;
- }
-
- public function stik(): ?string
- {
- return $this->stik;
- }
-
- public function toArray(): array
- {
- return [
- 'title' => $this->title,
- 'track_number' => $this->track_number,
- 'disc_number' => $this->disc_number,
- 'compilation' => $this->compilation,
- 'album' => $this->album,
- 'genre' => $this->genre,
- 'composer' => $this->composer,
- 'creation_date' => $this->creation_date,
- 'copyright' => $this->copyright,
- 'artist' => $this->artist,
- 'album_artist' => $this->album_artist,
- 'encoded_by' => $this->encoded_by,
- 'encoding_tool' => $this->encoding_tool,
- 'description' => $this->description,
- 'description_long' => $this->description_long,
- 'language' => $this->language,
- 'lyrics' => $this->lyrics,
- 'comment' => $this->comment,
- 'stik' => $this->stik,
- ];
- }
-}
-
-class Id3TagAsf
-{
- public function __construct(
- protected ?string $title = null,
- protected ?string $artist = null,
- protected ?string $album = null,
- protected ?string $albumartist = null,
- protected ?string $composer = null,
- protected ?string $partofset = null,
- protected ?string $genre = null,
- protected ?string $track_number = null,
- protected ?string $year = null,
- protected ?string $encodingsettings = null,
- ) {}
-
- public static function make(?array $metadata): ?self
- {
- if (! $metadata) {
- return null;
- }
- $self = new self(
- title: $metadata['title'] ?? null,
- artist: $metadata['artist'] ?? null,
- album: $metadata['album'] ?? null,
- albumartist: $metadata['albumartist'] ?? null,
- composer: $metadata['composer'] ?? null,
- partofset: $metadata['partofset'] ?? null,
- genre: $metadata['genre'] ?? null,
- track_number: $metadata['track_number'] ?? null,
- year: $metadata['year'] ?? null,
- encodingsettings: $metadata['encodingsettings'] ?? null,
- );
-
- return $self;
- }
-
- public function title(): ?string
- {
- return $this->title;
- }
-
- public function artist(): ?string
- {
- return $this->artist;
- }
-
- public function album(): ?string
- {
- return $this->album;
- }
-
- public function albumartist(): ?string
- {
- return $this->albumartist;
- }
-
- public function composer(): ?string
- {
- return $this->composer;
- }
-
- public function partofset(): ?string
- {
- return $this->partofset;
- }
-
- public function genre(): ?string
- {
- return $this->genre;
- }
-
- public function track_number(): ?string
- {
- return $this->track_number;
- }
-
- public function year(): ?string
- {
- return $this->year;
- }
-
- public function encodingsettings(): ?string
- {
- return $this->encodingsettings;
- }
-
- public function toArray(): array
- {
- return [
- 'title' => $this->title,
- 'artist' => $this->artist,
- 'album' => $this->album,
- 'albumartist' => $this->albumartist,
- 'composer' => $this->composer,
- 'partofset' => $this->partofset,
- 'genre' => $this->genre,
- 'track_number' => $this->track_number,
- 'year' => $this->year,
- 'encodingsettings' => $this->encodingsettings,
- ];
- }
-}
-
-class Id3TagVorbisComment
-{
- public function __construct(
- protected ?string $description = null,
- protected ?string $encoder = null,
- protected ?string $title = null,
- protected ?string $artist = null,
- protected ?string $album = null,
- protected ?string $genre = null,
- protected ?string $comment = null,
- protected ?string $albumartist = null,
- protected ?string $composer = null,
- protected ?string $discnumber = null,
- protected ?string $compilation = null,
- protected ?string $date = null,
- protected ?string $tracknumber = null,
- ) {}
-
- public static function make(?array $metadata): ?self
- {
- if (! $metadata) {
- return null;
- }
- $self = new self(
- description: $metadata['description'] ?? null,
- encoder: $metadata['encoder'] ?? null,
- title: $metadata['title'] ?? null,
- artist: $metadata['artist'] ?? null,
- album: $metadata['album'] ?? null,
- genre: $metadata['genre'] ?? null,
- comment: $metadata['comment'] ?? null,
- albumartist: $metadata['albumartist'] ?? null,
- composer: $metadata['composer'] ?? null,
- discnumber: $metadata['discnumber'] ?? null,
- compilation: $metadata['compilation'] ?? null,
- date: $metadata['date'] ?? null,
- tracknumber: $metadata['tracknumber'] ?? null,
- );
-
- return $self;
- }
-
- public function description(): ?string
- {
- return $this->description;
- }
-
- public function title(): ?string
- {
- return $this->title;
- }
-
- public function artist(): ?string
- {
- return $this->artist;
- }
-
- public function album(): ?string
- {
- return $this->album;
- }
-
- public function genre(): ?string
- {
- return $this->genre;
- }
-
- public function comment(): ?string
- {
- return $this->comment;
- }
-
- public function albumartist(): ?string
- {
- return $this->albumartist;
- }
-
- public function composer(): ?string
- {
- return $this->composer;
- }
-
- public function discnumber(): ?string
- {
- return $this->discnumber;
- }
-
- public function compilation(): ?string
- {
- return $this->compilation;
- }
-
- public function date(): ?string
- {
- return $this->date;
- }
-
- public function tracknumber(): ?string
- {
- return $this->tracknumber;
- }
-
- public function encoder(): ?string
- {
- return $this->encoder;
- }
-
- public function toArray(): array
- {
- return [
- 'description' => $this->description,
- 'encoder' => $this->encoder,
- 'title' => $this->title,
- 'artist' => $this->artist,
- 'album' => $this->album,
- 'genre' => $this->genre,
- 'comment' => $this->comment,
- 'albumartist' => $this->albumartist,
- 'composer' => $this->composer,
- 'discnumber' => $this->discnumber,
- 'compilation' => $this->compilation,
- 'date' => $this->date,
- 'tracknumber' => $this->tracknumber,
- ];
- }
-}
-
-class Id3TagRiff
-{
- public function __construct(
- protected ?string $artist = null,
- protected ?string $comment = null,
- protected ?string $creationdate = null,
- protected ?string $genre = null,
- protected ?string $title = null,
- protected ?string $product = null,
- protected ?string $software = null,
- ) {}
-
- public static function make(?array $metadata): ?self
- {
- if (! $metadata) {
- return null;
- }
- $self = new self(
- artist: $metadata['artist'] ?? null,
- comment: $metadata['comment'] ?? null,
- creationdate: $metadata['creationdate'] ?? null,
- genre: $metadata['genre'] ?? null,
- title: $metadata['title'] ?? null,
- product: $metadata['product'] ?? null,
- software: $metadata['software'] ?? null,
- );
-
- return $self;
- }
-
- public function artist(): ?string
- {
- return $this->artist;
- }
-
- public function comment(): ?string
- {
- return $this->comment;
- }
-
- public function creationdate(): ?string
- {
- return $this->creationdate;
- }
-
- public function genre(): ?string
- {
- return $this->genre;
- }
-
- public function title(): ?string
- {
- return $this->title;
- }
-
- public function product(): ?string
- {
- return $this->product;
- }
-
- public function software(): ?string
- {
- return $this->software;
- }
-
- public function toArray(): array
- {
- return [
- 'artist' => $this->artist,
- 'comment' => $this->comment,
- 'creationdate' => $this->creationdate,
- 'genre' => $this->genre,
- 'title' => $this->title,
- 'product' => $this->product,
- 'software' => $this->software,
- ];
- }
-}
-
-class Id3TagMatroska
-{
- public function __construct(
- protected ?string $title = null,
- protected ?string $muxingapp = null,
- protected ?string $writingapp = null,
- protected ?string $album = null,
- protected ?string $artist = null,
- protected ?string $album_artist = null,
- protected ?string $comment = null,
- protected ?string $composer = null,
- protected ?string $disc = null,
- protected ?string $genre = null,
- protected ?string $compilation = null,
- protected ?string $part_number = null,
- protected ?string $date = null,
- protected ?string $encoder = null,
- protected ?string $duration = null,
- ) {}
-
- public static function make(?array $metadata): ?self
- {
- if (! $metadata) {
- return null;
- }
-
- $self = new self(
- title: $metadata['title'] ?? null,
- muxingapp: $metadata['muxingapp'] ?? null,
- writingapp: $metadata['writingapp'] ?? null,
- album: $metadata['album'] ?? null,
- artist: $metadata['artist'] ?? null,
- album_artist: $metadata['album_artist'] ?? null,
- comment: $metadata['comment'] ?? null,
- composer: $metadata['composer'] ?? null,
- disc: $metadata['disc'] ?? null,
- genre: $metadata['genre'] ?? null,
- compilation: $metadata['compilation'] ?? null,
- part_number: $metadata['part_number'] ?? null,
- date: $metadata['date'] ?? null,
- encoder: $metadata['encoder'] ?? null,
- duration: $metadata['duration'] ?? null,
- );
-
- return $self;
- }
-
- public function title(): ?string
- {
- return $this->title;
- }
-
- public function muxingapp(): ?string
- {
- return $this->muxingapp;
- }
-
- public function writingapp(): ?string
- {
- return $this->writingapp;
- }
-
- public function album(): ?string
- {
- return $this->album;
- }
-
- public function artist(): ?string
- {
- return $this->artist;
- }
-
- public function album_artist(): ?string
- {
- return $this->album_artist;
- }
-
- public function comment(): ?string
- {
- return $this->comment;
- }
-
- public function composer(): ?string
- {
- return $this->composer;
- }
-
- public function disc(): ?string
- {
- return $this->disc;
- }
-
- public function genre(): ?string
- {
- return $this->genre;
- }
-
- public function compilation(): ?string
- {
- return $this->compilation;
- }
-
- public function part_number(): ?string
- {
- return $this->part_number;
- }
-
- public function date(): ?string
- {
- return $this->date;
- }
-
- public function encoder(): ?string
- {
- return $this->encoder;
- }
-
- public function duration(): ?string
- {
- return $this->duration;
- }
-
- public function toArray(): array
- {
- return [
- 'title' => $this->title,
- 'muxingapp' => $this->muxingapp,
- 'writingapp' => $this->writingapp,
- 'album' => $this->album,
- 'artist' => $this->artist,
- 'album_artist' => $this->album_artist,
- 'comment' => $this->comment,
- 'composer' => $this->composer,
- 'disc' => $this->disc,
- 'genre' => $this->genre,
- 'compilation' => $this->compilation,
- 'part_number' => $this->part_number,
- 'date' => $this->date,
- 'encoder' => $this->encoder,
- 'duration' => $this->duration,
- ];
- }
-}
-
-class Id3TagApe
-{
- public function __construct(
- protected ?string $title = null,
- protected ?string $artist = null,
- protected ?string $album = null,
- protected ?string $album_artist = null,
- protected ?string $composer = null,
- protected ?string $comment = null,
- protected ?string $genre = null,
- protected ?string $disc = null,
- protected ?string $compilation = null,
- protected ?string $track = null,
- protected ?string $date = null,
- protected ?string $encoder = null,
- protected ?string $description = null,
- protected ?string $copyright = null,
- protected ?string $lyrics = null,
- protected ?string $podcastdesc = null,
- protected ?string $language = null,
- protected ?string $year = null,
- ) {}
-
- public static function make(?array $metadata): ?self
- {
- if (! $metadata) {
- return null;
- }
-
- $self = new self(
- title: $metadata['title'] ?? null,
- artist: $metadata['artist'] ?? null,
- album: $metadata['album'] ?? null,
- album_artist: $metadata['album_artist'] ?? $metadata['albumartist'] ?? null,
- composer: $metadata['composer'] ?? null,
- comment: $metadata['comment'] ?? null,
- genre: $metadata['genre'] ?? null,
- disc: $metadata['disc'] ?? $metadata['discnumber'] ?? null,
- compilation: $metadata['compilation'] ?? null,
- track: $metadata['track'] ?? null,
- date: $metadata['date'] ?? null,
- encoder: $metadata['encoder'] ?? null,
- description: $metadata['description'] ?? null,
- copyright: $metadata['copyright'] ?? null,
- lyrics: $metadata['unsyncedlyrics'] ?? null,
- podcastdesc: $metadata['podcastdesc'] ?? null,
- language: $metadata['language'] ?? null,
- year: $metadata['year'] ?? null,
- );
-
- return $self;
- }
-
- public function title(): ?string
- {
- return $this->title;
- }
-
- public function artist(): ?string
- {
- return $this->artist;
- }
-
- public function album(): ?string
- {
- return $this->album;
- }
-
- public function album_artist(): ?string
- {
- return $this->album_artist;
- }
-
- public function composer(): ?string
- {
- return $this->composer;
- }
-
- public function comment(): ?string
- {
- return $this->comment;
- }
-
- public function genre(): ?string
- {
- return $this->genre;
- }
-
- public function disc(): ?string
- {
- return $this->disc;
- }
-
- public function compilation(): ?string
- {
- return $this->compilation;
- }
-
- public function track(): ?string
- {
- return $this->track;
- }
-
- public function date(): ?string
- {
- return $this->date;
- }
-
- public function encoder(): ?string
- {
- return $this->encoder;
- }
-
- public function description(): ?string
- {
- return $this->description;
- }
-
- public function copyright(): ?string
- {
- return $this->copyright;
- }
-
- public function lyrics(): ?string
- {
- return $this->lyrics;
- }
-
- public function podcastdesc(): ?string
- {
- return $this->podcastdesc;
- }
-
- public function language(): ?string
- {
- return $this->language;
- }
-
- public function year(): ?string
- {
- return $this->year;
- }
-
- public function toArray(): array
- {
- return [
- 'title' => $this->title,
- 'artist' => $this->artist,
- 'album' => $this->album,
- 'album_artist' => $this->album_artist,
- 'composer' => $this->composer,
- 'comment' => $this->comment,
- 'genre' => $this->genre,
- 'disc' => $this->disc,
- 'compilation' => $this->compilation,
- 'track' => $this->track,
- 'date' => $this->date,
- 'encoder' => $this->encoder,
- 'description' => $this->description,
- 'copyright' => $this->copyright,
- 'lyrics' => $this->lyrics,
- 'podcastdesc' => $this->podcastdesc,
- 'language' => $this->language,
- 'year' => $this->year,
- ];
- }
-}
-
-class Id3TagsHtml
-{
- protected function __construct(
- protected ?Id3AudioTagV1 $id3v1 = null,
- protected ?Id3AudioTagV2 $id3v2 = null,
- protected ?Id3TagQuicktime $quicktime = null,
- protected ?Id3TagAsf $asf = null,
- protected ?Id3TagVorbisComment $vorbiscomment = null,
- protected ?Id3TagRiff $riff = null,
- protected ?Id3TagMatroska $matroska = null,
- protected ?Id3TagApe $ape = null,
- ) {}
-
- public static function make(?array $metadata): ?self
- {
- if (! $metadata) {
- return null;
- }
-
- $id3v1 = Id3Reader::cleanTags($metadata['id3v1'] ?? null);
- $id3v2 = Id3Reader::cleanTags($metadata['id3v2'] ?? null);
- $quicktime = Id3Reader::cleanTags($metadata['quicktime'] ?? null);
- $asf = Id3Reader::cleanTags($metadata['asf'] ?? null);
- $vorbiscomment = Id3Reader::cleanTags($metadata['vorbiscomment'] ?? null);
- $riff = Id3Reader::cleanTags($metadata['riff'] ?? null);
- $matroska = Id3Reader::cleanTags($metadata['matroska'] ?? null);
- $ape = Id3Reader::cleanTags($metadata['ape'] ?? null);
-
- $self = new self(
- id3v1: Id3AudioTagV1::make($id3v1),
- id3v2: Id3AudioTagV2::make($id3v2),
- quicktime: Id3TagQuicktime::make($quicktime),
- asf: Id3TagAsf::make($asf),
- vorbiscomment: Id3TagVorbisComment::make($vorbiscomment),
- riff: Id3TagRiff::make($riff),
- matroska: Id3TagMatroska::make($matroska),
- ape: Id3TagApe::make($ape),
- );
-
- return $self;
- }
-
- public function id3v1(): ?Id3AudioTagV1
- {
- return $this->id3v1;
- }
-
- public function id3v2(): ?Id3AudioTagV2
- {
- return $this->id3v2;
- }
-
- public function quicktime(): ?Id3TagQuicktime
- {
- return $this->quicktime;
- }
-
- public function asf(): ?Id3TagAsf
- {
- return $this->asf;
- }
-
- public function vorbiscomment(): ?Id3TagVorbisComment
- {
- return $this->vorbiscomment;
- }
-
- public function riff(): ?Id3TagRiff
- {
- return $this->riff;
- }
-
- public function matroska(): ?Id3TagMatroska
- {
- return $this->matroska;
- }
-
- public function ape(): ?Id3TagApe
- {
- return $this->ape;
- }
-}
diff --git a/src/Models/Id3Writer.php b/src/Models/Id3Writer.php
index d403cdb..e4c7c8f 100644
--- a/src/Models/Id3Writer.php
+++ b/src/Models/Id3Writer.php
@@ -5,6 +5,7 @@
use DateTime;
use getid3_writetags;
use Kiwilan\Audio\Audio;
+use Kiwilan\Audio\Core\AudioCore;
use Kiwilan\Audio\Enums\AudioFormatEnum;
use Kiwilan\Audio\Enums\AudioTypeEnum;
@@ -221,13 +222,6 @@ public function lyrics(?string $lyrics): self
return $this;
}
- public function stik(?string $stik): self
- {
- $this->core->setStik($stik);
-
- return $this;
- }
-
/**
* @param string $pathOrData Path to cover image or binary data
*/
@@ -331,6 +325,13 @@ public function save(): bool
$this->instance->tagformats = $this->tagFormats;
$this->instance->tag_data = $this->tags;
+ // $this->instance->overwrite_tags = false;
+ // $this->instance->remove_other_tags = false;
+ // ray($this->instance);
+
+ // $this->core->setTitle('test');
+ // ray($this->core);
+ // ray($this->instance);
$this->success = $this->instance->WriteTags();
$this->errors = $this->instance->errors;
@@ -371,7 +372,7 @@ public function save(): bool
}
if (! $supported && $this->failOnError) {
- throw new \Exception("Format {$this->audio->getFormat()?->value} is not supported.");
+ throw new \Exception("Format {$this->audio->getFormat()->value} is not supported.");
}
if (! empty($this->warnings)) {
@@ -381,6 +382,11 @@ public function save(): bool
return $this->success;
}
+ private function assignCurrentTags(): self
+ {
+ //
+ }
+
private function automaticConvert(): self
{
$this->convertTagFormats();
diff --git a/tests/ArchTest.php b/tests/ArchTest.php
new file mode 100644
index 0000000..fd6a1e4
--- /dev/null
+++ b/tests/ArchTest.php
@@ -0,0 +1,5 @@
+expect(['dd', 'dump', 'ray'])
+ ->not->toBeUsed();
diff --git a/tests/AudioCoreTest.php b/tests/AudioCoreTest.php
index f146f9e..02f3d0a 100644
--- a/tests/AudioCoreTest.php
+++ b/tests/AudioCoreTest.php
@@ -1,8 +1,8 @@
getAlbum(),
genre: $audio->getGenre(),
year: $audio->getYear(),
- trackNumber: $audio->getTrackNumber(),
+ track_number: $audio->getTrackNumber(),
comment: $audio->getComment(),
- albumArtist: $audio->getAlbumArtist(),
+ album_artist: $audio->getAlbumArtist(),
composer: $audio->getComposer(),
- discNumber: $audio->getDiscNumber(),
- isCompilation: $audio->isCompilation(),
- creationDate: $audio->getCreationDate(),
+ disc_number: $audio->getDiscNumber(),
+ is_compilation: $audio->isCompilation(),
+ creation_date: $audio->getCreationDate(),
copyright: $audio->getCopyright(),
- encodingBy: $audio->getEncodingBy(),
+ encoding_by: $audio->getEncodingBy(),
encoding: $audio->getEncoding(),
description: $audio->getDescription(),
lyrics: $audio->getLyrics(),
- stik: $audio->getStik(),
);
expect($core->getTitle())->toBe('Introduction');
diff --git a/tests/AudioCoverTest.php b/tests/AudioCoverTest.php
new file mode 100644
index 0000000..cd68e29
--- /dev/null
+++ b/tests/AudioCoverTest.php
@@ -0,0 +1,34 @@
+getCover();
+
+ if ($audio->hasCover()) {
+ expect($cover)->toBeInstanceOf(AudioCover::class);
+ expect($cover->getContents())->toBeString();
+ expect($cover->getContents())->toBeString();
+ expect($cover->getMimeType())->toBeString();
+ if ($cover->getWidth()) {
+ expect($cover->getWidth())->toBeInt();
+ }
+ if ($cover->getHeight()) {
+ expect($cover->getHeight())->toBeInt();
+ }
+
+ $path = "tests/output/cover-{$ext}.jpg";
+ file_put_contents($path, $cover->getContents());
+ expect(file_exists($path))->toBeTrue();
+ expect($path)->toBeReadableFile();
+ } else {
+ expect($cover)->toBeNull();
+ }
+})->with([...AUDIO]);
diff --git a/tests/AudioMetadataTest.php b/tests/AudioMetadataTest.php
new file mode 100644
index 0000000..62c4661
--- /dev/null
+++ b/tests/AudioMetadataTest.php
@@ -0,0 +1,87 @@
+getMetadata();
+ expect($metadata->getFileSize())->toBe(272737);
+ expect($metadata->getDataFormat())->toBe('mp3');
+ expect($metadata->getEncoding())->toBe('UTF-8');
+ expect($metadata->getMimeType())->toBe('audio/mpeg');
+ expect($metadata->getDurationSeconds())->toBe(11.0496875);
+ expect($metadata->getBitrate())->toBe(128000);
+ expect($metadata->getBitrateMode())->toBe('cbr');
+ expect($metadata->getSampleRate())->toBe(44100);
+ expect($metadata->getChannels())->toBe(2);
+ expect($metadata->getChannelMode())->toBe('joint stereo');
+ expect($metadata->isLossless())->toBeFalse();
+ expect($metadata->getCompressionRatio())->toBe(0.09070294784580499);
+ expect($metadata->getCodec())->toBe('LAME');
+ expect($metadata->getEncoderOptions())->toBe('CBR128');
+ expect($metadata->getVersion())->toContain('1.9');
+ expect($metadata->getAvDataOffset())->toBe(95396);
+ expect($metadata->getAvDataEnd())->toBe(272609);
+ expect($metadata->getFilePath())->toContain('tests/media');
+ expect($metadata->getFilename())->toBe('test.mp3');
+ expect($metadata->getLastAccessAt())->toBeInstanceOf(DateTime::class);
+ expect($metadata->getCreatedAt())->toBeInstanceOf(DateTime::class);
+ expect($metadata->getModifiedAt())->toBeInstanceOf(DateTime::class);
+});
+
+it('can read basic info', function (string $path) {
+ $audio = Audio::get($path);
+ $metadata = $audio->getMetadata();
+
+ expect($metadata)->toBeInstanceOf(AudioMetadata::class);
+ expect($metadata->getFileSize())->toBeInt();
+ expect($metadata->getSizeHuman())->toBeString();
+ expect($metadata->getMimeType())->toBeString();
+ expect($metadata->isLossless())->toBeBool();
+ expect($metadata->getLastAccessAt())->toBeInstanceOf(DateTime::class);
+ expect($metadata->getCreatedAt())->toBeInstanceOf(DateTime::class);
+ expect($metadata->getModifiedAt())->toBeInstanceOf(DateTime::class);
+ expect($metadata->getVersion())->toContain('1.9');
+ expect($metadata->getAvDataOffset())->toBeInt();
+ expect($metadata->getAvDataEnd())->toBeInt();
+ expect($metadata->getFilePath())->toBeString();
+ expect($metadata->getFilename())->toBeString();
+
+ if ($metadata->getChannels()) {
+ expect($metadata->getChannels())->toBeInt();
+ }
+ if ($metadata->getBitrate()) {
+ expect($metadata->getBitrate())->toBeInt();
+ }
+ if ($metadata->getChannelMode()) {
+ expect($metadata->getChannelMode())->toBeString();
+ }
+ if ($metadata->getDataFormat()) {
+ expect($metadata->getDataFormat())->toBeString();
+ }
+ if ($metadata->getEncoding()) {
+ expect($metadata->getEncoding())->toBeString();
+ }
+ if ($metadata->getDurationSeconds()) {
+ expect($metadata->getDurationSeconds())->toBeFloat();
+ expect($metadata->getDurationSeconds(2))->toBeFloat();
+ }
+ if ($metadata->getSampleRate()) {
+ expect($metadata->getSampleRate())->toBeInt();
+ }
+ if ($metadata->getBitrateMode()) {
+ expect($metadata->getBitrateMode())->toBeString();
+ }
+ if ($metadata->getCompressionRatio()) {
+ expect($metadata->getCompressionRatio())->toBeFloat();
+ expect($metadata->getCompressionRatio(2))->toBeFloat();
+ }
+ if ($metadata->getCodec()) {
+ expect($metadata->getCodec())->toBeString();
+ }
+ if ($metadata->getEncoderOptions()) {
+ expect($metadata->getEncoderOptions())->toBeString();
+ }
+})->with([...AUDIO]);
diff --git a/tests/AudioMp3Test.php b/tests/AudioMp3Test.php
new file mode 100644
index 0000000..53e27c6
--- /dev/null
+++ b/tests/AudioMp3Test.php
@@ -0,0 +1,117 @@
+toBeInstanceOf(Audio::class);
+ expect($audio->getPath())->toBe(MP3);
+ expect($audio->getExtension())->toBe('mp3');
+ expect($audio->getFormat())->toBe(AudioFormatEnum::mp3);
+ expect($audio->getType())->toBe(AudioTypeEnum::id3);
+ expect($audio->getMetadata())->toBeInstanceOf(AudioMetadata::class);
+ expect($audio->getId3Reader())->toBeInstanceOf(Id3Reader::class);
+ expect($audio->getDuration())->toBe(11.05);
+ expect($audio->getDurationHuman())->toBe('00:00:11');
+
+ expect($audio->isWritable())->toBeTrue();
+ expect($audio->isValid())->toBeTrue();
+ expect($audio->hasCover())->toBeTrue();
+
+ expect($audio->getTitle())->toBe('Introduction');
+ expect($audio->getArtist())->toBe('Mr Piouf');
+ expect($audio->getAlbum())->toBe('P1PDD Le conclave de Troie');
+ expect($audio->getGenre())->toBe('Roleplaying game');
+ expect($audio->getYear())->toBe(2016);
+ expect($audio->getTrackNumber())->toBe('1');
+ expect($audio->getTrackNumberInt())->toBe(1);
+ expect($audio->getAlbumArtist())->toBe('P1PDD & Mr Piouf');
+ expect($audio->getComposer())->toBe('P1PDD & Piouf');
+ expect($audio->getDiscNumber())->toBe('1');
+ expect($audio->getDiscNumberInt())->toBe(1);
+ expect($audio->isCompilation())->toBeTrue();
+ expect($audio->getCreationDate())->toBeNull();
+ expect($audio->getEncodingBy())->toBeNull();
+ expect($audio->getEncoding())->toBeNull();
+ expect($audio->getCopyright())->toBeNull();
+ expect($audio->getDescription())->toBeNull();
+ expect($audio->getSynopsis())->toBeNull();
+ expect($audio->getLanguage())->toBeNull();
+ expect($audio->getLyrics())->toBeNull();
+ expect($audio->getComment())->toBe('http://www.p1pdd.com');
+
+ expect($audio->getRawTagsAll())->toBeArray();
+ expect($audio->getRawTagsAll()['id3v1'])->toBeArray();
+ expect($audio->getRawTagsAll()['id3v1'])->toHaveCount(6);
+ expect($audio->getRawTagsAll()['id3v2'])->toBeArray();
+ expect($audio->getRawTagsAll()['id3v2'])->toHaveCount(11);
+ expect($audio->getRawTags())->toHaveCount(11);
+ expect($audio->getRawTags('id3v2'))->toHaveCount(11);
+ expect($audio->getRawTagsKey('title'))->toBe('Introduction');
+ expect($audio->getExtras())->toBeArray();
+
+ $cover = $audio->getCover();
+ expect($cover)->toBeInstanceOf(AudioCover::class);
+ expect($cover->getContents())->toBeString();
+ expect($cover->getContents(base64: true))->toBeString();
+ expect($cover->getMimeType())->toBe('image/jpeg');
+ expect($cover->getWidth())->toBe(640);
+ expect($cover->getHeight())->toBe(640);
+
+ $metadata = $audio->getMetadata();
+ expect($metadata->getFileSize())->toBe(272737);
+ expect($metadata->getEncoding())->toBe('UTF-8');
+ expect($metadata->getMimeType())->toBe('audio/mpeg');
+ expect($metadata->getDurationSeconds())->toBe(11.0496875);
+ expect($metadata->getBitrate())->toBe(128000);
+ expect($metadata->getBitrateMode())->toBe('cbr');
+ expect($metadata->getSampleRate())->toBe(44100);
+ expect($metadata->getChannels())->toBe(2);
+ expect($metadata->getChannelMode())->toBe('joint stereo');
+ expect($metadata->isLossless())->toBeFalse();
+ expect($metadata->getCompressionRatio())->toBe(0.09070294784580499);
+});
+
+it('can extract cover mp3', function () {
+ $audio = Audio::get(MP3);
+ $cover = $audio->getCover();
+
+ expect($cover)->toBeInstanceOf(AudioCover::class);
+ expect($cover->getContents())->toBeString();
+ expect($cover->getMimeType())->toBe('image/jpeg');
+ expect($cover->getWidth())->toBe(640);
+ expect($cover->getHeight())->toBe(640);
+
+ $path = 'tests/output/cover.jpg';
+ file_put_contents($path, $cover->getContents());
+ expect(file_exists($path))->toBeTrue();
+ expect($path)->toBeReadableFile();
+});
+
+it('can read file mp3 no meta', function () {
+ $audio = Audio::get(MP3_NO_META);
+
+ expect($audio)->toBeInstanceOf(Audio::class);
+ expect($audio->getTitle())->toBeNull();
+ expect($audio->getArtist())->toBeNull();
+ expect($audio->getAlbum())->toBeNull();
+ expect($audio->getGenre())->toBeNull();
+ expect($audio->getYear())->toBeNull();
+ expect($audio->getTrackNumber())->toBeNull();
+ expect($audio->getComment())->toBeNull();
+ expect($audio->getAlbumArtist())->toBeNull();
+ expect($audio->getComposer())->toBeNull();
+ expect($audio->getDiscNumber())->toBeNull();
+ expect($audio->isCompilation())->toBeFalse();
+ expect($audio->getPath())->toBe(MP3_NO_META);
+});
+
+it("can fail if file didn't exists", function () {
+ expect(fn () => Audio::get('tests/media/unknown.mp3'))->toThrow(Exception::class);
+});
diff --git a/tests/AudioTest.php b/tests/AudioTest.php
index 2bd29d2..d743271 100644
--- a/tests/AudioTest.php
+++ b/tests/AudioTest.php
@@ -2,140 +2,61 @@
use Kiwilan\Audio\Audio;
use Kiwilan\Audio\Enums\AudioFormatEnum;
-use Kiwilan\Audio\Models\AudioCover;
+use Kiwilan\Audio\Id3\Id3Reader;
+use Kiwilan\Audio\Models\AudioMetadata;
-it('can read file', function (string $path) {
+it('can read basic info', function (string $path) {
$audio = Audio::get($path);
$extension = pathinfo($path, PATHINFO_EXTENSION);
$format = AudioFormatEnum::tryFrom($extension);
expect($audio)->toBeInstanceOf(Audio::class);
+ expect($audio->getPath())->toBe($path);
+ expect($audio->getExtension())->toBe($extension);
+ expect($audio->getFormat())->toBe($format);
+
+ expect($audio->getMetadata())->toBeInstanceOf(AudioMetadata::class);
+ expect($audio->getId3Reader())->toBeInstanceOf(Id3Reader::class);
+ expect($audio->getDuration())->toBeFloat();
+ expect($audio->getDurationHuman())->toBeString();
+
+ expect($audio->isWritable())->toBeBool();
+ expect($audio->isValid())->toBeBool();
+ expect($audio->hasCover())->toBeBool();
+
expect($audio->getTitle())->toBe('Introduction');
expect($audio->getArtist())->toBe('Mr Piouf');
expect($audio->getAlbum())->toBe('P1PDD Le conclave de Troie');
expect($audio->getGenre())->toBe('Roleplaying game');
expect($audio->getYear())->toBe(2016);
expect($audio->getTrackNumber())->toBe('1');
- if ($audio->getComment()) {
- expect($audio->getComment())->toBe('http://www.p1pdd.com');
- }
- expect($audio->getAlbumArtist())->toBe('P1PDD & Mr Piouf');
- expect($audio->getComposer())->toBe('P1PDD & Piouf');
- expect($audio->getDiscNumber())->toBeString();
- expect($audio->isCompilation())->toBeBool();
- expect($audio->getPath())->toBe($path);
- expect($audio->getgetExtension())->toBe($extension);
+ expect($audio->getTrackNumberInt())->toBe(1);
expect($audio->getFormat())->toBe($format);
- expect($audio->getDuration())->toBeFloat();
- expect($audio->getExtras())->toBeArray();
- expect($audio->getTags())->toBeArray();
- expect($audio->toArray())->toBeArray();
-
- $metadata = $audio->getAudio();
- expect($metadata->getPath())->toBeString();
- expect($metadata->getFilesize())->toBeInt();
- expect($metadata->getExtension())->toBeString();
- expect($metadata->getEncoding())->toBeString();
- expect($metadata->getMimeType())->toBeString();
- if ($metadata->getDurationSeconds()) {
- expect($metadata->getDurationSeconds())->toBeFloat();
- }
- if ($metadata->getDurationReadable()) {
- expect($metadata->getDurationReadable())->toBeString();
- }
- if ($metadata->getBitrate()) {
- expect($metadata->getBitrate())->toBeInt();
- }
- if ($metadata->getBitrateMode()) {
- expect($metadata->getBitrateMode())->toBeString();
- }
- if ($metadata->getSampleRate()) {
- expect($metadata->getSampleRate())->toBeInt();
- }
- if ($metadata->getChannels()) {
- expect($metadata->getChannels())->toBeInt();
- }
- if ($metadata->getChannelMode()) {
- expect($metadata->getChannelMode())->toBeString();
- }
- expect($metadata->getLossless())->toBeBool();
- if ($metadata->getCompressionRatio()) {
- expect($metadata->getCompressionRatio())->toBeFloat();
- }
- expect($audio->isValid())->toBeTrue();
})->with([...AUDIO]);
-it('can extract cover', function (string $path) {
- $audio = Audio::get($path);
- $ext = pathinfo($path, PATHINFO_EXTENSION);
- $cover = $audio->getCover();
-
- if ($audio->hasCover()) {
- expect($cover)->toBeInstanceOf(AudioCover::class);
- expect($cover->getContents())->toBeString();
- expect($cover->getContents())->toBeString();
- expect($cover->getMimeType())->toBeString();
- if ($cover->getWidth()) {
- expect($cover->getWidth())->toBeInt();
- }
- if ($cover->getHeight()) {
- expect($cover->getHeight())->toBeInt();
- }
-
- $path = "tests/output/cover-{$ext}.jpg";
- file_put_contents($path, $cover->getContents());
- expect(file_exists($path))->toBeTrue();
- expect($path)->toBeReadableFile();
- } else {
- expect($cover)->toBeNull();
- }
-})->with([...AUDIO]);
+it('can read disc number', function () {
+ $audio = Audio::get(M4A);
-it('can use stat data', function (string $path) {
- $audio = Audio::get($path);
- $stat = $audio->getStat();
-
- expect($stat->getPath())->toBe($path);
- expect($stat->getDeviceNumber())->toBeInt();
- expect($stat->getInodeNumber())->toBeInt();
- expect($stat->getInodeProtectionMode())->toBeInt();
- expect($stat->getNumberOfLinks())->toBeInt();
- expect($stat->getUserId())->toBeInt();
- expect($stat->getGroupId())->toBeInt();
- expect($stat->getDeviceType())->toBeInt();
- expect($stat->getLastAccessAt())->toBeInstanceOf(DateTime::class);
- expect($stat->getCreatedAt())->toBeInstanceOf(DateTime::class);
- expect($stat->getModifiedAt())->toBeInstanceOf(DateTime::class);
- expect($stat->getBlockSize())->toBeInt();
- expect($stat->getNumberOfBlocks())->toBeInt();
- expect($stat->toArray())->toBeArray();
- expect($stat->toJson())->toBeString();
- expect($stat->__toString())->toBeString();
-})->with([...AUDIO]);
+ expect($audio->getDiscNumber())->toBe('1/2');
+ expect($audio->getDiscNumberInt())->toBe(1);
+});
-it('can read mp3 stream', function () {
- $audio = Audio::get(MP3);
- $streams = $audio->getReader()->getAudio()->streams();
-
- expect($streams)->toBeArray();
- expect($streams)->toHaveCount(1);
- expect($streams[0]->dataformat())->toBe('mp3');
- expect($streams[0]->channels())->toBe(2);
- expect($streams[0]->sample_rate())->toBe(44100);
- expect($streams[0]->bitrate())->toBe(128000.0);
- expect($streams[0]->channelmode())->toBe('joint stereo');
- expect($streams[0]->bitrate_mode())->toBe('cbr');
- expect($streams[0]->codec())->toBe('LAME');
- expect($streams[0]->encoder())->toBe('LAME3.100');
- expect($streams[0]->lossless())->toBeFalse();
- expect($streams[0]->encoder_options())->toBe('CBR128');
- expect($streams[0]->compression_ratio())->toBe(0.09070294784580499);
+it('can read encoding', function () {
+ $audio = Audio::get(M4V);
+
+ expect($audio->getEncoding())->toBe('Lavf60.3.100');
});
-it('can read wrong audio file', function () {
- $audio = Audio::get(MD);
+it('can read description', function () {
+ $audio = Audio::get(FLAC);
- expect($audio->isValid())->toBeFalse();
+ expect($audio->getDescription())->toBe('http://www.p1pdd.com');
+});
+
+it('can read creation date', function () {
+ $audio = Audio::get(WV);
+
+ expect($audio->getCreationDate())->toBe('2016');
});
it('can read file id3v1', function (string $path) {
@@ -150,11 +71,17 @@
expect($audio->getAlbumArtist())->toBeString();
expect($audio->getComposer())->toBeNull();
- expect($audio->getgetExtension())->toBe($extension);
+ expect($audio->getExtension())->toBe($extension);
expect($audio->getFormat())->toBe($format);
expect($audio->getDuration())->toBeFloat();
- expect($audio->getDurationHumanReadable())->toBe('00:00:11');
+ expect($audio->getDurationHuman())->toBe('00:00:11');
expect($audio->getExtras())->toBeArray();
expect($audio)->toBeInstanceOf(Audio::class);
})->with([...AUDIO_ID3_V1]);
+
+it('can read wrong audio file', function () {
+ $audio = Audio::get(MD);
+
+ expect($audio->isValid())->toBeFalse();
+});
diff --git a/tests/AudiobookTest.php b/tests/AudiobookTest.php
index 3bcc230..f9b4e6a 100644
--- a/tests/AudiobookTest.php
+++ b/tests/AudiobookTest.php
@@ -2,6 +2,70 @@
use Kiwilan\Audio\Audio;
use Kiwilan\Audio\Enums\AudioFormatEnum;
+use Kiwilan\Audio\Enums\AudioTypeEnum;
+use Kiwilan\Audio\Models\AudioMetadata;
+
+it('can read audiobook', function () {
+ $audiobook = Audio::get(AUDIOBOOK_RH);
+
+ expect($audiobook->getPath())->toContain('tests/media/audiobook_rh.m4b');
+ expect($audiobook->getExtension())->toBe('m4b');
+ expect($audiobook->getFormat())->toBe(AudioFormatEnum::m4b);
+ expect($audiobook->getType())->toBe(AudioTypeEnum::quicktime);
+
+ expect($audiobook->getMetadata())->toBeInstanceOf(AudioMetadata::class);
+
+ $raw = $audiobook->getRawTags();
+ expect($raw['title'])->toBe('Assassin’s Apprentice');
+ expect($raw['artist'])->toBe('Robin Hobb');
+ expect($raw['album'])->toBe('Assassin’s Apprentice');
+ expect($raw['genre'])->toBe('Animals/Political/Epic/Military');
+ expect($raw['origyear'])->toBe('2024/09/30');
+ expect($raw['track_number'])->toBe('1/1');
+ expect($raw['disc_number'])->toBe('1');
+ expect($raw['compilation'])->toBe(1);
+ expect($raw['creation_date'])->toBe('2024-9-30T12:00:00Z');
+ expect($raw['encoding_tool'])->toBe('Audiobook Builder 2.2.9 (www.splasm.com), macOS 15.0');
+ expect($raw['subtitle'])->toBe('Subtitle');
+ expect($raw['description_long'])->toBeString();
+ expect($raw['language'])->toBe('English');
+ expect($raw['lyrics'])->toBe('The Farseer #01');
+ expect($raw['stik'])->toBe('Audiobook');
+ expect($raw['encoded_by'])->toBe('©2012 Robin Hobb (P)2012 HarperCollins Publishers Limited');
+ expect($raw['description'])->toBeString();
+ expect($raw['copyright'])->toBe('HarperCollins');
+ expect($raw['isbn'])->toBe('ISBN');
+ expect($raw['composer'])->toBe('Paul Boehmer');
+ expect($raw['comment'])->toBe('English');
+ expect($raw['asin'])->toBe('ASIN');
+ expect($raw['album_artist'])->toBe('Robin Hobb');
+
+ expect($audiobook->isWritable())->toBeTrue();
+ expect($audiobook->isValid())->toBeTrue();
+ expect($audiobook->hasCover())->toBeTrue();
+
+ expect($audiobook->getTitle())->toBe('Assassin’s Apprentice');
+ expect($audiobook->getArtist())->toBe('Robin Hobb');
+ expect($audiobook->getAlbum())->toBe('Assassin’s Apprentice');
+ expect($audiobook->getGenre())->toBe('Animals/Political/Epic/Military');
+ expect($audiobook->getYear())->toBe(2024);
+ expect($audiobook->getTrackNumber())->toBe('1/1');
+ expect($audiobook->getTrackNumberInt())->toBe(1);
+ expect($audiobook->getComment())->toBe('English');
+ expect($audiobook->getAlbumArtist())->toBe('Robin Hobb');
+ expect($audiobook->getComposer())->toBe('Paul Boehmer');
+ expect($audiobook->getDiscNumber())->toBe('1');
+ expect($audiobook->getDiscNumberInt())->toBe(1);
+ expect($audiobook->isCompilation())->toBeTrue();
+ expect($audiobook->getCreationDate())->toBe('2024-09-30T12:00:00Z');
+ expect($audiobook->getCopyright())->toBe('HarperCollins');
+ expect($audiobook->getEncodingBy())->toBe('©2012 Robin Hobb (P)2012 HarperCollins Publishers Limited');
+ expect($audiobook->getEncoding())->toBe('Audiobook Builder 2.2.9 (www.splasm.com), macOS 15.0');
+ expect($audiobook->getDescription())->toBeString();
+ expect($audiobook->getSynopsis())->toBeString();
+ expect($audiobook->getLanguage())->toBe('English');
+ expect($audiobook->getLyrics())->toBe('The Farseer #01');
+});
it('can read audiobook file m4b', function (string $file) {
$audio = Audio::get($file);
@@ -24,31 +88,25 @@
expect($audio->getEncoding())->toBe('Audiobook Builder 2.2.6 (www.splasm.com), macOS 13.4');
expect($audio->getCopyright())->toBe('Copyright');
expect($audio->getDescription())->toBe('Description');
- expect($audio->getPodcastDescription())->toBe('Synopsis');
+ expect($audio->getSynopsis())->toBe('Synopsis');
expect($audio->getLanguage())->toBe('Language');
expect($audio->getLyrics())->toBe('Lyrics');
- expect($audio->getStik())->toBe('Audiobook');
expect($audio->getDuration())->toBe(11.00);
- expect($audio->getDurationHumanReadable())->toBe('00:00:11');
+ expect($audio->getDurationHuman())->toBe('00:00:11');
expect($audio->getExtras())->toBeArray();
- expect($audio->toArray())->toBeArray();
-
- expect($audio->getTags())->toBeArray();
- expect($audio->getTag('title'))->toBe('P1PDD Saison 1');
- expect($audio->getTag('artist'))->toBe('Mr Piouf');
- expect($audio->getTag('album'))->toBe('P1PDD Saison 1');
- expect($audio->getTag('genre'))->toBe('Audiobooks');
- expect($audio->getTag('track_number'))->toBe('1/1');
- expect($audio->getTag('comment'))->toBe('P1PDD team');
+
+ expect($audio->getRawTags())->toBeArray();
+ expect($audio->getRawTagsKey('title'))->toBe('P1PDD Saison 1');
+ expect($audio->getRawTagsKey('artist'))->toBe('Mr Piouf');
+ expect($audio->getRawTagsKey('album'))->toBe('P1PDD Saison 1');
+ expect($audio->getRawTagsKey('genre'))->toBe('Audiobooks');
+ expect($audio->getRawTagsKey('track_number'))->toBe('1/1');
+ expect($audio->getRawTagsKey('comment'))->toBe('P1PDD team');
})->with([AUDIOBOOK]);
it('can read audiobook file mp3', function (string $file) {
$audio = Audio::get($file);
- expect(count($audio->getTags()))->toBe(16);
- expect(count($audio->getTags('id3v2')))->toBe(15);
-
- expect(count($audio->getAudioFormats()))->toBe(3);
- expect($audio->getAudioFormats())->toBeArray();
- expect($audio->toArray())->toBeArray();
+ expect(count($audio->getRawTags()))->toBe(15);
+ expect(count($audio->getRawTags('id3v2')))->toBe(15);
})->with([AUDIOBOOK_MP3]);
diff --git a/tests/Mp3Test.php b/tests/Mp3Test.php
deleted file mode 100644
index 7598f3c..0000000
--- a/tests/Mp3Test.php
+++ /dev/null
@@ -1,80 +0,0 @@
-toBeInstanceOf(Audio::class);
- expect($audio->getTitle())->toBe('Introduction');
- expect($audio->getArtist())->toBe('Mr Piouf');
- expect($audio->getAlbum())->toBe('P1PDD Le conclave de Troie');
- expect($audio->getGenre())->toBe('Roleplaying game');
- expect($audio->getYear())->toBe(2016);
- expect($audio->getTrackNumber())->toBe('1');
- expect($audio->getComment())->toBe('http://www.p1pdd.com');
- expect($audio->getAlbumArtist())->toBe('P1PDD & Mr Piouf');
- expect($audio->getComposer())->toBe('P1PDD & Piouf');
- expect($audio->getDiscNumber())->toBe('1');
- expect($audio->isCompilation())->toBe(true);
- expect($audio->getPath())->toBe(MP3);
- expect($audio->getFormat())->toBe(AudioFormatEnum::mp3);
- expect($audio->getDuration())->toBe(11.05);
- expect($audio->getDurationHumanReadable())->toBe('00:00:11');
- expect($audio->getExtras())->toBeArray();
-
- $audio = $audio->getAudio();
- expect($audio->getFilesize())->toBe(272737);
- expect($audio->getExtension())->toBe('mp3');
- expect($audio->getEncoding())->toBe('UTF-8');
- expect($audio->getMimeType())->toBe('audio/mpeg');
- expect($audio->getDurationSeconds())->toBe(11.0496875);
- expect($audio->getDurationReadable())->toBe('0:11');
- expect($audio->getBitrate())->toBe(128000);
- expect($audio->getBitrateMode())->toBe('cbr');
- expect($audio->getSampleRate())->toBe(44100);
- expect($audio->getChannels())->toBe(2);
- expect($audio->getChannelMode())->toBe('joint stereo');
- expect($audio->getLossless())->toBe(false);
- expect($audio->getCompressionRatio())->toBe(0.09070294784580499);
-});
-
-it('can extract cover mp3', function () {
- $audio = Audio::get(MP3);
- $cover = $audio->getCover();
-
- expect($cover)->toBeInstanceOf(AudioCover::class);
- expect($cover->getContents())->toBeString();
- expect($cover->getMimeType())->toBe('image/jpeg');
- expect($cover->getWidth())->toBe(640);
- expect($cover->getHeight())->toBe(640);
-
- $path = 'tests/output/cover.jpg';
- file_put_contents($path, $cover->getContents());
- expect(file_exists($path))->toBeTrue();
- expect($path)->toBeReadableFile();
-});
-
-it('can read file mp3 no meta', function () {
- $audio = Audio::get(MP3_NO_META);
-
- expect($audio)->toBeInstanceOf(Audio::class);
- expect($audio->getTitle())->toBeNull();
- expect($audio->getArtist())->toBeNull();
- expect($audio->getAlbum())->toBeNull();
- expect($audio->getGenre())->toBeNull();
- expect($audio->getYear())->toBeNull();
- expect($audio->getTrackNumber())->toBeNull();
- expect($audio->getComment())->toBeNull();
- expect($audio->getAlbumArtist())->toBeNull();
- expect($audio->getComposer())->toBeNull();
- expect($audio->getDiscNumber())->toBeNull();
- expect($audio->isCompilation())->toBeFalse();
- expect($audio->getPath())->toBe(MP3_NO_META);
-});
-
-it("can fail if file didn't exists", function () {
- expect(fn () => Audio::get('tests/media/unknown.mp3'))->toThrow(Exception::class);
-});
diff --git a/tests/Pest.php b/tests/Pest.php
index a265cc3..ce1dc99 100644
--- a/tests/Pest.php
+++ b/tests/Pest.php
@@ -76,6 +76,9 @@ function addWriterFilesForTests()
define('WMA', __DIR__.'/media/test.wma');
define('WV', __DIR__.'/media/test.wv');
+define('AUDIOBOOK_RH', __DIR__.'/media/audiobook_rh.m4b');
+define('AUDIOBOOK_RH_NOCOVER', __DIR__.'/media/audiobook_rh-nocover.m4b');
+
define('AUDIOBOOKS', [
AUDIOBOOK,
AUDIOBOOK_MP3,
@@ -131,3 +134,16 @@ function addWriterFilesForTests()
// WMA_WRITER,
// WV_WRITER,
]);
+
+function clearOutput()
+{
+ $files = glob('./tests/output/*');
+ foreach ($files as $file) {
+ if (is_file($file)) {
+ if ($file === './tests/output/.gitignore') {
+ continue;
+ }
+ unlink($file);
+ }
+ }
+}
diff --git a/tests/ReaderTest.php b/tests/ReaderTest.php
index dda2a98..c7821db 100644
--- a/tests/ReaderTest.php
+++ b/tests/ReaderTest.php
@@ -1,16 +1,34 @@
getId3Reader()->getAudio()->streams();
+
+ expect($streams)->toBeArray();
+ expect($streams)->toHaveCount(1);
+ expect($streams[0]->dataFormat())->toBe('mp3');
+ expect($streams[0]->channels())->toBe(2);
+ expect($streams[0]->sampleRate())->toBe(44100);
+ expect($streams[0]->bitrate())->toBe(128000.0);
+ expect($streams[0]->channelmode())->toBe('joint stereo');
+ expect($streams[0]->bitrateMode())->toBe('cbr');
+ expect($streams[0]->codec())->toBe('LAME');
+ expect($streams[0]->encoder())->toBe('LAME3.100');
+ expect($streams[0]->lossless())->toBeFalse();
+ expect($streams[0]->encoderOptions())->toBe('CBR128');
+ expect($streams[0]->compressionRatio())->toBe(0.09070294784580499);
+});
it('can parse ID3 reader', function (string $path) {
$audio = Audio::get($path);
- $reader = $audio->getReader();
+ $reader = $audio->getId3Reader();
$raw = $reader->getRaw();
expect($reader->getInstance())->toBeInstanceOf(getID3::class);
@@ -41,9 +59,6 @@
expect($reader->getPlaytimeSeconds())->toBeFloat();
}
- if ($reader->getTagsHtml()) {
- expect($reader->getTagsHtml())->toBeInstanceOf(Id3TagsHtml::class);
- }
if ($reader->getBitrate()) {
expect($reader->getBitrate())->toBeFloat();
}
@@ -51,16 +66,3 @@
expect($reader->getPlaytimeString())->toBeString();
}
})->with([...AUDIO]);
-
-it('can parse with ID3 methods', function (string $path) {
- $audio = Audio::get($path);
- $type = $audio->getType()->value;
- $tags = $audio->getReader()->getTags();
-
- if ($type === 'id3') {
- $type = 'id3v2';
- }
-
- $metadata = $tags->{$type}();
- expect($metadata->toArray())->toBeArray();
-})->with([...AUDIO]);
diff --git a/tests/WriterTest.php b/tests/WriterTest.php
index a1c3c60..a4d2d84 100644
--- a/tests/WriterTest.php
+++ b/tests/WriterTest.php
@@ -4,276 +4,276 @@
use Kiwilan\Audio\Enums\AudioFormatEnum;
use Kiwilan\Audio\Models\AudioCore;
-it('can update file', function (string $path) {
- $audio = Audio::get($path);
- $random = (string) rand(1, 1000);
- $tag = $audio->update()
- ->title($random)
- ->artist('New Artist')
- ->album('New Album')
- ->genre('New Genre')
- ->year('2022')
- ->trackNumber('2/10')
- ->albumArtist('New Album Artist')
- ->comment('New Comment')
- ->composer('New Composer')
- ->creationDate('2021-01-01')
- ->description('New Description')
- ->discNumber('2/2')
- ->encodingBy('New Encoding By')
- ->encoding('New Encoding')
- ->isNotCompilation()
- ->lyrics('New Lyrics')
- ->stik('New Stik')
- ->cover(FOLDER);
-
- $core = $tag->getCore();
- $tag->save();
-
- $audio = Audio::get($path);
-
- expect($audio->getTitle())->toBe($random);
- expect($audio->getArtist())->toBe('New Artist');
- expect($audio->getAlbum())->toBe('New Album');
- expect($audio->getGenre())->toBe('New Genre');
- expect($audio->getYear())->toBe(2022);
- expect($audio->getAlbumArtist())->toBe('New Album Artist');
- expect($audio->getComment())->toBe('New Comment');
- expect($audio->getComposer())->toBe('New Composer');
- expect($audio->getDiscNumber())->toBe('2/2');
- expect($audio->isCompilation())->toBeFalse();
-
- expect($audio->getCreationDate())->toBeNull();
- if ($audio->getFormat() === AudioFormatEnum::mp3) {
- expect($audio->getDescription())->toBeNull();
- expect($audio->getEncoding())->toBeNull();
- }
- expect($audio->getEncodingBy())->toBeNull();
- if ($audio->getLyrics()) {
- expect($audio->getLyrics())->toBe('New Lyrics');
- }
- expect($audio->getStik())->toBeNull();
-
- if ($audio->getFormat() !== AudioFormatEnum::mp3) {
- expect($audio->getTrackNumber())->toBe('2/10');
- } else {
- expect($audio->getTrackNumber())->toBe('2');
- }
-
- if ($tag->getCore()->hasCover()) {
- $content = file_get_contents(FOLDER);
- expect($tag->getCore()->getCover()->data())->toBe(base64_encode($content));
- }
-})->with(AUDIO_WRITER);
-
-it('can read use file content as cover', function (string $path) {
- $audio = Audio::get($path);
-
- $tag = $audio->update()
- ->cover(file_get_contents(FOLDER));
-
- $tag->save();
-
- $audio = Audio::get($path);
-
- $content = file_get_contents(FOLDER);
- expect($tag->getCore()->getCover()->data())->toBe(base64_encode($content));
-})->with([MP3_WRITER]);
-
-it('can read use tags', function (string $path) {
- $audio = Audio::get($path);
-
- $random = (string) rand(1, 1000);
- $image = getimagesize(FOLDER);
- $coverData = file_get_contents(FOLDER);
- $coverPicturetypeid = $image[2];
- $coverDescription = 'cover';
- $coverMime = $image['mime'];
- $tag = $audio->update()
- ->tags([
- 'title' => $random,
- 'attached_picture' => [
- [
- 'data' => $coverData,
- 'picturetypeid' => $coverPicturetypeid,
- 'description' => $coverDescription,
- 'mime' => $coverMime,
- ],
- ],
- ]);
-
- $tag->save();
-
- $audio = Audio::get($path);
- expect($audio->getTitle())->toBe($random);
-
- $content = file_get_contents(FOLDER);
- expect($audio->getCover()->getContents())->toBe($content);
-})->with([MP3_WRITER]);
-
-it('can update use tags with tag formats', function (string $path) {
- $audio = Audio::get($path);
-
- $random = (string) rand(1, 1000);
- $tag = $audio->update()
- ->tags([
- 'title' => $random,
- ])
- ->tagFormats(['id3v1', 'id3v2.4']);
-
- $tag->save();
-
- $audio = Audio::get($path);
- expect($audio->getTitle())->toBe($random);
-})->with([MP3_WRITER]);
-
-it('can update with tags and handle native metadata', function (string $path) {
- $audio = Audio::get($path);
-
- $tag = $audio->update()
- ->isCompilation()
- ->tags([
- 'title' => 'New Title',
- 'band' => 'New Band',
- ])
- ->tagFormats(['id3v1', 'id3v2.4']);
-
- $tag->save();
-
- $audio = Audio::get($path);
- expect($audio->getTitle())->toBe('New Title');
- expect($audio->getAlbumArtist())->toBe('New Band');
- expect($audio->isCompilation())->toBeTrue();
-})->with([MP3_WRITER]);
-
-it('can update with new path', function (string $path) {
- $audio = Audio::get($path);
- $newPath = 'tests/output/new.mp3';
-
- $tag = $audio->update()
- ->title('New Title')
- ->path($newPath);
-
- $tag->save();
-
- $audio = Audio::get($newPath);
- expect($audio->getTitle())->toBe('New Title');
-})->with([MP3_WRITER]);
+// it('can update file', function (string $path) {
+// $audio = Audio::get($path);
+// $random = (string) rand(1, 1000);
+// $tag = $audio->update()
+// ->title($random)
+// ->artist('New Artist')
+// ->album('New Album')
+// ->genre('New Genre')
+// ->year('2022')
+// ->trackNumber('2/10')
+// ->albumArtist('New Album Artist')
+// ->comment('New Comment')
+// ->composer('New Composer')
+// ->creationDate('2021-01-01')
+// ->description('New Description')
+// ->discNumber('2/2')
+// ->encodingBy('New Encoding By')
+// ->encoding('New Encoding')
+// ->isNotCompilation()
+// ->lyrics('New Lyrics')
+// ->stik('New Stik')
+// ->cover(FOLDER);
+
+// $core = $tag->getCore();
+// $tag->save();
+
+// $audio = Audio::get($path);
+
+// expect($audio->getTitle())->toBe($random);
+// expect($audio->getArtist())->toBe('New Artist');
+// expect($audio->getAlbum())->toBe('New Album');
+// expect($audio->getGenre())->toBe('New Genre');
+// expect($audio->getYear())->toBe(2022);
+// expect($audio->getAlbumArtist())->toBe('New Album Artist');
+// expect($audio->getComment())->toBe('New Comment');
+// expect($audio->getComposer())->toBe('New Composer');
+// expect($audio->getDiscNumber())->toBe('2/2');
+// expect($audio->isCompilation())->toBeFalse();
+
+// expect($audio->getCreationDate())->toBeNull();
+// if ($audio->getFormat() === AudioFormatEnum::mp3) {
+// expect($audio->getDescription())->toBeNull();
+// expect($audio->getEncoding())->toBeNull();
+// }
+// expect($audio->getEncodingBy())->toBeNull();
+// if ($audio->getLyrics()) {
+// expect($audio->getLyrics())->toBe('New Lyrics');
+// }
+// expect($audio->getStik())->toBeNull();
+
+// if ($audio->getFormat() !== AudioFormatEnum::mp3) {
+// expect($audio->getTrackNumber())->toBe('2/10');
+// } else {
+// expect($audio->getTrackNumber())->toBe('2');
+// }
+
+// if ($tag->getCore()->hasCover()) {
+// $content = file_get_contents(FOLDER);
+// expect($tag->getCore()->getCover()->data())->toBe(base64_encode($content));
+// }
+// })->with(AUDIO_WRITER);
+
+// it('can read use file content as cover', function (string $path) {
+// $audio = Audio::get($path);
+
+// $tag = $audio->update()
+// ->cover(file_get_contents(FOLDER));
+
+// $tag->save();
+
+// $audio = Audio::get($path);
+
+// $content = file_get_contents(FOLDER);
+// expect($tag->getCore()->getCover()->data())->toBe(base64_encode($content));
+// })->with([MP3_WRITER]);
+
+// it('can read use tags', function (string $path) {
+// $audio = Audio::get($path);
+
+// $random = (string) rand(1, 1000);
+// $image = getimagesize(FOLDER);
+// $coverData = file_get_contents(FOLDER);
+// $coverPicturetypeid = $image[2];
+// $coverDescription = 'cover';
+// $coverMime = $image['mime'];
+// $tag = $audio->update()
+// ->tags([
+// 'title' => $random,
+// 'attached_picture' => [
+// [
+// 'data' => $coverData,
+// 'picturetypeid' => $coverPicturetypeid,
+// 'description' => $coverDescription,
+// 'mime' => $coverMime,
+// ],
+// ],
+// ]);
+
+// $tag->save();
+
+// $audio = Audio::get($path);
+// expect($audio->getTitle())->toBe($random);
+
+// $content = file_get_contents(FOLDER);
+// expect($audio->getCover()->getContents())->toBe($content);
+// })->with([MP3_WRITER]);
+
+// it('can update use tags with tag formats', function (string $path) {
+// $audio = Audio::get($path);
+
+// $random = (string) rand(1, 1000);
+// $tag = $audio->update()
+// ->tags([
+// 'title' => $random,
+// ])
+// ->tagFormats(['id3v1', 'id3v2.4']);
+
+// $tag->save();
+
+// $audio = Audio::get($path);
+// expect($audio->getTitle())->toBe($random);
+// })->with([MP3_WRITER]);
+
+// it('can update with tags and handle native metadata', function (string $path) {
+// $audio = Audio::get($path);
+
+// $tag = $audio->update()
+// ->isCompilation()
+// ->tags([
+// 'title' => 'New Title',
+// 'band' => 'New Band',
+// ])
+// ->tagFormats(['id3v1', 'id3v2.4']);
+
+// $tag->save();
+
+// $audio = Audio::get($path);
+// expect($audio->getTitle())->toBe('New Title');
+// expect($audio->getAlbumArtist())->toBe('New Band');
+// expect($audio->isCompilation())->toBeTrue();
+// })->with([MP3_WRITER]);
+
+// it('can update with new path', function (string $path) {
+// $audio = Audio::get($path);
+// $newPath = 'tests/output/new.mp3';
+
+// $tag = $audio->update()
+// ->title('New Title')
+// ->path($newPath);
+
+// $tag->save();
-it('can update with merged tags and core methods', function (string $path) {
- $audio = Audio::get($path);
-
- $tag = $audio->update()
- ->title('New Title')
- ->tags([
- 'title' => 'New Title tag',
- 'band' => 'New Band',
- ]);
+// $audio = Audio::get($newPath);
+// expect($audio->getTitle())->toBe('New Title');
+// })->with([MP3_WRITER]);
- $tag->save();
+// it('can update with merged tags and core methods', function (string $path) {
+// $audio = Audio::get($path);
- $audio = Audio::get($path);
- expect($audio->getTitle())->toBe('New Title');
- expect($audio->getAlbumArtist())->toBe('New Band');
-})->with([MP3_WRITER]);
-
-it('can use arrow function safe with unsupported tags', function (string $path) {
- $audio = Audio::get($path);
-
- $tag = $audio->update()
- ->title('New Title')
- ->encoding('New encoding');
-
- expect(fn () => $tag->save())->not()->toThrow(Exception::class);
-
- $audio = Audio::get($path);
- expect($audio->getTitle())->toBe('New Title');
-})->with([MP3_WRITER]);
+// $tag = $audio->update()
+// ->title('New Title')
+// ->tags([
+// 'title' => 'New Title tag',
+// 'band' => 'New Band',
+// ]);
-it('can use arrow function safe with unsupported formats', function (string $path) {
- $audio = Audio::get($path);
+// $tag->save();
- $tag = $audio->update()
- ->title('New Title Alac');
+// $audio = Audio::get($path);
+// expect($audio->getTitle())->toBe('New Title');
+// expect($audio->getAlbumArtist())->toBe('New Band');
+// })->with([MP3_WRITER]);
- expect(fn () => $tag->save())->toThrow(Exception::class);
-})->with([ALAC_WRITER]);
+// it('can use arrow function safe with unsupported tags', function (string $path) {
+// $audio = Audio::get($path);
-it('can get core before save', function (string $path) {
- $audio = Audio::get($path);
+// $tag = $audio->update()
+// ->title('New Title')
+// ->encoding('New encoding');
- $tag = $audio->update()
- ->title('New Title')
- ->tags([
- 'title' => 'New Title tag',
- 'band' => 'New Band',
- ]);
+// expect(fn () => $tag->save())->not()->toThrow(Exception::class);
- expect($tag->getCore())->toBeInstanceOf(AudioCore::class);
-})->with([MP3_WRITER]);
+// $audio = Audio::get($path);
+// expect($audio->getTitle())->toBe('New Title');
+// })->with([MP3_WRITER]);
-it('can handle exceptions', function (string $path) {
- $audio = Audio::get($path);
+// it('can use arrow function safe with unsupported formats', function (string $path) {
+// $audio = Audio::get($path);
- $tag = $audio->update()
- ->tags([
- 'title' => 'New Title',
- 'albumArtist' => 'New Album Artist',
- ])
- ->options(['encoding' => 'UTF-8']);
+// $tag = $audio->update()
+// ->title('New Title Alac');
- expect(fn () => $tag->save())->toThrow(Exception::class);
-})->with([MP3_WRITER]);
+// expect(fn () => $tag->save())->toThrow(Exception::class);
+// })->with([ALAC_WRITER]);
-it('can skip exceptions', function (string $path) {
- $audio = Audio::get($path);
+// it('can get core before save', function (string $path) {
+// $audio = Audio::get($path);
- $tag = $audio->update()
- ->tags([
- 'title' => 'New Title',
- 'albumArtist' => 'New Album Artist',
- ])
- ->preventFailOnError();
+// $tag = $audio->update()
+// ->title('New Title')
+// ->tags([
+// 'title' => 'New Title tag',
+// 'band' => 'New Band',
+// ]);
- $tag->save();
+// expect($tag->getCore())->toBeInstanceOf(AudioCore::class);
+// })->with([MP3_WRITER]);
- $audio = Audio::get($path);
- expect($audio->getTitle())->toBe('New Title');
- expect($audio->getAlbumArtist())->toBeNull();
-})->with([MP3_WRITER]);
+// it('can handle exceptions', function (string $path) {
+// $audio = Audio::get($path);
-it('can remove old tags', function (string $path) {
- $audio = Audio::get($path);
+// $tag = $audio->update()
+// ->tags([
+// 'title' => 'New Title',
+// 'albumArtist' => 'New Album Artist',
+// ])
+// ->options(['encoding' => 'UTF-8']);
- $tag = $audio->update()
- ->title('New Title')
- ->removeOldTags()
- ->path('tests/output/new.mp3');
+// expect(fn () => $tag->save())->toThrow(Exception::class);
+// })->with([MP3_WRITER]);
- $tag->save();
+// it('can skip exceptions', function (string $path) {
+// $audio = Audio::get($path);
- $audio = Audio::get('tests/output/new.mp3');
- expect($audio->getTitle())->toBe('New Title');
- expect($audio->getAlbumArtist())->toBeNull();
-})->with([MP3]);
+// $tag = $audio->update()
+// ->tags([
+// 'title' => 'New Title',
+// 'albumArtist' => 'New Album Artist',
+// ])
+// ->preventFailOnError();
-it('can use tags with cover', function (string $path) {
- $audio = Audio::get($path);
+// $tag->save();
- $tag = $audio->update()
- ->tags([
- 'title' => 'New Title',
- ])
- ->cover(FOLDER);
+// $audio = Audio::get($path);
+// expect($audio->getTitle())->toBe('New Title');
+// expect($audio->getAlbumArtist())->toBeNull();
+// })->with([MP3_WRITER]);
- $tag->save();
+// it('can remove old tags', function (string $path) {
+// $audio = Audio::get($path);
- $audio = Audio::get($path);
+// $tag = $audio->update()
+// ->title('New Title')
+// ->removeOldTags()
+// ->path('tests/output/new.mp3');
+
+// $tag->save();
+
+// $audio = Audio::get('tests/output/new.mp3');
+// expect($audio->getTitle())->toBe('New Title');
+// expect($audio->getAlbumArtist())->toBeNull();
+// })->with([MP3]);
+
+// it('can use tags with cover', function (string $path) {
+// $audio = Audio::get($path);
+
+// $tag = $audio->update()
+// ->tags([
+// 'title' => 'New Title',
+// ])
+// ->cover(FOLDER);
- $content = file_get_contents(FOLDER);
- expect($audio->getTitle())->toBe('New Title');
- expect($tag->getCore()->getCover()->data())->toBe(base64_encode($content));
-})->with([MP3_WRITER]);
+// $tag->save();
+
+// $audio = Audio::get($path);
+
+// $content = file_get_contents(FOLDER);
+// expect($audio->getTitle())->toBe('New Title');
+// expect($tag->getCore()->getCover()->data())->toBe(base64_encode($content));
+// })->with([MP3_WRITER]);
// it('can change podcast description and language', function () {
// $audio = Audio::get(AUDIOBOOK);
@@ -297,3 +297,33 @@
// $audio = Audio::get('tests/output/new.mp3');
// expect($audio->getTitle())->toBe('Introduction');
// })->with([MP3]);
+
+it('can update tags', function () {
+ $audio = Audio::get(MP3);
+
+ expect($audio->getAlbum())->toBe('P1PDD Le conclave de Troie');
+ expect($audio->getArtist())->toBe('Mr Piouf');
+ expect($audio->getAlbumArtist())->toBe('P1PDD & Mr Piouf');
+ expect($audio->getTitle())->toBe('Introduction');
+ expect($audio->getTrackNumber())->toBe('1');
+ expect($audio->getYear())->toBe(2016);
+
+ ray($audio->getGenre());
+ expect($audio->getGenre())->toBe('Roleplaying game');
+
+ // $audio->update()
+ // ->album('P1PDD')
+ // ->save();
+
+ // $audio->update()
+ // ->album('P1PDD')
+ // ->save();
+
+ // $tag = $audio->update()
+ // ->tags([
+ // 'title' => 'New Title',
+ // ])
+ // ->save();
+
+ // expect($audio->getAlbum())->toBe('P1PDD');
+});
diff --git a/tests/media/audiobook_rh-nocover.m4b b/tests/media/audiobook_rh-nocover.m4b
new file mode 100644
index 0000000..4017a1b
Binary files /dev/null and b/tests/media/audiobook_rh-nocover.m4b differ
diff --git a/tests/media/audiobook_rh.m4b b/tests/media/audiobook_rh.m4b
new file mode 100644
index 0000000..f5e4e88
Binary files /dev/null and b/tests/media/audiobook_rh.m4b differ