ID3 Tags Reader with PHP
Today we will work with PHP again. Today I will show you how you can use PHP to obtain ID3 meta info from music files (mp3). Most easy way to store id3 info – winamp software. So you will able to test our result script with your music files. We will extract next fields: Title, Album, Author, Discription, Genre, Publisher, OriginalArtist, URL etc.
Live Demo
download in package
Now – download the example files and lets start coding !
Step 1. HTML
As usual, we start with the HTML. This is source of demo page layout:
main_page.html
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<title>ID3 Tags Reader with PHP | Script-tutorials</title>
<link rel="stylesheet" href="css/main.css" type="text/css" media="all" />
</head>
<body>
<div class="example" id="main">
<table style="width:100%">
<thead>
<td><b>Title</b></td>
<td><b>Album</b></td>
<td><b>Author</b></td>
<td><b>AlbumAuthor</b></td>
<td><b>Track</b></td>
<td><b>Year</b></td>
<td><b>Lenght</b></td>
<td><b>Lyric</b></td>
<td><b>Desc</b></td>
<td><b>Genre</b></td>
</thead>
__list__
</table>
<hr /><h3>Extra info</h3>
<table style="width:100%">
<thead>
<td><b>Title</b></td>
<td><b>Encoded</b></td>
<td><b>Copyright</b></td>
<td><b>Publisher</b></td>
<td><b>OriginalArtist</b></td>
<td><b>URL</b></td>
<td><b>Comments</b></td>
<td><b>Composer</b></td>
</thead>
__list2__
</table>
</div>
</body>
</html>
I prepared 2 tables to display ID3 infos of each enumerated file
Step 2. CSS
Here are used CSS styles:
css/main.css
body{background-color:#ddd;margin:0;padding:0}
.example{position:relative;background-color:#fff;width:980px;height:700px;border:1px #000 solid;margin:20px auto;padding:20px;-moz-border-radius:3px;-webkit-border-radius:3px}
Step 3. PHP
Our most important part of project – PHP.
index.php
<?php
// set error reporting level
if (version_compare(phpversion(), '5.3.0', '>=') == 1)
error_reporting(E_ALL & ~E_NOTICE & ~E_DEPRECATED);
else
error_reporting(E_ALL & ~E_NOTICE);
// gathering all mp3 files in 'mp3' folder into array
$sDir = 'mp3/';
$aFiles = array();
$rDir = opendir($sDir);
if ($rDir) {
while ($sFile = readdir($rDir)) {
if ($sFile == '.' or $sFile == '..' or !is_file($sDir . $sFile))
continue;
$aPathInfo = pathinfo($sFile);
$sExt = strtolower($aPathInfo['extension']);
if ($sExt == 'mp3') {
$aFiles[] = $sDir . $sFile;
}
}
closedir( $rDir );
}
// new object of our ID3TagsReader class
$oReader = new ID3TagsReader();
// passing through located files ..
$sList = $sList2 = '';
foreach ($aFiles as $sSingleFile) {
$aTags = $oReader->getTagsInfo($sSingleFile); // obtaining ID3 tags info
$sList .= '<tr><td>'.$aTags['Title'].'</td><td>'.$aTags['Album'].'</td><td>'.$aTags['Author'].'</td>
<td>'.$aTags['AlbumAuthor'].'</td><td>'.$aTags['Track'].'</td><td>'.$aTags['Year'].'</td>
<td>'.$aTags['Lenght'].'</td><td>'.$aTags['Lyric'].'</td><td>'.$aTags['Desc'].'</td>
<td>'.$aTags['Genre'].'</td></tr>';
$sList2 .= '<tr><td>'.$aTags['Title'].'</td><td>'.$aTags['Encoded'].'</td><td>'.$aTags['Copyright'].'</td>
<td>'.$aTags['Publisher'].'</td><td>'.$aTags['OriginalArtist'].'</td><td>'.$aTags['URL'].'</td>
<td>'.$aTags['Comments'].'</td><td>'.$aTags['Composer'].'</td></tr>';
}
// main output
echo strtr(file_get_contents('main_page.html'), array('__list__' => $sList, '__list2__' => $sList2));
// class ID3TagsReader
class ID3TagsReader {
// variables
var $aTV23 = array( // array of possible sys tags (for last version of ID3)
'TIT2',
'TALB',
'TPE1',
'TPE2',
'TRCK',
'TYER',
'TLEN',
'USLT',
'TPOS',
'TCON',
'TENC',
'TCOP',
'TPUB',
'TOPE',
'WXXX',
'COMM',
'TCOM'
);
var $aTV23t = array( // array of titles for sys tags
'Title',
'Album',
'Author',
'AlbumAuthor',
'Track',
'Year',
'Lenght',
'Lyric',
'Desc',
'Genre',
'Encoded',
'Copyright',
'Publisher',
'OriginalArtist',
'URL',
'Comments',
'Composer'
);
var $aTV22 = array( // array of possible sys tags (for old version of ID3)
'TT2',
'TAL',
'TP1',
'TRK',
'TYE',
'TLE',
'ULT'
);
var $aTV22t = array( // array of titles for sys tags
'Title',
'Album',
'Author',
'Track',
'Year',
'Lenght',
'Lyric'
);
// constructor
function ID3TagsReader() {}
// functions
function getTagsInfo($sFilepath) {
// read source file
$iFSize = filesize($sFilepath);
$vFD = fopen($sFilepath,'r');
$sSrc = fread($vFD,$iFSize);
fclose($vFD);
// obtain base info
if (substr($sSrc,0,3) == 'ID3') {
$aInfo['FileName'] = $sFilepath;
$aInfo['Version'] = hexdec(bin2hex(substr($sSrc,3,1))).'.'.hexdec(bin2hex(substr($sSrc,4,1)));
}
// passing through possible tags of idv2 (v3 and v4)
if ($aInfo['Version'] == '4.0' || $aInfo['Version'] == '3.0') {
for ($i = 0; $i < count($this->aTV23); $i++) {
if (strpos($sSrc, $this->aTV23[$i].chr(0)) != FALSE) {
$s = '';
$iPos = strpos($sSrc, $this->aTV23[$i].chr(0));
$iLen = hexdec(bin2hex(substr($sSrc,($iPos + 5),3)));
$data = substr($sSrc, $iPos, 9 + $iLen);
for ($a = 0; $a < strlen($data); $a++) {
$char = substr($data, $a, 1);
if ($char >= ' ' && $char <= '~')
$s .= $char;
}
if (substr($s, 0, 4) == $this->aTV23[$i]) {
$iSL = 4;
if ($this->aTV23[$i] == 'USLT') {
$iSL = 7;
} elseif ($this->aTV23[$i] == 'TALB') {
$iSL = 5;
} elseif ($this->aTV23[$i] == 'TENC') {
$iSL = 6;
}
$aInfo[$this->aTV23t[$i]] = substr($s, $iSL);
}
}
}
}
// passing through possible tags of idv2 (v2)
if($aInfo['Version'] == '2.0') {
for ($i = 0; $i < count($this->aTV22); $i++) {
if (strpos($sSrc, $this->aTV22[$i].chr(0)) != FALSE) {
$s = '';
$iPos = strpos($sSrc, $this->aTV22[$i].chr(0));
$iLen = hexdec(bin2hex(substr($sSrc,($iPos + 3),3)));
$data = substr($sSrc, $iPos, 6 + $iLen);
for ($a = 0; $a < strlen($data); $a++) {
$char = substr($data, $a, 1);
if ($char >= ' ' && $char <= '~')
$s .= $char;
}
if (substr($s, 0, 3) == $this->aTV22[$i]) {
$iSL = 3;
if ($this->aTV22[$i] == 'ULT') {
$iSL = 6;
}
$aInfo[$this->aTV22t[$i]] = substr($s, $iSL);
}
}
}
}
return $aInfo;
}
}
?>
After put your mp3 files near these code files thats all. Yes, there are a lot of code, but everything is close. Commonly – you can check code in beginning (before defining of class), and class itself. First half is very easy – passing through files of folder, and generating output. So about class itself (ID3TagsReader) – this is more difficult. We will read hex code of each MP3 file and looking for inner information (ID3). I will try to pick all ID3 tags which can be available in Winamp (mp3 player). But I can say that the total of all possible tags is much more.
Live Demo
download in archive
Conclusion
I hope today’s article was very interesting for you. This material can be of great interest for projects that work with the music. This will help you get a variety of information from music files without including another large libraries. Good luck in your work!


Hello there, while trying to implement your ID3CLASSREADER class I came upon some things I wanted to share with you so that you can maybe help me out. So first thing I love using ezsql when working with php + sql, however it seems that your class turns ezsql useless lol which is nothing really serious but just so you know. The second thing I came across is the fact that a lot of mp3′s get they’re titles or albums chopped up by exactly one letter at the end, or at the begining, and sometimes both! Also some characters like “(” or “/” appear sometimes in the titles, artists or album titles. I was trying to use your class to get all the id3 of 1000 mp3′s inside a folder while retrieving them to a sql database. Just by “echo”ing it all I came up with those small bugs.
I’ve been using other scripts but none was able to read as much id3 as yours, without those small bugs it would render this script perfect for me.
Could you help me out?
John More
Hello John,
Yes, I know, I noticed this too, but did not had much time to investigate it and fix. Possible I will do it in next time when will back to work with MP3 files and its tags
Hi,
Can it read Id3 info from link?
Eg. http://www.djpreet.net/dj/songs/Hindi/Movie album/B/Breathing Under Water (hindi-Ost) ( Feb 2k8)/Breathing Under Water – 04 – Sea Dreamer.mp3
??
Thank u..
yoyr script is working correctly.
but i also want to fetch the thumbnail of that mp3 file..
can u help me in this…?
can u tell me how can i read all this information for an video file as well…?
Hello Shubham,
Yes, possible. But which video file format you like to investigate?
Hello sam,
Why now? .. But in this case you need to accept (download) this file locally to work with this file