Откуда mp3 плеер знает информацию об исполнителе или названии проигрываемого трека? В этом нет никаких чудес! Эта информация хранится в файлах. Музыкальные файлы других форматов, таких как WMA или Ogg Vorbis, также содержат эту информацию, но в этой статье мы поговорим о формате mp3.
Спецификация mp3 определяет способ хранения музыкальных данных, но не предусматривает возможности сохранения метаданных трека, например названия или имени исполнителя. Чтобы миновать эти ограничения, был создан стандарт ID3. Согласно этой спецификации, метаданные должны быть помещены в ID3-теги. ID3-теги первой версии (ID3v1-Tags) имеют простую конструкцию и пишутся в конце файла. Их размер не должен превышать 128 байтов. Структура тегов следующая: за строковым значением «TAG» должна следовать информация о названии (30 символов), исполнителе (30 символов), альбоме (30 символов), годе выпуска (четырехзначное число), а также комментарий (30 символов) и жанр (1 байт). Тэг с такой структурой выглядит так: ID3v1.0-Tag. Существует еще один формат - ID3v1.1-Tag. Он позволяет хранить информацию о порядковом номере трека.
Для считывания информации с ID3v1-тегов в библиотеку PEAR уже включили пакет MP3_Id[3]. Это позволят извлекать информацию из тега и записывать ее. Листинг 1 показывает, как считывать информацию с тегов. При этом создается объект класса MP3_ID, далее происходит считывание файла, после чего методом getTag() производится извлечение информации. Результаты показаны в Листинге 2.
Листинг 1
<?php require_once "MP3/Id.php"; // Создаём объект и читаем файл $id3 = &new MP3_Id(); $result = $id3->read("../data/Little-Big-Man.mp3"); if (PEAR::isError($result)) { } // Читаем поля и выволдим информацию echo "Имя: " . $id3->getTag("name") . "\n"; echo "Исполнитель: " . $id3->getTag("artists") . "\n"; echo "Альбом: " . $id3->getTag("album") . "\n"; echo "Год: " . $id3->getTag("year") . "\n"; echo "Комментарий: " . $id3->getTag("comment") . "\n"; echo "Жанр: " . $id3->getTag("genre") . "\n"; echo "Жанр (номер): " . $id3->getTag("genreno") . "\n"; echo "Трэк: " . $id3->getTag("track") . "\n"; ?>
Листинг 1
Имя: Little Big Man Исполнитель: Dirty Mac Альбом: Demo-Tape Год: 2001 Комментарий: Song from the Demo-Tape album Жанр: Rock Жанр (номер): 17 Трэк: 5
Листинг 3 показывает, как можно менять содержимое ID3-тегов, а также создавать их. Сначала создается объект класса MP3_ID (так же, как в Листинге 1), затем происходит считывание файла, а после, посредством использования метода setTag($fieldname, $value), в тег помещается нужная информация. Если вы хотите удалить все теги, ознакомьтесь с Листингом 4. Для удаления тегов используйте метод remove().
Листинг 3Листинг 4
<?php require_once 'MP3/Id.php'; // создаем объект, читаем данные $id3 = &new MP3_Id(); $result = $id3->read('../data/Little-Big-Man.mp3'); // Ошибка "Tag not found" игнорируется if (PEAR::isError($result) && $result->getCode() !== PEAR_MP3_ID_TNF) { } // Определяем информацию $id3->setTag('name', 'Neuer Titel'); $id3->setTag('artists', 'Andere Band'); $id3->setTag('album', 'Schlagertraum #3'); $id3->setTag('year', 1984); $id3->setTag('comment', 'Volksmusikal. Hochgenuss'); $id3->setTag('genre', 'Folk'); $id3->setTag('track', 5); // Записываем информацию в тег $result = $id3->write(); if (PEAR::isError($result)) { } echo "Тег успешно записан!\n"; ?>
<?php require_once 'MP3/Id.php'; // Создаем объект, читаем файл $id3 = &new MP3_Id(); $err = $id3->read('../data/Little-Big-Man.mp3'); if (PEAR::isError($err)) { } // Удаляем тег $result = $id3->remove(); if (PEAR::isError($result)) { } echo "Тег успешно стерт!\n"; ?>
Использование PECL
В 2004 году появилось новое PHP расширение - ext/id3[7]. В отличие от MP3_ID эта библиотека написана на языке С, а не PHP, поэтому она должна работать быстрее. Для того чтобы использовать это расширение, следует воспользоваться PEAR-installer или компилировать PHP, включив поддержку этого расширения. Эта библиотека позволяет изменять содержимое ID3-тегов. Для этого вам потребуется всего лишь массив, как в Листинге 6, а также функция id3_set_tag(). Первым параметром данной функции является название mp3 файла. Второй параметр – массив с необходимой информацией. Третий параметр – необязательный. Он представляет собой константу, показывающую версию ID3-тега. В настоящей версии библиотеки функция id3_set_tag() работает только с тегами версии 1.0 и 1.1. В Листинге 7 содержится необходимый код php. В дополнение к этому Листинг 8 показывает, как удалить настоящий тег, используя функцию id3_remove_tag.
Листинг 5Листинг 6
<?php // имя файла на локальном диске // имя файла в виде URL // Внимание! Или вы подключаетесь к DSL, или ждете ;-) // идентификатор ресурса вместо имени файла ?>
Array ( [title] => Little Big Man [artist] => Dirty Mac [album] => Demo-Tape [year] => 2001 [comment] => Song vom Demo-Tape [track] => 5 [genre] => 17 )
Листинг 7
<?php 'title' => 'Новое название', 'artist' => 'Другая группа', 'album' => 'Schlagertraum #3', 'year' => 1984, 'comment' => 'Отличная популярная мелодия', 'track' => 5 ); // Записываем тег if ($result === false) { echo "Тег не был успешно записан!\n"; } echo "Тег успешно записан!\n"; ?>
Новое поколение
Несмотря на то, что использование ID3-тегов позволяет сохранять важную информацию о содержимом mp3 файлов, существует несколько ограничений для версий 1.0 и 1.1:
в связи с фиксированным размером тега ограничен размер сохраняемой информации;
ограничено количество сохраняемых атрибутов.
Для того чтобы устранить эти ограничения, были созданы ID3-теги версии 2[2] - ID3v2. Теги ID3v2 записываются в начале файла. Они могут содержать больше информации, чем ID3v1-теги. Такой информацией может быть информация об авторских правах, BMP или тексте песен. Новые возможности тегов ID3v2 значительно усложнили процесс считывания информации. При исполнении кода из Листинга 9 получится результат, указанный в Листинге 10.
Каждый фрейм ID3v2-тега обладает уникальным ID. Ext/id3 имеет две функции, которые позволяют узнавать содержимое фрейма. Это id3_get_frame_short() и id3_get_frame_long_name(). В качестве параметра они принимают id фрейма и возвращают его описание.
Листинг 8Листинг 9
<?php // удаляет тег if ($result === false) { echo "Тег не удален!\n"; } echo "Тег успешно удален!\n"; ?>
<?php //Читаем ID3v2 тег ?>
Дополнительная информация
Использование библиотеки MP3_Id позволяет не только считывать информацию ID3-тегов, но также получать интересную информацию о самом mp3 файле. Получение данной информации возможно при использовании метода study(), а после, используя метод getTag(), вы можете выбирать необходимую информацию. Листинг 12 показывает, как это работает. Результаты показаны в Листинге 13.
Листинг 10Array ( [copyright] => Dirty Mac [originalArtist] => Dirty Mac [composer] => Marcus Goetze [artist] => Dirty Mac [title] => Little Big Man [album] => Demo-Tape [track] => 5/12 [genre] => (17)Rock [year] => 2001 )
Листинг 11
<?php // Id ID3v2-Frames $frame = "TOLY"; echo "Frame: $frame\n"; echo "Kurzform: $short\n"; echo "Beschreibung: $descr\n"; ?>
Листинг 12
<?php require_once "MP3/Id.php"; // создаем объект, считываем данные $id3 = &new MP3_Id(); $result = $id3->read("../data/Little-Big-Man.mp3"); // Ошибки типа "Тег не найден" игнорируются if (PEAR::isError($result) && $result->getCode() !== PEAR_MP3_ID_TNF) { } $result = $id3->study(); if (PEAR::isError($result)) { } echo "MPEG " . $id3->getTag("mpeg_ver") . " Layer " . $id3->getTag("layer") . "\n"; echo $id3->getTag("mode"). "\n"; echo "Размер файла: " . $id3->getTag("filesize") . " Bytes\n"; echo "Качество: " . $id3->getTag("bitrate") . "kB/s n"; echo "Продолжительность: " . $id3->getTag("length") . " min\n"; echo "Частота оцифровки: " . $id3->getTag("frequency") . "Hz\n"; ?>
Листинг 13
MPEG 1 Layer 3 Joint Stereo Размер: 4089856 Bytes Качество: 128kB/s Продолжительность: 04:15 min Частота оцифровки: 44100Hz