Однажды мне понадобилось решить простенькую (как мне тогда казалось) задачу – в PHP-скрипте узнать длительность mp3-файла. Я слышал о ID3 тегах и сразу подумал, что информация о длительности хранится либо в тегах, либо в заголовках mp3-файла. Поверхностные поиски в интернете показали что за пару-тройку минут решить эту задачу не получится. Поскольку от природы я довольно любопытен а время не поджимало — решил не использовать сторонние инструменты а разобраться в одном из самых популярных форматов самостоятельно.
Если Вам интересно, что там внутри – добро пожаловать под кат (трафик).
В данной статье мы не будем подробно останавливаться на извлечении ID3v2 тегов – это можно вынести в отдельную статью, так как там есть различные нюансы. А так же на фрагментах заголовков, которые практически не используются в настоящее время (например, часть Emphasis заголовка mp3-фрейма). Так же мы не рассматриваем структуру самих аудиоданных — тех самых, которые слышим из колонок.
ID3 теги
ID3 (от англ. Identify a MP3) — формат метаданных, наиболее часто используемый в звуковых файлах в формате MP3. ID3 подпись содержит данные о названии трека, альбома, имени исполнителя и т. д., которые используются мультимедиапроигрывателями и другими программами, а также аппаратными проигрывателями, для отображения информации о файле и автоматического упорядочивания аудиоколлекции.
Wikipedia
Существует две абсолютно разных версии ID3-данных: ID3v1 и ID3v2.
ID3v1 – имеет фиксированный размер в 128 байт, которые дописываются в конец mp3-файла. Там можно хранить: название трека, исполнитель, альбом, год, комментарий, номер трека (для версии 1.1) и жанр.
Довольно быстро всем стало понятно, что 128 байт – очень уж небольшое место для хранения таких данных. И поэтому, со временем, появилась и успешно используется вторая версия данных – ID3v2.
В отличии от первой версии, теги v2 имеют переменную длину и размещаются в начале файла, что позволяет поддерживать потоковое воспроизведение. (Формат ID3v2.4 позволяет так же хранить данные и в конце файла).
Данные ID3v2 состоят из заголовка и последующих фреймов ID3v2. Например, в версии ID3v2.3 существует более 70 типов фреймов.
- маркер всегда равен ‘ID3’
- В данный момент имеются три версии ID3v2.2, ID3v2.3 и ID3v2.4
Версия v2.2 считается устаревшей.
v2.3 – самая популярная версия.
v2.4 – набирает популярность. Одно из отличий от v2.3 в том, что позволяет использовать кодировку UTF-8 (а не только UTF-16) - Флаги. В настоящее время используются только три (5,6,7) бита:
bin: %abc00000
a ‘unsynchronisation’ – используется только с MPEG-2 и MPEG-2.5 форматами.
b ‘Extended header’ – указывает на наличие расширенного заголовка
с ‘Experimental indicator’ – эксперементальный индикатор - Длина. Особенность указания длины данных ID3v2 в том, что в каждом байте 7-й бит не используется и всегда установлен в 0.
Рассмотрим пример:
В данном случае вместе с заголовком ID3v2 (10 байт) – данные ID3v2 занимают 1024 байта.
После ID3v2-заголовка идут собственно теги. Подробный разбор чтения тегов ID3v2, как сказано выше, я решил не включать в эту статью.
Теперь у нас есть информация о наличии и длине тегов ID3 и мы можем приступать в разбору mp3-фрейма и понять-таки – где же хранится длительность. А заодно понять и всё остальное.
MP3-фрейм
Весь mp3-файл состоит из фреймов, которые можно извлекать только последовательно. Фрейм содержит в себе заголовок и аудио-данные. Поскольку мы не ставим себе целью написать прошивку для магнитофона – нас интересует именно заголовок фрейма.
О нем подробнее (куча таблиц и сухой информации)
Размер заголовка – 4 байта.
Описание:
- [0-10] Маркер – 11 бит, заполненные единицами (Frame sync)
- [11-12] Индекс версии MPEG (Audio version ID)
- [13-14] Индекс версии Layer (Layer index)
Кстати, MP3 – это MPEG-1 Layer III - [15] Бит защиты (Protection bit)
1 – нет защиты
0 – заголовок защищен 16-бит. CRC (следует за заголовком) - [16-19] Индекс битрейта (Bitrate index)
В таблице хранятся значения битрейта в килобит/сек. Однако в данном формате подразумевается, что 1 килобит = 1000 бит, а не 1024. Таким образом 96 Кбит/сек = 96000 бит/сек. - [20-21] Индекс частоты дискретизации (Sampling rate index)
- [22] Бит смещения (Padding bit)
Если он установлен, то данные смещаются на 1 байт. Это важно для расчета размера фрейма. - [23] Бит private (только для информации)
- [24-25] Режим канала (Channel mode)
- [26-27] Расширение режима канала. (Mode extension) Используется только с Joint stereo
- [28] Копирайт (Copyright bit) – только для информации
- [29] Оригинал (Original bit) – только для информации.
- [30-31] Акцент (Emphasis) – в данный момент практически не используется.
Режимы сжатия данных или какой бывает битрейт
Существует 3 режима сжатия данных:
CBR (constant bitrate) – постоянный битрейт. Не меняется на всем протяжении трека.
VBR (variable bitrate) – переменный битрейт. При этом сжатии битрейт постоянно меняется на протяжении трека.
ABR (average bitrate) – усредненный битрейт. Это понятие используется только при кодировании файла. На «выходе» получается файл с VBR.
CBR
Если файл закодирован с постоянным битрейтом – то мы уже можем
Длительность = Размер аудиоданных / Битрейт (в битах!) * 8
Например, файл имеет размер 350670 байт. Есть ID3v1 теги (128 байт) и ID3v2 теги (1024 байта). Битрейт = 96. Следовательно размер аудиоданных равен 350670 – 128 – 1024 = 349518 байт.
Длительность = 349518 / 96000 * 8 = 29,1265 = 29 секунд
VBR
Необходимо пояснить – как определить режим сжатия. Всё просто. Если файл сжат с VBR – то добавляется VBR-заголовок. По его наличию мы и можем понять, что используется переменный битрейт.
Есть два вида заголовков: Xing и VBRI.
Xing размещается со смещением от начала первого mp3-фрейма в позиции, согласно таблице:
Например: у нас ID3v2 тег занимает 1024 байта. Если наш mp3-файл имеет режим канала «Стерео» — то заголовок VBR Xing будет начинаться со смещения 1024 + 32 = 1056 байт.
Заголовок VBRI всегда размещается со смещением +32 байта от начала первого mp3-фрейма.
Первые четыре байта в обоих заголовках содержат маркер ‘Xing’ или ‘Info’ для Xing. И ‘VBRI’ для VBRI.
Эти VBR заголовки имеют переменную длину и содержат различную информацию о кодировании файла. Подробнее о структуре заголовков VBR (и не только) можно почитать, например, тут.
Я же расскажу только о том, что нас интересует в данный момент. А именно – количество фреймов (Number of Frames). Это число длиной 4 байта.
В заголовке Xing оно содержится по смещению +8 байт от начала заголовка. В VBRI +14 байт от начала заголовка.
Используя таблицу Сэмплов на фрейм (Sampler Per Frame) мы можем получить длительность mp3-файла, закодированного с переменным битрейтом.
Длительность = Количество фреймов * Сэмплов на фрейм / Частоту дискретизации
Например: из заголовка VBRI получили количество фреймов 1118, сэмплов на фрейм = 1152. Частота дискретизации = 44100.
Длительность = 1118 * 1152 / 44100 = 29.204 = 29 секунд.
На этом на сегодня всё. Если был кому-то полезен — спасибо.
Для тех, кто захочет немедленно поковырять внутренности mp3 — Тут лежат скрипт на php, которые я писал для себя одновременно с данной статьей и четыре небольших mp3-файла для теста.
Ссылки
id3.org — Читаем о ID3
id3.org — и кое-что о mp3 frame
Довольно подробно о mp3 frame
getID3: Неплохая библиотека для получения информации о mp3. (PHP)