标题/专辑名称长度超过30个字节

时间:2017-05-04 17:32:19

标签: python id3

Dunno,如果这是正确的地方。

我正在尝试读取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 个答案:

答案 0 :(得分:1)

正如PeterCo在评论中所说,只要ID3v1标签知道,你就 读取完整的标题。该标准有一些非正式的扩展,允许稍长的字段(" extended tag"比ID3v1.2或{{3}更为知名}),但它们都没有共同点 - 如果您的测试文件包含它们,我会感到惊讶。我的猜测是,显示完整标题的程序实际上是从ID3v2标签中获取的,其中(尽管名称)与ID3v1几乎没有共同之处。

如果你只是想要确保正确的文件通过更大的程序正确的路径,那么我建议坚持你所拥有的;它清晰轻巧。如果您关心ID3v1标记,则相同。但是,如果 使用完整标题做某事,那么到目前为止最好的选择是使用ID3v1.3中的一个。实际上,我觉得实现规范很有趣,但并没有反对它自己整个项目的事实。

那就是说,如果你知道你永远不会想要除标题之外的任何东西(或者可预测的,有限选择的其他几乎无处不在的文本字段),你可以天真地扫描文件寻找合适的文件。标题,如下所述。我希望你能原谅我不写真正的代码,但是自从我编写Python之后已经有一段时间了。如果你这样做,我真的建议你查看existing libraries official,以便更好地了解你将要跳过的内容。

您要做的第一件事是检查文件的前三个字节。如果他们不是49 44 33(ASCII中的ID3),那么它可能没有ID3v2标记(或者它的格式不正确),您也可以依赖它ID3v1。当您在这里时,您可能需要检查第四个字节 - 它将是0304,具体取决于文件使用的版本。一旦我们到达文本,它们之间会有一些差异,但是现在只需确保第二个字节(文件中的第六个)小于128,特别是如果版本字节是03;相信我,你不想处理扭转不同步的问题。

一旦您确认了这一点,就开始浏览该文件,直到找到序列54 49 54 32TIT2代表"文字标题2"这实际上是数字我们想要;或者,您可能想要为艺术家匹配54 50 45 31 TPE1,或者为相册匹配54 41 4C 42 TALB,或者在规格中查找其他ID。这不是一个特别常见的序列,但只是为了确保您不会遇到任何已经保存在评论或任何内容中的内容,您可能希望确定下一个几个字节跟随00 00 0_ __ _0 00 - 甚至不完全是万无一失的。无论如何,前四个字节是大小,虽然它在技术上可能,但是前两个半就不会是00 00 0,那就是需要一个可笑的长文本字符串(超过2047字节)或填充太多;最后两个表示关于该字段的特殊属性,并且虽然零可能实际上不是零,但这意味着对于字段的编码方式并不是直截了当的,并且如果你试图解决这个问题,你可以考虑实施整个标准。

读取下一个字节。它表示文本的编码方式:00表示specifications01表示UTF-16以字节顺序标记开头,02表示大端UTF-16没有字节标记,03是UTF-8。您可以忽略任何您不想处理的内容,但ID3v2.3仅支持前两个,如果您已经识别出UTF-16,那么忽略UTF-16BE并没有任何好处BOM(以及足够的程序在您希望捕获的编码中写入标签),如果您识别ISO-8859-1,则为UTF-8。

之后是那个版本字节真正发挥作用的地方。如果你在ID3v2.3中,你只需要读取直到第一个空字符(不是字节;仅对于UTF-16编码,这意味着要查找两个连续的00个字节)。如果您在ID3v2.4中,则需要在该简单方法之间做出决定,或者完全支持新版本支持的多个值。我推荐第一个 - 不管你信不信 - 我试图保持这个实现简洁,但为了完整性,另一个需要记住两个段落中的大小字节,移动第三个(前半个空白)通过 7 位(或乘以128)并添加第四个(全空白),读取多个字节(不是字符),根据前一段解码它们,并将字符串拆分为空字符(不是字节)。

然后,最后,你有完整的头衔。如果你想继续寻找另一个文本标签(比如我在那里放弃的作者​​或专辑),那么你需要继续扫描文件的其余部分以找到它们的标题。否则,只需跳转到ID3v1标签,并陶醉于获取截断值的简单程度。