Python:用Kaitai Struct读取ID3v1标签
Python: reading ID3v1 tag with Kaitai Struct
我正在尝试让 Kaitai Struct 解析 MP3 的 ID3v1 标签格式。根据standard,它是位于某个偏移量的固定格式结构——但诀窍是这个偏移量不是从文件的开头计算的,而是从末尾计算的。
这是标签的基本 .ksy
大纲,我认为它不应该真正改变是理所当然的:
meta:
id: id3v1
types:
id3v1_tag:
seq:
- id: magic
contents: 'TAG'
- id: title
size: 30
- id: artist
size: 30
- id: album
size: 30
- id: year
size: 4
- id: comment
size: 30
- id: genre
type: u1
这是我关于如何从 128 字节读取文件到文件末尾的幼稚想法:
instances:
tag:
pos: -128
type: id3v1_tag
我尝试使用一个简单的 Python 测试脚本:
#!/usr/bin/env python
from id3v1 import *
f = Id3v1.from_file('some_file_with_id3.mp3')
print(f.tag)
但是,它似乎将该负数直接传递给 Python 的文件对象 seek()
,因此失败了:
Traceback (most recent call last): File "try-id3.py", line 6, in
print(f.id3v1_tag) File "id3v1_1.py", line 171, in id3v1_tag
self._io.seek(-128) File "kaitaistruct.py", line 29, in seek
self._io.seek(n) IOError: [Errno 22] Invalid argument
在其他一些同样疯狂的想法之后,我找到了一个解决方法:我可以省略 .ksy
中的任何 pos
参数,然后我手动寻找脚本中的正确位置:
f = Id3v1.from_file('some_file_with_id3.mp3')
f._io.seek(-128, 2)
print(f.tag.title)
这行得通,但感觉真的很糟糕 :( 在 Kaitai Struct 和 Python 中有更好的方法吗?
即将发布的 Kaitai Struct v0.4 中的一项新功能正好解决了这个问题。您可以使用 _io
获取当前流对象,然后可以使用 .size
获取当前流的完整长度(以字节为单位)。因此,如果你想通过从流的末尾开始的固定偏移量来寻址某些结构,你会想在你的 .ksy:
中使用类似的东西
instances:
tag:
pos: _io.size - 128
type: id3v1_tag
请注意,虽然当前的稳定版是 v0.3,但您必须从 Github 下载并构建编译器 + 运行时并使用最新的。
我正在尝试让 Kaitai Struct 解析 MP3 的 ID3v1 标签格式。根据standard,它是位于某个偏移量的固定格式结构——但诀窍是这个偏移量不是从文件的开头计算的,而是从末尾计算的。
这是标签的基本 .ksy
大纲,我认为它不应该真正改变是理所当然的:
meta:
id: id3v1
types:
id3v1_tag:
seq:
- id: magic
contents: 'TAG'
- id: title
size: 30
- id: artist
size: 30
- id: album
size: 30
- id: year
size: 4
- id: comment
size: 30
- id: genre
type: u1
这是我关于如何从 128 字节读取文件到文件末尾的幼稚想法:
instances:
tag:
pos: -128
type: id3v1_tag
我尝试使用一个简单的 Python 测试脚本:
#!/usr/bin/env python
from id3v1 import *
f = Id3v1.from_file('some_file_with_id3.mp3')
print(f.tag)
但是,它似乎将该负数直接传递给 Python 的文件对象 seek()
,因此失败了:
Traceback (most recent call last): File "try-id3.py", line 6, in print(f.id3v1_tag) File "id3v1_1.py", line 171, in id3v1_tag self._io.seek(-128) File "kaitaistruct.py", line 29, in seek self._io.seek(n) IOError: [Errno 22] Invalid argument
在其他一些同样疯狂的想法之后,我找到了一个解决方法:我可以省略 .ksy
中的任何 pos
参数,然后我手动寻找脚本中的正确位置:
f = Id3v1.from_file('some_file_with_id3.mp3')
f._io.seek(-128, 2)
print(f.tag.title)
这行得通,但感觉真的很糟糕 :( 在 Kaitai Struct 和 Python 中有更好的方法吗?
即将发布的 Kaitai Struct v0.4 中的一项新功能正好解决了这个问题。您可以使用 _io
获取当前流对象,然后可以使用 .size
获取当前流的完整长度(以字节为单位)。因此,如果你想通过从流的末尾开始的固定偏移量来寻址某些结构,你会想在你的 .ksy:
instances:
tag:
pos: _io.size - 128
type: id3v1_tag
请注意,虽然当前的稳定版是 v0.3,但您必须从 Github 下载并构建编译器 + 运行时并使用最新的。