
ID3 Tags Reader with PHP
Today we will work with PHP again. Today’s tutorial will tell you about how you can use PHP to obtain ID3 meta info from music files (mp3). The easiest way to save id3 info – winamp software (try to find it in old archives). 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
[sociallocker]
download in package
[/sociallocker]
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 | Dev School</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
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!