|
|
|||||||||||||||||||||||||||||
|
Чтение ID3 тегов и другой информации из mp3 файлов средствами phpВсе ID3 теги (ID3 tag) хранятся в последних 128-ми байтах mp3 файла. Это означает, что их можно читать без специальных компонентов. Распределение информации следующее:
Для определения тегов достаточно отформатировать распаковку из бинарной строки в соответствии с выше приведенной последовательностью: 01$f = fopen('test.mp3', 'rb');02rewind($f);03fseek($f, -128, SEEK_END);04$tmp = fread($f,128);05if ($tmp[125] == Chr(0) and $tmp[126] != Chr(0)) {06// ID3 v1.107$format = 'a3TAG/a30NAME/a30ARTISTS/a30ALBUM/a4YEAR/a28COMMENT/x1/C1TRACK/C1GENRENO';08} else {09// ID3 v110$format = 'a3TAG/a30NAME/a30ARTISTS/a30ALBUM/a4YEAR/a30COMMENT/C1GENRENO';11}12 13$id3tag = unpack($format, $tmp);Результат работы скрипта: Иногда бывает необходимо кроме ID3 tag 'ов узнать и другую инфу об mp3 файле (частоту, bitrate, длительность и др.), я взял за основу библиотекуhttp://pear.php.net/package/MP3_ID и написал следующую функцию, которая позволяет это сделать. Я не буду ее комментировать, потому что здесь мало программирования, а в основном знание структуры mp3 файла, кто захочет - разберется. 001function readframe($file) {002if (! ($f = fopen($file, 'rb')) ) die("Unable to open " . $file);003$res['filesize'] = filesize($file);004do {005while (fread($f,1) != Chr(255)) { // Find the first frame 006if (feof($f)) die( "No mpeg frame found") ;007}008fseek($f, ftell($f) - 1); // back up one byte009 010$frameoffset = ftell($f);011 012$r = fread($f, 4);013 014$bits = sprintf("%'08b%'08b%'08b%'08b", ord($r{0}), ord($r{1}), ord($r{2}), ord($r{3}));015}016while (!$bits[8] and !$bits[9] and !$bits[10]); // 1st 8 bits true from the while 017 018// Detect VBR header019if ($bits[11] == 0) {020if (($bits[24] == 1) && ($bits[25] == 1)) {021$vbroffset = 9; // MPEG 2.5 Mono022} else {023$vbroffset = 17; // MPEG 2.5 Stereo024}025} else if ($bits[12] == 0) {026if (($bits[24] == 1) && ($bits[25] == 1)) {027$vbroffset = 9; // MPEG 2 Mono028} else {029$vbroffset = 17; // MPEG 2 Stereo030}031} else {032if (($bits[24] == 1) && ($bits[25] == 1)) {033$vbroffset = 17; // MPEG 1 Mono034} else {035$vbroffset = 32; // MPEG 1 Stereo036}037}038 039fseek($f, ftell($f) + $vbroffset);040$r = fread($f, 4);041 042switch ($r) {043case 'Xing':044$res['encoding_type'] = 'VBR';045case 'VBRI':046default:047if ($vbroffset != 32) {048// VBRI Header is fixed after 32 bytes, so maybe we are looking at the wrong place.049fseek($f, ftell($f) + 32 - $vbroffset);050$r = fread($f, 4);051 052if ($r != 'VBRI') {053$res['encoding_type'] = 'CBR';054break;055}056} else {057$res['encoding_type'] = 'CBR';058break;059}060 061$res['encoding_type'] = 'VBR';062}063 064fclose($f);065 066if ($bits[11] == 0) {067$res['mpeg_ver'] = "2.5";068$bitrates = array(069'1' => array(0, 32, 48, 56, 64, 80, 96, 112, 128, 144, 160, 176, 192, 224, 256, 0),070'2' => array(0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160, 0),071'3' => array(0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160, 0),072);073} else if ($bits[12] == 0) {074$res['mpeg_ver'] = "2";075$bitrates = array(076'1' => array(0, 32, 48, 56, 64, 80, 96, 112, 128, 144, 160, 176, 192, 224, 256, 0),077'2' => array(0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160, 0),078'3' => array(0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160, 0),079);080} else {081$res['mpeg_ver'] = "1";082$bitrates = array(083'1' => array(0, 32, 64, 96, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, 448, 0),084'2' => array(0, 32, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 384, 0),085'3' => array(0, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 0),086);087}088 089$layer = array(090array(0,3),091array(2,1),092);093$res['layer'] = $layer[$bits[13]][$bits[14]];094 095if ($bits[15] == 0) {096// It's backwards, if the bit is not set then it is protected.097$res['crc'] = true;098}099 100$bitrate = 0;101if ($bits[16] == 1) $bitrate += 8;102if ($bits[17] == 1) $bitrate += 4;103if ($bits[18] == 1) $bitrate += 2;104if ($bits[19] == 1) $bitrate += 1;105$res['bitrate'] = $bitrates[$res['layer']][$bitrate];106 107$frequency = array(108'1' => array(109'0' => array(44100, 48000),110'1' => array(32000, 0),111),112'2' => array(113'0' => array(22050, 24000),114'1' => array(16000, 0),115),116'2.5' => array(117'0' => array(11025, 12000),118'1' => array(8000, 0),119),120);121$res['frequency'] = $frequency[$res['mpeg_ver']][$bits[20]][$bits[21]];122 123$mode = array(124array('Stereo', 'Joint Stereo'),125array('Dual Channel', 'Mono'),126);127$res['mode'] = $mode[$bits[24]][$bits[25]];128 129$samplesperframe = array(130'1' => array(131'1' => 384,132'2' => 1152,133'3' => 1152134),135'2' => array(136'1' => 384,137'2' => 1152,138'3' => 576139),140'2.5' => array(141'1' => 384,142'2' => 1152,143'3' => 576144),145);146$res['samples_per_frame'] = $samplesperframe[$res['mpeg_ver']][$res['layer']];147 148if ($res['encoding_type'] != 'VBR') {149if ($res['bitrate'] == 0) {150$s = -1;151} else {152$s = ((8*filesize($file))/1000) / $res['bitrate'];153}154$res['length'] = sprintf('%02d:%02d',floor($s/60),floor($s-(floor($s/60)*60)));155$res['lengthh'] = sprintf('%02d:%02d:%02d',floor($s/3600),floor($s/60),floor($s-(floor($s/60)*60)));156$res['lengths'] = (int)$s;157 158$res['samples'] = ceil($res['lengths'] * $res['frequency']);159if(0 != $res['samples_per_frame']) {160$res['frames'] = ceil($res['samples'] / $res['samples_per_frame']);161} else {162$res['frames'] = 0;163}164$res['musicsize'] = ceil($res['lengths'] * $res['bitrate'] * 1000 / 8);165} else {166$res['samples'] = $res['samples_per_frame'] * $res['frames'];167$s = $res['samples'] / $res['frequency'];168 169$res['length'] = sprintf('%02d:%02d',floor($s/60),floor($s-(floor($s/60)*60)));170$res['lengthh'] = sprintf('%02d:%02d:%02d',floor($s/3600),floor($s/60),floor($s-(floor($s/60)*60)));171$res['lengths'] = (int)$s;172 173$res['bitrate'] = (int)(($res['musicsize'] / $s) * 8 / 1000);174}175 176return $res;177}Результат работы скрипта:
|
|
|||||||