Python:使用Kaitai Struct

时间:2016-08-07 19:55:21

标签: python id3 kaitai-struct

我正在尝试让Kaitai Struct解析MP3的ID3v1标签格式。根据{{​​3}},它是一个位于特定偏移处的固定格式结构 - 但诀窍是这个偏移量不是从文件的开头计算,而是从结尾计算。

以下是标记的基本.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的File对象seek()中,因此失败了:

  

回溯(最近一次调用最后一次):文件“try-id3.py”,第6行,in          print(f.id3v1_tag)文件“id3v1_1.py”,第171行,在id3v1_tag中       self._io.seek(-128)文件“kaitaistruct.py”,第29行,在搜索中       self._io.seek(n)IOError:[Errno 22]参数无效

在其他一些同样疯狂的想法之后,我找到了一个解决方法:我可以省略pos中的任何.ksy个参数,然后我手动寻找我脚本中的正确位置:

f = Id3v1.from_file('some_file_with_id3.mp3')
f._io.seek(-128, 2)
print(f.tag.title)

这有效,但感觉非常hackish :(在Kaitai Struct和Python中有更好的方法吗?

1 个答案:

答案 0 :(得分:1)

Kaitai Struct即将发布的v0.4中有一个新功能可以解决这个问题。您可以使用_io获取当前流对象,然后可以使用.size以字节为单位获取当前流的全长。因此,如果您想要通过流末尾的固定偏移量来解决某些结构,那么您需要使用类似于.ksy的内容:

instances:
  tag:
    pos: _io.size - 128
    type: id3v1_tag

请注意,虽然current stable是v0.3,但您必须从Github下载并构建编译器+运行时并使用最新版本。