чтение ID3 тегов и другой информации из mp3 файлов средствами phpВсе ID3 теги (ID3 tag) хранятся в последних 128-ми байтах mp3 файла. Это означает, что их можно читать без специальных компонентов. Распределение информации следующее:
Byte 1-3 = ID 'TAG' Для определения тегов достаточно отформатировать распаковку из бинарной строки в соответствии с выше приведенной последовательностью:
$f = fopen('test.mp3', 'rb');
rewind($f);
fseek($f, -128, SEEK_END);
$tmp = fread($f,128);
if ($tmp[125] == Chr(0) and $tmp[126] != Chr(0)) {
// ID3 v1.1
$format = 'a3TAG/a30NAME/a30ARTISTS/a30ALBUM/a4YEAR/a28COMMENT/x1/C1TRACK/C1GENRENO';
} else {
// ID3 v1
$format = 'a3TAG/a30NAME/a30ARTISTS/a30ALBUM/a4YEAR/a30COMMENT/C1GENRENO';
}
$id3tag = unpack($format, $tmp);
Результат работы скрипта:Array ( [TAG] => TAG [NAME] => test [ARTISTS] => oz [ALBUM] => [YEAR] => 2007 [COMMENT] => [GENRENO] => 0 )
Иногда бывает необходимо кроме ID3 tag 'ов узнать и другую инфу об mp3 файле (частоту, bitrate, длительность и др.), я взял за основу библиотеку http://pear.php.net/package/MP3_ID и написал следующую функцию, которая позволяет это сделать. Я не буду ее комментировать, потому что здесь мало программирования, а в основном знание структуры mp3 файла, кто захочет - разберется.
function readframe($file) {
if (! ($f = fopen($file, 'rb')) ) die("Unable to open " . $file);
$res['filesize'] = filesize($file);
do {
while (fread($f,1) != Chr(255)) { // Find the first frame
if (feof($f)) die( "No mpeg frame found") ;
}
fseek($f, ftell($f) - 1); // back up one byte
$frameoffset = ftell($f);
$r = fread($f, 4);
$bits = sprintf("%'08b%'08b%'08b%'08b", ord($r{0}), ord($r{1}), ord($r{2}), ord($r{3}));
}
while (!$bits[8] and !$bits[9] and !$bits[10]); // 1st 8 bits true from the while
// Detect VBR header
if ($bits[11] == 0) {
if (($bits[24] == 1) && ($bits[25] == 1)) {
$vbroffset = 9; // MPEG 2.5 Mono
} else {
$vbroffset = 17; // MPEG 2.5 Stereo
}
} else if ($bits[12] == 0) {
if (($bits[24] == 1) && ($bits[25] == 1)) {
$vbroffset = 9; // MPEG 2 Mono
} else {
$vbroffset = 17; // MPEG 2 Stereo
}
} else {
if (($bits[24] == 1) && ($bits[25] == 1)) {
$vbroffset = 17; // MPEG 1 Mono
} else {
$vbroffset = 32; // MPEG 1 Stereo
}
}
fseek($f, ftell($f) + $vbroffset);
$r = fread($f, 4);
switch ($r) {
case 'Xing':
$res['encoding_type'] = 'VBR';
case 'VBRI':
default:
if ($vbroffset != 32) {
// VBRI Header is fixed after 32 bytes, so maybe we are looking at the wrong place.
fseek($f, ftell($f) + 32 - $vbroffset);
$r = fread($f, 4);
if ($r != 'VBRI') {
$res['encoding_type'] = 'CBR';
break;
}
} else {
$res['encoding_type'] = 'CBR';
break;
}
$res['encoding_type'] = 'VBR';
}
fclose($f);
if ($bits[11] == 0) {
$res['mpeg_ver'] = "2.5";
$bitrates = array(
'1' => array(0, 32, 48, 56, 64, 80, 96, 112, 128, 144, 160, 176, 192, 224, 256, 0),
'2' => array(0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160, 0),
'3' => array(0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160, 0),
);
} else if ($bits[12] == 0) {
$res['mpeg_ver'] = "2";
$bitrates = array(
'1' => array(0, 32, 48, 56, 64, 80, 96, 112, 128, 144, 160, 176, 192, 224, 256, 0),
'2' => array(0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160, 0),
'3' => array(0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160, 0),
);
} else {
$res['mpeg_ver'] = "1";
$bitrates = array(
'1' => array(0, 32, 64, 96, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, 448, 0),
'2' => array(0, 32, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 384, 0),
'3' => array(0, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 0),
);
}
$layer = array(
array(0,3),
array(2,1),
);
$res['layer'] = $layer[$bits[13]][$bits[14]];
if ($bits[15] == 0) {
// It's backwards, if the bit is not set then it is protected.
$res['crc'] = true;
}
$bitrate = 0;
if ($bits[16] == 1) $bitrate += 8;
if ($bits[17] == 1) $bitrate += 4;
if ($bits[18] == 1) $bitrate += 2;
if ($bits[19] == 1) $bitrate += 1;
$res['bitrate'] = $bitrates[$res['layer']][$bitrate];
$frequency = array(
'1' => array(
'0' => array(44100, 48000),
'1' => array(32000, 0),
),
'2' => array(
'0' => array(22050, 24000),
'1' => array(16000, 0),
),
'2.5' => array(
'0' => array(11025, 12000),
'1' => array(8000, 0),
),
);
$res['frequency'] = $frequency[$res['mpeg_ver']][$bits[20]][$bits[21]];
$mode = array(
array('Stereo', 'Joint Stereo'),
array('Dual Channel', 'Mono'),
);
$res['mode'] = $mode[$bits[24]][$bits[25]];
$samplesperframe = array(
'1' => array(
'1' => 384,
'2' => 1152,
'3' => 1152
),
'2' => array(
'1' => 384,
'2' => 1152,
'3' => 576
),
'2.5' => array(
'1' => 384,
'2' => 1152,
'3' => 576
),
);
$res['samples_per_frame'] = $samplesperframe[$res['mpeg_ver']][$res['layer']];
if ($res['encoding_type'] != 'VBR') {
if ($res['bitrate'] == 0) {
$s = -1;
} else {
$s = ((8*filesize($file))/1000) / $res['bitrate'];
}
$res['length'] = sprintf('%02d:%02d',floor($s/60),floor($s-(floor($s/60)*60)));
$res['lengthh'] = sprintf('%02d:%02d:%02d',floor($s/3600),floor($s/60),floor($s-(floor($s/60)*60)));
$res['lengths'] = (int)$s;
$res['samples'] = ceil($res['lengths'] * $res['frequency']);
if(0 != $res['samples_per_frame']) {
$res['frames'] = ceil($res['samples'] / $res['samples_per_frame']);
} else {
$res['frames'] = 0;
}
$res['musicsize'] = ceil($res['lengths'] * $res['bitrate'] * 1000 / 8);
} else {
$res['samples'] = $res['samples_per_frame'] * $res['frames'];
$s = $res['samples'] / $res['frequency'];
$res['length'] = sprintf('%02d:%02d',floor($s/60),floor($s-(floor($s/60)*60)));
$res['lengthh'] = sprintf('%02d:%02d:%02d',floor($s/3600),floor($s/60),floor($s-(floor($s/60)*60)));
$res['lengths'] = (int)$s;
$res['bitrate'] = (int)(($res['musicsize'] / $s) * 8 / 1000);
}
return $res;
}
Результат работы скрипта:
Комментарии:Hermes 25.03.08 в 11:35 Большое спасибо! очень интересно , коротко и главное всё по делу! Dok 22.04.08 в 11:44 Автор молоток! Спасибо! melok 11.11.08 14:49 Cтатья отличная, потому прошу разрешить ее размещения в разделе \"Библиотека->программирование->PHP\" на моем сайте http://melok.com.ua/ Baxa 15.12.08 04:38 Причем тут ссылка на объект? 46 строка: $this->encoding_type = \'VBR\'; Alek Veritov 17.12.08 11:00 да, ссылка не причем, исправил Alex 24.03.09 15:54 Огромный респект, сотит конечно учесть, что в файле может и не быть тегов , а инфу по длительности все таки можно вытащить ... хотя легко доделывается Darkhan 12.02.10 12:52 Все сделано хорошо, удобно, но он у меня выводит неправильную длину песни и битрейт. Когда длина 3:50 и битрейт 256, он выводит 07:42 и 128 kbit Stas 07.05.10 20:58 Спасибо, Автору. Коротко и понятно. Только у меня почему-то длительность не правильно выводит. Из трех файлов только у одного вывел реальную длительность. У второго так вообще отрицательная получилась. Из-за чего может быть? tolikman 23.06.10 16:03 Всем здравствуйте! Очень интересная статья - коротко, ясно и полезно! Тока научиться бы читать еще ID3v2.x теги. Мне очень помогла! НО! Я кажется нашел ошибку во втором листинге! Zorg 16.07.10 15:21 Вы кудесник и как я вижу тоже любите простоту и лаконичность. Великий респект за ресурс. олександр 27.05.11 18:38 У меня сайт на дле, можете подсказать куда этот скрипт ставить надо? waip 21.06.11 10:02 олександр: смотря что вы хотите с ним сделать. мое мнение что вам лучше свой двиг написать и походу поймете что и куда нужно вписывать. waip 21.06.11 10:03 Сори за флуд автору спосяб. =) Darkhan 06.10.11 23:12 Почему никто не говорит про ошибки функции? Айдин 17.01.12 09:19 КрасавчиК!!! Как раз столкнулся с такой проблемой! Айдин 26.01.12 06:46 В некоторых случаях не правильно определяет продолжительность, битрейт. -00:00:01 или в 2,3,4 раза больше чем истинная продолжительность mp3-шки Андрей Шеляков 30.04.12 14:38 Автору реальный респект=) Андрей Шеляков 30.04.12 14:54 Ещёб статью о том как записать значение тега bifurcator 07.05.12 09:36 В целом работает, но в некоторых случаях выдает отрицательные значения продолжительности. Если вам помогла или просто понравилась эта статья вы можете отблагодарить автора кликнув по рекламе. Спасибо! комментировать:
прежде чем писать комментарий убедитесь, пожалуйста, что он не попадает в нижеследующие категории:
прямые оскорбления кого бы то ни было будут удалятся! от кого: |


