Названия / Названия альбомов длиной более 30 байт

Не знаю, если это правильное место.

Я пытаюсь прочитать метаданные тегов ID3V1, и некоторые заголовки длиннее 30 байт, а другие программы не имеют проблем с чтением полного заголовка. Я проверил id3.org, но не смог найти ничего полезного. Как мне прочитать полное название?

#!/usr/bin/python3

from os import listdir
from os.path import isfile, join

path = "/media/Music/RZ"
files = [join(path, f) for f in listdir(path) if isfile(join(path, f)) and f.endswith("mp3")]

for f in files:
    with open(f, "rb") as f:
        f.seek(-128, 2)
        data = f.read()

        if data[:3] == b"TAG":
            title = data[3:33].decode("UTF-8")
            artist = data[33:63].decode("UTF-8")
            album = data[63:93].decode("UTF-8")

печать результатов приводит к

Super-Doom-Hex-Gloom Part One
Get Your Boots On ! That's The
Wurdalak
In The Age Of The Consegrated 
A Hearse That Overturns With T
Well, Everybody's Fucking In A
Satanic Cyanide ! The Killer R
The Life And Times Of A Teenag
The Last Of The Demons Defeate
Medication For The Melancholy
The Hideous Exhibitions Of A D
In The Bone Pile

1 ответ

Решение

Как сказал PeterCo в своем комментарии, насколько вы знаете тег ID3v1, вы читаете полный заголовок. Существует несколько неофициальных расширений стандарта, которые допускают немного более длинные поля (" расширенный тег " немного более известен, чем ID3v1.2 или ID3v1.3), но ни одно из них не является общим - до такой степени, что я буду удивлен, если ваши тестовые файлы будут включать их. Я предполагаю, что программы, которые показывают полные заголовки, на самом деле берут его из тега ID3v2, который (несмотря на название) имеет очень мало общего с ID3v1.

Если вы просто хотите что-то, чтобы убедиться, что правильные файлы следуют по правильному пути через большую программу, то я бы рекомендовал придерживаться того, что у вас есть; это ясно и легко. То же самое, если вы заботитесь только о теге ID3v1. Однако, если вы делаете что-то с полным заголовком, лучше всего было бы использовать одну из существующих библиотек. На самом деле я нахожу это забавным для реализации спецификации, но нет никаких аргументов против того факта, что это целый проект сам по себе.


Тем не менее, если вы знаете, что вам никогда не понадобится ничего, кроме заголовка (или предсказуемого, ограниченного выбора других почти повсеместных текстовых полей), вы можете наивно сканировать файл в поисках подходящих заголовков, как описано ниже., Я надеюсь, что вы простите меня за то, что я не пишу настоящий код, но с тех пор, как я написал Python, прошло много времени. Если вы согласитесь с этим, я бы порекомендовал ознакомиться с официальными спецификациями, чтобы лучше понять, что именно вы пропустите.

Первое, что вам нужно сделать, это проверить первые три байта файла. Если они не 49 44 33 (ID3 в ASCII), то, вероятно, у него нет тега ID3v2 (или он искажен), и вы также можете прибегнуть к ID3v1. Пока вы здесь, вы можете проверить четвертый байт - это будет либо 03 или же 04 в зависимости от того, какую версию использует файл. Есть несколько различий между ними, которые могут вступить в игру, как только мы дойдем до текста, но пока просто убедитесь, что второй байт после этого (шестой в файле) меньше 128, особенно если байт версии 03; Вы не хотите иметь дело с обращенной асинхронизацией, поверьте мне.

После того, как вы проверите это, просто начните пробежку по файлу, пока не найдете последовательность 54 49 54 32 (TIT2 представляющий "Text tITle 2", который фактически является числом, которое мы хотим; в качестве альтернативы, вы можете захотеть соответствовать 54 50 45 31TPE1 для художника или 54 41 4C 42TALB для альбома, или искать другие идентификаторы в спецификации). Это не совсем обычная последовательность, но просто чтобы быть уверенным, что вы не столкнетесь ни с чем, что было сохранено в комментарии или чем-то еще, вы, вероятно, захотите убедиться, что следующие несколько байтов следуют 00 00 0_ __ _0 00 - и даже это не совсем надежно. В любом случае, первые четыре байта имеют размер, и хотя технически возможно, что верхние два с половиной не будут 00 00 0, что потребовало бы смехотворно длинной строки текста (более 2047 байт) или слишком большого заполнения; последние два указывают на особые свойства поля, и, хотя опять-таки возможно, что нули на самом деле не являются нулями, это будет означать, что есть что-то непростое в том, как кодируется поле, и если вы попытаетесь обработать это, вы можете хорошо подумайте о реализации всего стандарта.

Прочитайте следующий байт. Указывает, как кодируется текст: 00 означает ISO-8859-1, 01 означает UTF-16, начинающийся с маркера порядка следования байтов, 02 является байтовым порядком байтов UTF-16 без байтового маркера, и 03 это UTF-8. Вы можете игнорировать любого из тех, с кем вы не хотите иметь дело, но ID3v2.3 поддерживает только первые два, и нет никакого смысла игнорировать UTF-16BE, если вы уже распознаете UTF-16 с BOM (и достаточно написано программ теги в той кодировке, которые вы захотите поймать), или UTF-8, если вы узнаете ISO-8859-1.

После этого байт этой версии действительно вступает в игру. Если вы в ID3v2.3, вам нужно только прочитать до первого нулевого символа (не байта; только для кодировок UTF-16, что означает поиск двух последовательных символов). 00 байт). Если вы находитесь в ID3v2.4, вам нужно будет выбрать между этим простым подходом или полной поддержкой нескольких значений, поддерживаемых новой версией. Я рекомендую первый, поскольку - хотите верьте, хотите нет - я стараюсь сделать эту реализацию краткой, но для полноты другой требует запоминания байтов размера из двух абзацев назад, сдвигая третий (первый полупустой) влево на 7 биты (или умножение на 128) и добавление четвертого (полный пробел), считывание такого количества байтов (не символов), декодирование их в соответствии с предыдущим абзацем и разбиение строки на нулевые символы (не байты).

И, наконец, у вас есть полное название. Если вы хотите продолжить поиск другого текстового тега (например, автора или альбома, который я там указывал), вам нужно будет продолжить сканирование остальной части файла, чтобы найти их заголовки. В противном случае просто перейдите к тегу ID3v1 и наслаждайтесь тем, как просто получить усеченные значения.

Другие вопросы по тегам