Reading mp3 informations with php (id3 tags)

Inside mp3 files there are often some usefull informations stored. Those data are called “id3 tags” and deal with Author…

Febbraio 22, 2010

Inside mp3 files there are often some usefull informations stored. Those data are called “id3 tags” and deal with Author name, Title and Album name.
There are also some other informations sometimes: such as the length of the track, or the track number of the album, and more…

Well, all of these infos are packed inside the mp3 into a block of bytes called “header“. When I say packed I mean that they are written in a block of bytes in which each byte must be read as binary data following pre-defined rules. The rules, for the mp3 id3 tags, are defined here in the ID3v2 site (at the chapter 3.1).

Reading binary data means that you have to understand each bit, because each bit as a meaning and the rules can say something like “the first 3 bytes identify the tag: the mp3 contains a ID3 tag if the first 3 bytes are ‘ID3’ string“. This rule is easy because you are used to watch bytes as chars as in text files, so you read the first 3 bytes and compare them to the ‘ID3’ string.

Another rule can say: “after the first 3 bytes you have a byte for the version and a byte for the revision number”. This is more complex because you cannnot use bytes as chars, since the number 3 is this octet 00000011 (an octet is a group of 8 bits), whereas the char “3” is this octet 00110011, that is the number 51.
This means that you have to use functions like bin2hex and hexdec to convert bytes into chars to understand them.

I’ve found the following function on the Giuseppe Manzavino site and I’ve modified it to fix two really small bugs and I see it works fine with ID3 tags written in some files I’ve edited with iTunes.

<?
// From here: http://www.autistici.org/ermes/index.php?pag=1&post=15
// and fixed here: https://www.barattalo.it
// ------------------------------
// example:
// print_r( tagReader ("myfile.mp3") );
// ------------------------------
function tagReader($file){
	$id3v23 = array("TIT2","TALB","TPE1","TRCK","TDRC","TLEN","USLT");
	$id3v22 = array("TT2","TAL","TP1","TRK","TYE","TLE","ULT");
	$fsize = filesize($file);
	$fd = fopen($file,"r");
	$tag = fread($fd,$fsize);
	$tmp = "";
	fclose($fd);
	if (substr($tag,0,3) == "ID3") {
		$result['FileName'] = $file;
		$result['TAG'] = substr($tag,0,3);
		$result['Version'] = hexdec(bin2hex(substr($tag,3,1))).".".hexdec(bin2hex(substr($tag,4,1)));
	}
	if($result['Version'] == "4.0" || $result['Version'] == "3.0"){
		for ($i=0;$i<count($id3v23);$i++){
			if (strpos($tag,$id3v23[$i].chr(0))!= FALSE){
				$pos = strpos($tag, $id3v23[$i].chr(0));
				$len = hexdec(bin2hex(substr($tag,($pos+5),3)));
				$data = substr($tag, $pos, 9+$len);
				for ($a=0;$a<strlen($data);$a++){
					$char = substr($data,$a,1);
					if($char >= " " && $char <= "~") $tmp.=$char;
				}
				if(substr($tmp,0,4) == "TIT2") $result['Title'] = substr($tmp,4);
				if(substr($tmp,0,4) == "TALB") $result['Album'] = substr($tmp,4);
				if(substr($tmp,0,4) == "TPE1") $result['Author'] = substr($tmp,4);
				if(substr($tmp,0,4) == "TRCK") $result['Track'] = substr($tmp,4);
				if(substr($tmp,0,4) == "TDRC") $result['Year'] = substr($tmp,4);
				if(substr($tmp,0,4) == "TLEN") $result['Lenght'] = substr($tmp,4);
				if(substr($tmp,0,4) == "USLT") $result['Lyric'] = substr($tmp,7);
				$tmp = "";
			}
		}
	}
	if($result['Version'] == "2.0"){
		for ($i=0;$i<count($id3v22);$i++){
			if (strpos($tag,$id3v22[$i].chr(0))!= FALSE){
				$pos = strpos($tag, $id3v22[$i].chr(0));
				$len = hexdec(bin2hex(substr($tag,($pos+3),3)));
				$data = substr($tag, $pos, 6+$len);
				for ($a=0;$a<strlen($data);$a++){
					$char = substr($data,$a,1);
					if($char >= " " && $char <= "~") $tmp.=$char;
				}
				if(substr($tmp,0,3) == "TT2") $result['Title'] = substr($tmp,3);
				if(substr($tmp,0,3) == "TAL") $result['Album'] = substr($tmp,3);
				if(substr($tmp,0,3) == "TP1") $result['Author'] = substr($tmp,3);
				if(substr($tmp,0,3) == "TRK") $result['Track'] = substr($tmp,3);
				if(substr($tmp,0,3) == "TYE") $result['Year'] = substr($tmp,3);
				if(substr($tmp,0,3) == "TLE") $result['Lenght'] = substr($tmp,3);
				if(substr($tmp,0,3) == "ULT") $result['Lyric'] = substr($tmp,6);
				$tmp = "";
			}
		}
	}
	return $result;
}
?>

