Čteme data z ID3v1 tagů v PHP

Pokud jste už někdy dělali vlastní stránku na upload, kam jste si mohli nahrát soubor a poté se zobrazoval v seznamu souborů i s několika informacemi o něm a byl snadno dostupný ke stažení, určitě byste ocenili možnost přidat k těmto informacím i data z ID3 tagů. Konkrétně z ID3v1 tagů, díky jejich jednoduché struktuře. Protože je v2 nepoměrně složitější, tak bych v tomto případě doporučil nějakou specializovanou třídu.

Nejprve je potřeba si ujasnit strukturu ID3v1 tagu v souboru. Ten tvoří posledních 128 bytů v souboru, a to následujícím způsobem :

  • 3 znaky - string “TAG” pokud se jedna o ID3v1 tag
  • 30 znaků - název písničky
  • 30 znaků - umělec
  • 30 znaků - název alba
  • 4 znaky - rok vydání
  • 30 znaků - komentář
  • 1 byt - žánr

Možná bude výstižnější tento obrázek z http://www.id3.org/
ID3v1

Pro čtení souboru použijeme funkci fread(), která za nás obstará převod z binárních hodnot na textové, takže nebudeme muset data unpackovat.

Implementace vypadá nějak takto :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
function GetId3Tags($filename)
{
  //otevreni souboru pro cteni
  $file = fopen($filename, "r");  
 
  //kontrola jestli dany soubor existuje
  if ($file === FALSE)
  {
    return false;
  }
 
  //nastaveni ukazatele na pozici 128 bytu pred koncem souboru
  if (fseek($file, -128, SEEK_END))
  {
    return false;
  }
 
  //nacteni poslednich 128 bytu souboru (ID3v1 tag)
  $tagdata = fread($file, 128);
 
  //kontrola jestli prvni tri pismena techto dat odpovidaji ID3 tagu
  if(substr($tagdata, 0, 3) != "TAG")
  {
    return false;
  }
 
  $id3tag = array();
 
  //cteni id3tagu
  $id3tag['title'] = substr($tagdata, 3, 30);
  $id3tag['artist'] = substr($tagdata, 33, 30);
  $id3tag['album'] = substr($tagdata, 63, 30);
  $id3tag['year'] = substr($tagdata, 93, 4);
  $id3tag['comment'] = substr($tagdata, 97, 30);
 
  //prevod zanru na slovo
  $genreNo = hexdec(bin2hex(substr($tagdata, 127, 1)));
  $id3tag['genre'] = $GLOBALS['genres'][$genreNo];
 
  return $id3tag;
}
 
?>

Doufám, že kód mluví sám za sebe, jenom bych rád dovysvětlil pár důležitých věcí. Jako poslední byte načteme sice číslo žánru, ale v textové podobě, ne binární. Proto jej převedeme do šestnáctkové soustavy, odkud ho poté převedeme do standardní desítkové soustavy. A poté podle tohoto čísla a pole žánrů, kde každému číslu odpovídá jeden žánr určíme textovou reprezentaci tohoto žánru.

Pole žánrů (v příkladu $genres) je následující:

