|
Mutagen
Mutagen tagging library
MutagenMutagen has moved!Mutagen is now a separate project on Google Code. This page will remain intact until the new project has moved up in the search results, but updates and issues against Mutagen itself should be part of that project. What is Mutagen?Mutagen is a Python module to handle audio metadata. It supports ASF, FLAC, M4A, Monkey's Audio, MP3, Musepack, Ogg FLAC, Ogg Speex, Ogg Theora, Ogg Vorbis, True Audio, WavPack and OptimFROG audio files. All versions of ID3v2 are supported, and all standard ID3v2.4 frames are parsed. It can read Xing headers to accurately calculate the bitrate and length of MP3s. ID3 and APEv2 tags can be edited regardless of audio format. It can also manipulate Ogg streams on an individual packet/page level. There is a brief tutorial with several API examples. Where do I get it?The download page will have the latest version, which is at the current time of writing mutagen-1.15.tar.gz. It can also be checked out from our Subversion repository. $ svn co http://svn.sacredchao.net/svn/quodlibet/trunk/mutagen Why Mutagen?Quod Libet has more strenuous requirements in an ID3 library than most programs that deal with tags. Furthermore, most tagging libraries suck. Therefore we felt it was necessary to write our own.
Real World UseMutagen can load every MP3 we have thrown at it (when it hasn't, we make it do so). Scripts are included so you can run the same tests on your collection. The following software projects are using Mutagen for tagging:
|
Sign in to add a comment
Where can we find examples on how to use the Mutagen library?
http://svn.sacredchao.net/svn/quodlibet/trunk/mutagen/TUTORIAL
Any plans for python 3.0 compatibility?
a small example querying a flac file
#!/usr/bin/env python from mutagen.flac import FLAC from pprint import pprint import sys DEBUG=False if len(sys.argv) > 1: fname = sys.argv[1] else: fname = "/Users/philou/Music/Lhasa/La Llorona/01 De Cara A La Pared.flac" audio = FLAC(fname) if DEBUG: print "DD: instancied a mutagen object of type %s for file %s" % (type(audio), fname) print "DD: pprint(instance):" pprint(audio) print "/DD" print if audio.has_key('artist'): print "Artist: ", audio['artist'][0] if audio.has_key('album'): print "Album: ", audio['album'][0] if audio.has_key('tracktotal'): tracktot = int(audio['tracktotal'][0]) else: tracktot = None if audio.has_key('tracknumber'): trackn = int(audio['tracknumber'][0]) if tracktot != None: track_str = "%s / %s" % (trackn, tracktot) else: track_str = str(trackn) print "Track: %s" % track_str if audio.has_key('title'): print "Title: ", audio['title'][0] if audio.has_key('mcn'): print "MCN: ", audio['mcn'][0] if audio.has_key('isrc'): print "ISRC: ", audio['isrc'][0] print "Sample rate: ", audio.info.sample_rate print "Nr. of channels: ", audio.info.channels print "Bits per sample: ", audio.info.bits_per_sample print "Total nr. of samples:", audio.info.total_samples print "Length in secs: ", audio.info.length print "MD5: ", audio.info.md5_signatureAn apparent source of confusion is the relationship between mutagen.mp3, id3, and easyid3. mp3.MP3 should be used to open an MP3 file; in addition to reading ID3v2 tags using either of the two ID3 parsers in Mutagen, it also reads additional information from the actual MPEG stream which may not be in the ID3 tags (like bitrate and duration).
An mp3.MP3 object behaves like a dict, like ID3 and EasyID3; in fact, the methods for getting and setting keys and values on an MP3 appear to simply map to the underlying ID3 parser's. If the ID3 tags you're working are on MP3 files, stick to using mp3.MP3 instead of using ID3 objects directly.
An mp3.MP3 object also has the method add_tags(), which allows you to add ID3 tags to a file that doesn't have any. This is the only way to add ID3 tags within Mutagen, AFAIK.
Also: mp3.add_tags has an optional argument 'ID3', which works just like the same arg on the constructor of an mp3 object, viz:
from mutagen.mp3 import MP3 from mutagen.easyid3 import EasyID3 import mutagen.id3 def test(filename): """Example which shows how to automatically add tags to an MP3 using EasyID3.""" m = MP3(filename, ID3=EasyID3) try: m.add_tags(ID3=EasyID3) print("Added tags to %s" % filename) except mutagen.id3.error: print("%s already had tags" % filename) m['title'] = 'Test!' m.save() print(m.pprint()) print('\n') test('has-tags.mp3') test('no-tags.mp3')Any chance this library could ever be licensed as LGPL?
An example of writing tags to an ASF/WMA file in a format that ffmpeg knows how to decode:
from mutagen.asf import ASF audio = ASF("myfilename.wma") audio["Title"] = "MyTitle" audio["Author"] = "MyArtist" audio["WM/AlbumTitle"] = "MyAlbum" audio["WM/TrackNumber"] = "12" #print ASF.pprint(audio) #print ASF.keys(audio) ASF.save(audio)I use the "Author" tag for "Artist", as that happens to be the mapping used by musicpd (mpd) when it uses ffmepg AVFormatContext() to get the tags from the wma file.
How about a new page for MutagenExamples? ? I'd contribute a simple image extractor:
#!/usr/bin/python import os import sys import locale from optparse import OptionParser def main(argv): from mutagen.id3 import ID3 parser = OptionParser() (options, args) = parser.parse_args(argv[1:]) if not args: raise SystemExit(parser.print_help() or 1) enc = locale.getpreferredencoding() for filename in args: print "--", filename try: f = ID3(filename); for frame in f.getall("APIC"): print frame.pprint().encode(enc, 'replace') ext = ".img" if (frame.mime == "image/jpeg") or (frame.mime == "image/jpg"): ext = ".jpg" if frame.mime == "image/png": ext = ".png" if frame.mime == "image/gif": ext = ".gif" (proot,pext) = os.path.splitext(filename) imgfilename = proot + ext if os.path.exists(imgfilename) : print "File " + imgfilename + " exists. Skipping!" else: print "Writing image to " + imgfilename + " !" myfile = file(imgfilename, 'wb') myfile.write(frame.data) myfile.close() except AttributeError: print "- Unknown file type" except KeyboardInterrupt: raise except Exception, err: print str(err) print main(sys.argv)I'd like a way to determine if there is an id3v1 tag, even when an id3v2 tag is also present. For example, mutagen.id3.ID3.version will return (2,3,0) when both v1 and v2 tags are present. Any suggestions on how to check if an id3v1 tag is also there? Thanks.
What about COMM tags? As it is now, it converts only tags starting with T, but COMM too can contain text. I personally did something like this to make it work on my MP3s, but have no idea if it makes sense:
Index: mid3iconv =================================================================== --- mid3iconv (revision 4351) +++ mid3iconv (working copy) @@ -62,9 +62,9 @@ print str(err) continue - for tag in filter(lambda t: t.startswith("T"), id3): + for tag in id3: frame = id3[tag] - if isinstance(frame, mutagen.id3.TimeStampTextFrame): # non-unicode fields + if isinstance(frame, mutagen.id3.TimeStampTextFrame) or not hasattr(frame, "text"): # non-unicode fields continue try:Is there any way to read data from an MP3 file that is already in memory, stored in a file-like object? I've managed to pass the object to MPEGInfo just fine, but have been unable to do so for MP3 - which has made retrieving the ID3 information kind of difficult.