API / Minn\Media\Av / Id3

Id3 final class

Minn\Media\Av\Id3 · public/minn/src/Minn/Media/Av/Id3.php · 356 lines

ID3 tags, as the reference's audio reader names what they say (probe media-meta): an ID3v2 tag (versions 2.2 to 2.4) at the start of a file and an ID3v1 tag in its last 128 bytes. Each frame the reader knows becomes a named list of values in the order the frames come; one it does not know (a play count, a private frame, a podcast flag) is left out. ID3v2 text is made UTF-8 whatever its encoding; ID3v1 text is kept as its bytes.

Used by 1

Constants and properties

privateFRAMES = 'COM:comment COMM:comment TAL:album TALB:album TBP:bpm TBPM:bpm TCM:composer TCMP:part_of_a_compilation TCO:genre TCOM:composer TCON:genre TCOP:copyright_message TCP:part_of_a_compilation TCR:copyright_message TDA:date TDAT:date TDEN:encoding_time TDLY:playlist_delay TDOR:original_release_time TDRC:recording_time TDRL:release_time TDTG:tagging_time TDY:playlist_delay TEN:encoded_by TENC:encoded_by TEXT:lyricist TFLT:file_type TFT:file_type TIM:time TIME:time TIPL:involved_people_list TIT1:content_group_description TIT2:title TIT3:subtitle TKE:initial_key TKEY:initial_key TLA:language TLAN:language TLE:length TLEN:length TMCL:musician_credits_list TMED:media_type TMOO:mood TMT:media_type TOA:original_artist TOAL:original_album TOF:original_filename TOFN:original_filename TOL:original_lyricist TOLY:original_lyricist TOPE:original_artist TOR:original_year TORY:original_year TOT:original_album TOWN:file_owner TP1:artist TP2:band TP3:conductor TP4:remixer TPA:part_of_a_set TPB:publisher TPE1:artist TPE2:band TPE3:conductor TPE4:remixer TPOS:part_of_a_set TPRO:produced_notice TPUB:publisher TRC:isrc TRCK:track_number TRD:recording_dates TRDA:recording_dates TRK:track_number TRSN:internet_radio_station_name TRSO:internet_radio_station_owner TS2:album_artist_sort_order TSA:album_sort_order TSC:composer_sort_order TSI:size TSIZ:size TSO2:album_artist_sort_order TSOA:album_sort_order TSOC:composer_sort_order TSOP:performer_sort_order TSOT:title_sort_order TSP:performer_sort_order TSRC:isrc TSS:encoder_settings TSSE:encoder_settings TSST:set_subtitle TST:title_sort_order TT1:content_group_description TT2:title TT3:subtitle TXT:lyricist TXX:text TXXX:text TYE:year TYER:year ULT:unsynchronised_lyric USLT:unsynchronised_lyric WAF:url_file WAR:url_artist WAS:url_source WCM:commercial_information WCOM:commercial_information WCOP:copyright WCP:copyright WOAF:url_file WOAR:url_artist WOAS:url_source WORS:url_station WPAY:url_payment WPB:url_publisher WPUB:url_publisher WXX:url_user WXXX:url_user'
privatePICTURES = array ( 0 => 'APIC', 1 => 'PIC', )
privateDESCRIBED = array ( 0 => 'COMM', 1 => 'COM', 2 => 'USLT', 3 => 'ULT', )
privateOWN_TEXT = array ( 0 => 'TXXX', 1 => 'TXX', 2 => 'WXXX', 3 => 'WXX', )

Public

staticv2(Minn\Media\Av\Source $source): ?array#

The ID3v2 tag at the start of a file: where the bytes after it begin, its version, its named values and its pictures; null with no tag.

@return array{end: int, version: int, comments: array<string, list<string>>, pictures: list<array<string, mixed>>}|null
staticv1(Minn\Media\Av\Source $source): ?array#

The ID3v1 tag in a file's last 128 bytes: the title, artist, album, year and comment (kept when empty), the track of a version 1.1 tag and the named genre; null with no tag.

@return array<string, list<string|int>>|null

Internals 15

Private and protected methods: how the class does its work. Not a contract; they change whenever the code is tidied.

privateframes(string $body, int $at, int $version): array#

Every frame of a tag body, read from $at: the named values (a track "n/m" split into its number and total, a recording time's year added, both after the frames) and the pictures.

@return array{0: array<string, list<string>>, 1: list<array<string, mixed>>}
privateframeData(string $data, int $version, int $format): ?string#

A frame's data with its own flags undone; null for a compressed or encrypted frame.

privatevalues(string $id, string $data): array#

A frame's values: a text frame's (several in version 2.4), a comment's or lyric's text after its language and description, a user frame's value after its description, or a link frame's address. Empty values are left out.

@return list<string>
privateafterDescription(string $text, int $encoding): string#

What follows a description ended by the encoding's terminator.

privateterminator(string $text, int $encoding, int $from = 0): ?int#

Where a string's terminator starts, looking from $from: a NUL, or a NUL pair on a two-byte boundary for UTF-16.

privatedecoded(string $text, int $encoding): array#

Text in one of the four encodings, made UTF-8 and split at its terminators: Latin-1, UTF-16 with a byte-order mark, UTF-16 big-endian, UTF-8.

@return list<string>
privateutf16(string $text): string#

UTF-16 read by its byte-order mark (little-endian without one).

privateterminatorLength(int $encoding): int#

How many bytes end a string in an encoding: two for UTF-16, one otherwise.

privateattachedPicture(string $data): ?array#

An APIC frame's image: its bytes, type and the size it draws at; null when it holds no bytes.

@return array<string, mixed>|null
privateolderPicture(string $data): ?array#

A version 2.2 PIC frame's image: its bytes and the type its three-letter format names; null when it holds no bytes.

@return array<string, mixed>|null
privatepictureBytes(string $rest, int $encoding): string#

A picture's bytes: what follows its description.

privategenres(string $value): array#

The genres a genre frame's value names, the first being the one a site shows: a number in parentheses or alone is looked up (0 names nothing), a value starting "(RX)" or "(CR)" or an unknown reference is kept whole, "((" starts literal text, and otherwise the text before a slash or semicolon is the genre, its parentheses dropped.

@return list<string>
privatenumbered(int $number): array#

A genre by number in an ID3v2 tag: its name, an empty string for a number with none, "Unknown" for 255, and nothing for 0.

@return list<string>
privatesyncsafe(string $bytes): int#

A 28-bit size written seven bits to a byte.

privatenames(): array#
@return array<string, string> frame id => the name its values go under