Можно ли прочитать теги ID3 MP3, хранящиеся в Интернете, без фактической загрузки всего файла?
Я использовал TagLib Sharp, но, насколько мне известно, вам действительно нужно открыть файл, чтобы прочитать теги ID3.
Можно ли прочитать теги ID3 MP3, хранящиеся в Интернете, без фактической загрузки всего файла?
Я использовал TagLib Sharp, но, насколько мне известно, вам действительно нужно открыть файл, чтобы прочитать теги ID3.
Как сказал Флориан выше, вы можете использовать диапазон HTTP, чтобы прочитать немного файла и посмотреть, есть ли ID3 или нет, а затем прочитать остальную часть тега (если он присутствует/необходим). Например:
Range: bytes=0-65535
Тег ID3 может включать изображение, поэтому он может быть очень большим (я видел некоторые из них размером 500 КБ). Однако большая часть полезной информации, такой как заголовок, описание и т. д., скорее всего, будет доступна в первых нескольких килобайтах. В зависимости от ваших подключений (или ожидаемых подключений клиента) я бы выбрал первое количество килобайт для загрузки. Для большинства подключений скорость 64 КБ сейчас будет очень высокой (возможно, в 2014 году было меньше).
Обратите внимание, что весь файл также может быть менее 64 КБ. Запрос Range все еще должен работать, только он вернет размер файла. В этом случае вы никогда не отправите второй запрос на получение дополнительных данных.
Файл MP3 с тегом ID3 начинается так:
0x49 0x44 0x33 ID3
0x03 0x00 major.revision (2.0 or 3.0)
0x00 flags
0xSS 0xSS 0xSS 0xSS size
Примечания к версии:
- Тег ID3, что
3
не является частью версии- Первая версия —
2
, потому что MP3 уже имел возможностьTAG
и считалась версией1
(и1.1
при определенных условиях).- На данный момент я не вижу никакой ревизии, кроме
0
. Вот почему мы ссылаемся на теги как на ID3v1 (TAG
), ID3v2 (ID3
+ 0x02) и ID3v3 (ID3
+ 0x03).
0xSS
представляет размер. Это интересно, потому что в каждом байте используется только 7 бит, чтобы избежать 0xFF
, который является кодом синхронизации для файлов MP3 (MPEG). Только они забывают что-то сделать с 0xFF
в изображениях PNG и JPEG... В любом случае...
Способ расчета размера выглядит следующим образом:
size = (buffer[pos + 6] << 21) +
(buffer[pos + 7] << 14) +
(buffer[pos + 8] << 7) +
(buffer[pos + 9] << 0)
ВАЖНО: вы должны убедиться, что бит 7 не установлен ни в одном из этих байтов. Если установлено, то это недействительный тег ID3. Вот почему я не делаю (buffer[pos + n] & 0x7F
), часть & 0x7F
не требуется, если вы заранее правильно проверили размер.
Обратите внимание, что это size
не включает размер заголовка. Так что имейте в виду, что для заголовка есть 10 байтов.
Остальная часть буфера организована в виде кадров. Это либо 3 буквы, размер и данные этого фрейма, либо 4 буквы, размер, флаги и данные. Заголовок каждого кадра определяется версией (2 или 3).
В любом случае, если у вас есть этот size
, если вы хотите прочитать весь ID3, вы можете выполнить еще один GET на HTTP-сервер и получить оставшиеся данные, если первые 64 КБ (или любой другой размер, который вы использовали первым) уже не больше или не равен необходимый размер.
Range: bytes=65536-<size + 10 - 1>
Размер - это данные в ID3. +10 для заголовка. Значение -1 связано с тем, что диапазон HTTP включает (не размер, а положение).
ВАЖНОЕ ПРИМЕЧАНИЕ. Все серверы не принимают заголовок Range
. Если у вас все под контролем, а ваш сервер не поддерживает запросы диапазона, вы можете рассмотреть возможность добавления прокси-сервера перед сервером. nginx действительно хорош в этом. Он может кэшировать весь файл и возвращать только те диапазоны, которые запрошены в заголовке HTTP.