2016-08-07 3 views
3

Ich versuche Kaitai Struct, ein ID3v1-Tag-Format für MP3s zu parsen. Gemäß der standard ist es eine feste Formatstruktur, die sich am bestimmten Offset befindet - aber der Trick ist, dass dieser Offset nicht vom Anfang der Datei, sondern vom Ende her berechnet wird.Python: Lesen ID3v1-Tag mit Kaitai Struct

Hier ist der Grund .ksy Umriss des Tages, ich gehe davon aus, dass es nicht wirklich ändern soll:

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 

und meine naive Idee, wie um es hier von dem 128 Bytes gelesen werden bis zum Ende der Datei:

instances: 
    tag: 
    pos: -128 
    type: id3v1_tag 

ich versuche, dass mit einem einfachen Python Testskript:

#!/usr/bin/env python 

from id3v1 import * 

f = Id3v1.from_file('some_file_with_id3.mp3') 
print(f.tag) 

Allerdings scheint es, dass die negativen Betrag in den seek() und somit File-Objekt Python direkt nicht besteht:

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

Nach einigen anderen ebenso wahnsinnigen Ideen, ich eine Abhilfe gefunden habe: ich keine pos Argumente nur weglassen ich suche manuell in die richtige Position in .ksy und dann in meinem Skript:

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

Dies funktioniert, aber fühlt sich wirklich hackish :(gibt es einen besseren Weg, um es in Kaitai Struct und Python zu tun?

Antwort

1

Es gibt ein neues Feature in der kommenden v0.4 von Kaitai Struct, das genau dieses Problem anspricht. Sie können _io verwenden, um aktuelles Streamobjekt abzurufen, und dann können Sie .size verwenden, um die volle Länge des aktuellen Datenstroms in Byte zu erhalten. wenn Sie wollen, würde also auf eine gewisse Struktur adressieren, indem eine vom Ende des Stroms festen Offset, würden Sie so etwas wie in Ihrem .ksy verwenden:

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

Beachten Sie, dass während der Strom stabil ist v0. 3, müssen Sie die Compiler + Laufzeiten aus dem Github herunterladen und erstellen und die neuesten verwenden.

+1

Danke! Das könnte es gut lösen! Ich habe versucht [REPL] (http://kaitai.io/repl) - es berichtet v0.4, aber es scheint, dass es '_io.size' obwohl nicht unterstützt. Ist es nur ich oder da ist ein Fehler? –

+1

Ja, es ist noch nicht aktualisiert. Bleibt dran für die Veröffentlichung von v0.4, es sollte hoffentlich in dieser Woche passieren. – GreyCat

+1

v0.4 ist out! Fühlen Sie sich frei zu überprüfen! – GreyCat