reveal search box

pytagger

Intro

pytagger is a ID3 tag reader and writer implemented purely in Python. It supports all the current ID3 tag implementations including ID3v1, ID3v1.1, ID3v2.2, ID3v2.3 and ID3v2.4.

(Note: This project has now been renamed from pyid3v2 to pytagger to avoid conflict with existing projects.)

Download

  • pytagger-0.5 (10 May 2006)

    • Fix APIC extraction alignment error for v2.2, v2.3, v2.4
    • Fix APIC insertion error for v2.2
    • Refactored APIC output and input.
    • Removed debugging print statement for ID3v2
  • pytagger-0.4 - (07 May 2005)

    • API!! Does not throw exception if unable to find ID3 tag. You should now check the output tag_exists() to determine whether it was able to find tags. This is done so that you can create new ID3 tags without requiring the old one to be there. Still throws exceptions if tags found is invalid or IOErrors occur.
    • Added BSD license to source files
    • Revamped ID3v1 to allow read and write
    • Removed mode parameter from ID3v1 and ID3v2 contructor. It now autodetects mode.
    • Added ability to write to new file rather than modify existing open file.
    • Many bugfixes.
    • Edited mp3check.py to use the new API.
  • pytagger-0.2 - (07 May 2004) Major Revision. Totally new API.

    • Renamed to pytagger to avoid confusion with pyid3.
    • totally refactored code
    • added epydoc and copious documentation
    • added some preliminary unit tests
    • run over with pylint to ensure correctness
    • changed to use proper encoding names
  • pyid3v2-0.1.1 - (03 Feb 2004) - Bugfix Release.

    • Fixed major problems with ID3v2.2 support, nicer handling of invalid tags, etc.
  • pyid3v2-0.1 - (14 Jan 2004) - Initial Release

Example Usage

As with most pieces of software, you'd probably want a sample script to show you how this works:

>>> from tagger import *
>>> mp3_tag = ID3v2('amazing.mp3')      
>>> mp3_tag.version
2.2000000000000002

You can easily access the contents of frames:

>>> for frame in mp3_tag.frames:
...     print frame.fid 
... 
TT2
TP1
TAL
TRK
TYE
TEN
COM
COM
PIC
TCO
>>> for frame in mp3_tag.frames:
...     if frame.fid == 'TT2':
...             print frame.strings
... 
['Amazing', '']

You can add and remove frames from the ID3v2 tag:

>>> title_frame = mp3_tag.new_frame('TT2')
>>> title_frame.set_text('More Amazing') 
>>> title_frame.strings
['More Amazing']
>>> old_title_frame = [frame for frame in mp3_tag.frames if frame.fid == 'TT2'][0]
>>> mp3_tag.frames.remove(old_title_frame)
>>> mp3_tag.frames.append(title_frame)

You can commit your changes or discard them:

>>> mp3_tag.commit()
>>> mp3_tag.commit_to_file('newmusic.mp3')

And of course, you can also use it to read ID3v1 tags

>>> mp3_tag1 = ID3v1('amazing.mp3')
>>> print mp3_tag1.artist
'Alex Lloyd'

More complete documentation of the API can be found here.

Motivation

I initially wanted to edit ID3 tags of MP3 files in python. The main reason being that there are alot of MP3s around with non-unicode (eg. Big5 or GB2312) tags floating around. Under Linux GNOME applications default to using UTF-8 and under Mac OS X, iTunes require you to use UTF-16 for non ASCII tags.

I attempted to build wrappers for libid3tag and id3lib. Both of them had pecularities that made it difficult to understand or wrap around with Python.

There are also other pure Python implementations for ID3v1 and ID3v2 but they are either read-only or only support particular version. So rather than learning someone else's code, I decided to have a go at writing my own parser.

The code you see now has gone through a number of refactoring cycles and is the easier to work with for text tags. There are other tags such as embedding objects, numbers and URLs. Those have been less aggressively tested.

pytagger is now the basis of a Mac OS X application I wrote called TagEncoder which allows you to drag and drop MP3s in order to convert their tags from one encoding to another.

However, there will definitely still be bugs left. Right now, it is still in beta state, so the API can change at any minute. If you are using this for any application, please let me know so we can discuss what sort of API is the most useful. I'm still inexperienced with designing APIs so I would appreciate any input.

TODO

  • Higher level wrapping of common tag manipulation functions such as changing artist, songname and album for ID3v2 tags so people don't need to remember what TIT and TIT2 is.
  • Regression testing
  • Better documentation.
add commentAdd a comment
Joshua Hewitt says
10
I seem to have run into a bug. Using Pytagger v. 0.5 (Python v. 2.5.2). Trying to set int values for id3v1.genre and id3v1.track and it looks like "types" hasn't been imported:

Traceback (most recent call last):
File "musicTagger.py", line 113, in
tagRepair(ParsedDirectory(path))
File "musicTagger.py", line 97, in tagRepair
id3v1.genre = parsedDirectory.genre
File "build\bdist.win32\egg\tagger\id3v1.py", line 157, in __setattr__
NameError: global name 'types' is not defined
  • 1 year, 10 months ago (30/03/2008)
Ekred says
9
Is this project still alive? If not, I would be interested in carrying it on. Let me know!

eklectiqred*@*g*m*a*i*l*.*c*o*m
(without *, of course :P)
  • 2 years, 6 months ago (27/07/2007)
Ben Pirt says
8
Is it possible to support the TCMP compilation frame? Although I think it is non-standard it is very heavily used. Largely thanks to Apple I believe.

Great tagger by the way - recognised far more tags than the other python ID3 libraries I tried out.

Thanks.
  • 2 years, 8 months ago (14/06/2007)
Jokull Solberg says
7
Thank you for pytagger! Elegant id3 tool.

mp3check doesn't return foreign characters correctly (while players read them correctly).

Here is a sample of the output.

2-20 Jólakveðjur.mp3 : TT2 (latin_1) ['J\xf3lakve\xf0jur', '']
2-20 Jólakveðjur.mp3 : TP1 (latin_1) ['Eyj\xf3lfur Kristj\xe1nsson', '']
2-20 Jólakveðjur.mp3 : TRK (latin_1) ['20/20', '']
2-20 Jólakveðjur.mp3 : TPA (latin_1) ['2/5', '']
2-20 Jólakveðjur.mp3 : TYE (latin_1) ['2006', '']
2-20 Jólakveðjur.mp3 : TEN (latin_1) ['iTunes v7.0.2.16', '']
2-20 Jólakveðjur.mp3 : TAL (latin_1) ['100 \xedslensk j\xf3lal\xf6g [Disc 2/5]', '']
2-20 Jólakveðjur.mp3 : PIC (latin_1) []
2-20 Jólakveðjur.mp3 : TCO (latin_1) ['Christmas', '']

Similarly when I save an id3v1 (in winamp) and read with mp3check.py it returns nothing for fields with foreign characters.

How can I display my funky Icelandic characters? Any help much appreciated!
  • 3 years ago (21/01/2007)
187 says
6
pity that there's no new mp3conv, only mp3tagconf.py which is also broekn. please reupload.
  • 3 years, 2 months ago (15/11/2006)
Alastair Tse says
5
ID3's standard is really only latin-1, and the utf variants. All the other character sets such as Big5, ISO2022, etc are non-standard usages of ID3. But you can still make pytagger use those encodings, I use it in my TagEncoder to convert chinese ID3 tags to unicode ones that are compatible with iTunes.
  • 3 years, 3 months ago (03/11/2006)
ianare says
4
Hey,

Your program looks like it would work perfectly for my application (see link), save for one minor issue: encoding conversions. It looks like the only supported encodings are:

ID3V2_VALID_ENCODINGS = ["latin_1", "utf_16", "utf_16_be", "utf_8"]

is this correct?

I would need something that can convert all encodings handled by python. The reason being that I have had people send me mp3's in russian or japanese for exemple that were encoded in the windows encoding for that language. So just to play it safe, I allow all encodings.

If this would need to be added to your program, would it be a big overhaul or just some minor changes to the code to allow other encodings? I admit I haven't looked too closely at the code.

In any case, I would be happy to help you getting this to work. I was able to modify another mp3 parser to do the encoding stuff, but it's a little sloppy and yours opens up more possibilities for my application.

You can contact me here:

ianare AT gmail DOT com


Kind regards,
ianaré sévi
  • 3 years, 3 months ago (02/11/2006)
Alan says
3
Hello, I'm writing here since I can't find a ML or other place. I've spotted a bug in svn regarding ID3v1: at a certain point, the code in id3v1.py refers to 'types.IntValue', but there's no 'import types' statement and the code should be 'type.IntType' anyway.

Also, the ID3v2 still mentions a 'mode' arg which could be passed to the constructor, but it seems to be long gone in the actual code, which now 'autodetects' the correct mode to emply.

I could attach a diff for the id3v1.py if you tell me where to send it :-)

Alan Franzoni
alan.franzoni@geemail.kom

(mangled mail domain, change it with gmail.com to contact me)
  • 3 years, 4 months ago (03/10/2006)
Alastair Tse says
2
A couple of others were missing, I've just added them to SVN.
  • 3 years, 7 months ago (06/07/2006)
meyers says
1
I see that in the ID3V2_4_FRAME_NEW_FOR_2_4 constant that TMOO is mentioned, but is it implemented anywhere? When I try to read or write to the 'TMOO' field I get the 'ID3v2 exception: Unsupported ID3v2 Field: TMOO'.

Thanks.
  • 3 years, 7 months ago (05/07/2006)