$genres = array(
		0   => 'Blues',
		1   => 'Classic Rock',
		2   => 'Country',
		3   => 'Dance',
		4   => 'Disco',
		5   => 'Funk',
		6   => 'Grunge',
		7   => 'Hip-Hop',
		8   => 'Jazz',
		9   => 'Metal',
		10  => 'New Age',
		11  => 'Oldies',
		12  => 'Other',
		13  => 'Pop',
		14  => 'R&B',
		15  => 'Rap',
		16  => 'Reggae',
		17  => 'Rock',
		18  => 'Techno',
		19  => 'Industrial',
		20  => 'Alternative',
		21  => 'Ska',
		22  => 'Death Metal',
		23  => 'Pranks',
		24  => 'Soundtrack',
		25  => 'Euro-Techno',
		26  => 'Ambient',
		27  => 'Trip-Hop',
		28  => 'Vocal',
		29  => 'Jazz+Funk',
		30  => 'Fusion',
		31  => 'Trance',
		32  => 'Classical',
		33  => 'Instrumental',
		34  => 'Acid',
		35  => 'House',
		36  => 'Game',
		37  => 'Sound Clip',
		38  => 'Gospel',
		39  => 'Noise',
		40  => 'Alternative Rock',
		41  => 'Bass',
		42  => 'Soul',
		43  => 'Punk',
		44  => 'Space',
		45  => 'Meditative',
		46  => 'Instrumental Pop',
		47  => 'Instrumental Rock',
		48  => 'Ethnic',
		49  => 'Gothic',
		50  => 'Darkwave',
		51  => 'Techno-Industrial',
		52  => 'Electronic',
		53  => 'Pop-Folk',
		54  => 'Eurodance',
		55  => 'Dream',
		56  => 'Southern Rock',
		57  => 'Comedy',
		58  => 'Cult',
		59  => 'Gangsta',
		60  => 'Top 40',
		61  => 'Christian Rap',
		62  => 'Pop/Funk',
		63  => 'Jungle',
		64  => 'Native US',
		65  => 'Cabaret',
		66  => 'New Wave',
		67  => 'Psychadelic',
		68  => 'Rave',
		69  => 'Showtunes',
		70  => 'Trailer',
		71  => 'Lo-Fi',
		72  => 'Tribal',
		73  => 'Acid Punk',
		74  => 'Acid Jazz',
		75  => 'Polka',
		76  => 'Retro',
		77  => 'Musical',
		78  => 'Rock & Roll',
		79  => 'Hard Rock',
		80  => 'Folk',
		81  => 'Folk-Rock',
		82  => 'National Folk',
		83  => 'Swing',
		84  => 'Fast Fusion',
		85  => 'Bebob',
		86  => 'Latin',
		87  => 'Revival',
		88  => 'Celtic',
		89  => 'Bluegrass',
		90  => 'Avantgarde',
		91  => 'Gothic Rock',
		92  => 'Progressive Rock',
		93  => 'Psychedelic Rock',
		94  => 'Symphonic Rock',
		95  => 'Slow Rock',
		96  => 'Big Band',
		97  => 'Chorus',
		98  => 'Easy Listening',
		99  => 'Acoustic',
		100 => 'Humour',
		101 => 'Speech',
		102 => 'Chanson',
		103 => 'Opera',
		104 => 'Chamber Music',
		105 => 'Sonata',
		106 => 'Symphony',
		107 => 'Booty Bass',
		108 => 'Primus',
		109 => 'Porn Groove',
		110 => 'Satire',
		111 => 'Slow Jam',
		112 => 'Club',
		113 => 'Tango',
		114 => 'Samba',
		115 => 'Folklore',
		116 => 'Ballad',
		117 => 'Power Ballad',
		118 => 'Rhytmic Soul',
		119 => 'Freestyle',
		120 => 'Duet',
		121 => 'Punk Rock',
		122 => 'Drum Solo',
		123 => 'Acapella',
		124 => 'Euro-House',
		125 => 'Dance Hall',
		126 => 'Goa',
		127 => 'Drum & Bass',
		128 => 'Club-House',
		129 => 'Hardcore',
		130 => 'Terror',
		131 => 'Indie',
		132 => 'BritPop',
		133 => 'Negerpunk',
		134 => 'Polsk Punk',
		135 => 'Beat',
		136 => 'Christian Gangsta Rap',
		137 => 'Heavy Metal',
		138 => 'Black Metal',
		139 => 'Crossover',
		140 => 'Contemporary Christian',
		141 => 'Christian Rock',
		142 => 'Merengue',
		143 => 'Salsa',
		144 => 'Trash Metal',
		145 => 'Anime',
		146 => 'Jpop',
		147 => 'Synthpop');

?>

Jenom si dejte pozor, kdybyste chtěli získávat ID3v1.1 data, protože ty jsou trochu jinak strukturovaná. A to tak, že pole comment je zkráceno z o dva znaky, po něm následuje nula (0) a následující byt je pořadí skladby na albu. Poté už je žánr, jako v ID3v1.

Ještě příklad použití na konec:

$data = GetId3Tags("01_Porcupine Tree - Blackest Eyes.mp3");

a obsah $data bude

Array
(
	[title] => Blackest Eyes
	[artist] => Porcupine Tree
 	[album] => XM
	[year] => 2003
	[comment] =>
	[genre] => Progressive Rock
)

Tags: ,

Leave a Reply