Anyone as seen something similar for reading the EXIF informations on the JPEG files?

Author

PHP expert. Wordpress plugin and theme developer. Father, Maker, Arduino and ESP8266 enthusiast.

Comments on “Reading mp3 informations with php (id3 tags)”

7 thoughts

  1. Alan ha detto:

    Hmm… I’m getting both errors and truncated data. It’s not reading the track info correctly. Any ideas?

  2. That Guy ha detto:

    @Alan: change line 26 to this:

    $data = substr($tag, $pos, 10+$len);

    I have no idea why, but it works for me.

  3. jygiev ha detto:

    if i want to read comment tag in ID3 of a MP3, would u like to give me some help because i’m stuck in it.

    please help me every help would be a bless for me :)
    regards,

  4. James ha detto:

    I would like to include this function in the “Mootools File Manager” but you have not specified any license on the code.

    The MFM uses the MIT license, will it be acceptable to you to include this function under the MIT license.

    https://github.com/sleemanj/mootools-filemanager

  5. James ha detto:

    What if I just want to print one tag instead of all ID3 tags? Let’s say I just want to print the Artist name into html? Is that possible

  6. Dave ha detto:

    Thanks for this code sample. I am planning to use a modified version of it to index sermons uploaded to our church server. I credited your section of code.

    I found that your code doesn’t work properly with title,album,author,etc. longer than 30 characters. I found that there is an extra character appearing before strings longer than 30 characters.

    I have defined a new variable to state the first character in the substring and defined it between your lines 26 & 27:
    if($len>33){$fchar = 5;}Else{$fchar = 4;}

    On lines 31 – 36 I have changed your code
    substr($tmp,4);
    to
    substr($tmp,$fchar);

    Thanks again!

  7. Vidyranga ha detto:

    I used this.Thank you very much. But I also want to get image also. I found that the appropriate tag is “APIC”. But data doesn’t come out right. I mean it should be a string of 64base , right ? Or else ? Can you please help out

Comments are closed

Recommended

Modify the language attribute based on category in WordPress

How to modify the language attribute in your Wordpress theme using a specific value

Novembre 7, 2019

Embedding images in HTML or CSS with PHP

This small function returns an encoded string to embed images, inline, inside your html/css code and reduce the number of…

Dicembre 4, 2013

PHP function to fix collation on database fields of MySQL

This PHP function search for tables in the active db, match table’s name with the regular expression passed as first…

Febbraio 11, 2010

Sending HTML emails with attachment with PHP

This function allows you to send an HTML email with a file attachment. To do this it’s necessary to read…

Gennaio 10, 2010

Stop UTF8 problems with special characters

I’m italian and I always need to use special chars like è é à ù. The same need belongs to…

Novembre 9, 2009