March 31, 2008

Convert iTunes M4A Files to MP3, With an Easy-To-Use GUI

Filed under: Linux — bnsmith @ 9:29 pm

A few months ago, I described the steps needed to convert DRM-free iTunes M4A files into MP3 files using Ubuntu Linux. The procedure worked, but was more difficult than it should be, so now I’ve built a GUI front-end. No command-line typing is required!

How to Convert M4A Files to MP3 Files

Step 1: Enable Additional Software Repositories

  • Click on System -> Administration -> Software Sources (You may need to enter your administration password)


  • Check the “Community-maintained Open Source software (universe)” and “Software restricted by copyright or legal issues (multiverse)” repositories


  • Click Close
  • Click Reload on the pop-up window

Step 2: Download and Install the Conversion Program


  • Ensure that the Open with option is selected; click OK (You may need to enter your administration password)
  • Click the Install Package button
  • When the install process is complete, close the pop-up and the installer program

Step 3: Convert Some Music Files

  • Click on Applications -> Sound & Video -> Convert To MP3
  • Click the Browse… button in the Directory to Convert box
  • Find the directory containing your M4A files and click Open; the program should now look something like this:


  • Click on the Begin Converting button

It will likely take about thirty seconds to convert each file. If you find a bug, please either post a comment here or report it on the Google Code Project page. I’m also happy to implement new features, if you have any ideas.

Technical Details

It seems to me that making the GUI took just as long as making the actual conversion script, if not longer. I spent a lot of time experimenting with different GUI systems. I tried out Dabo, and was leaning heavily towards using it for this project. Unfortunately, as I worked with the IDE, I encountered a few frustrating usability issues that kept me from embracing it fully. Notice that I said “usability issues” instead of “bugs”. The software wasn’t buggy at all, and I think that the Dabo people should really be proud of what they’ve accomplished. It just needs to be a bit… simpler. Simple is better than complex.

I discarded QT for the same reason. Perhaps if I need a more powerful GUI system in the future, I’ll consider looking at it again.

In the end, I decided to go for wxPython with wxGlade to graphically design the layout. I really appreciate both the simplicity of this system, as well as the attractiveness of the result. It isn’t perfect, of course. I wish that the wxWidgets toolkit had an available control that was like a tabbed notebook, but without any tabs and controlled programatically. I know that there are several workarounds, but I would still like to see one of the workarounds integrated into the toolkit.

This is also the first time that I’ve created a Debian package. The process was more difficult than I’d hoped but easier than I’d feared. It was very time-consuming to boot my computer with the Ubuntu 7.10 live CD, try to install the package, find that I’d missed a dependency or something, go back and fix it and then repeat the whole process again. Still, it could have been a lot worse. I probably would have given up my packaging effort if not for this video.

Anyway, if you have any questions about creating GUIs or Debian packages for Ubuntu, leave a comment and I’ll help if I can.



  1. Is the Directory to Convert the itl file that itunes uses to keep track of the music or the file with the music?

    Comment by Sash — May 1, 2008 @ 9:04 am

  2. You should choose the folder that has the music in it (usually named “iTunes Music”), not the itl file.

    Comment by bnsmith — May 1, 2008 @ 10:01 pm

  3. Thanks a lot, a very usefull software.

    Comment by Fabio Assolini — July 10, 2008 @ 9:47 pm

  4. Hello,
    great tool, works easy and fast.
    One “Bug”.. it doesnt convert the id-tag year, which should be possible.

    Also it should be possible to change the bitrate or lame-options (but thats of course an humble feature request..)


    Comment by Thomas — August 4, 2008 @ 1:55 pm

  5. Thank you for a very simpel and easy to use program! 🙂

    Comment by Tobias — August 6, 2008 @ 12:21 pm

  6. Brad, I so much appreciate all your work on this. Unfortunately, I was not able to install the package, because I am using the 64-bit version of Ubuntu 8.04. I’m guessing that this may be simply a setting in the package, and it may be that I can override it somehow, but I’m enough of a Linux newbie to be unsure about how or whether to attempt that. Any help will be greatly appreciated!

    Comment by Andy — August 21, 2008 @ 9:18 pm

  7. Fabio, Thomas and Tobias, thank-you so much for your support. I’m glad that I could help.

    Andy, I looked into my deb package settings, and I set the “Architecture” to “any” in the control file. I think this means that it should install on the 64-bit version. Of course, I’m really not a deb-packaging expert. Perhaps you could paste the error message that you’re getting into a comment. Maybe one of the libraries that I depend on requires x86?

    Comment by bnsmith — August 23, 2008 @ 5:48 pm

  8. Crap! I accidentally closed it after running for two days! Is there any way I can resume it without it converting the ones I already did?

    Comment by Crashmaxx — September 23, 2008 @ 6:40 pm

  9. Crashmaxx, try doing the conversion with the command-line only version described here:

    You should be able to specify the same source and destination directories and it will skip ones that have already been converted.

    Comment by bnsmith — September 24, 2008 @ 10:01 am

  10. Hi. Very nice tool. Thangs for coding. I made a patch which adds the tags year and comment:

    — 2008-09-30 14:52:57.000000000 +0200
    +++ 2008-09-30 14:59:29.000000000 +0200
    @@ -94,7 +94,7 @@
    if not os.path.isdir(os.path.split(dest)[0]):

    – title = artist = album = track = genre = “”
    + title = artist = album = track = genre = year = comment = “”
    tagInfo = MP4(src)
    title = getTag(tagInfo, ‘\xa9nam’)
    @@ -102,6 +102,8 @@
    album = getTag(tagInfo, ‘\xa9alb’)
    track = getTag(tagInfo, ‘trkn’)
    genre = getTag(tagInfo, ‘\xa9gen’)
    + year = getTag(tagInfo, ‘\xa9day’)
    + comment = getTag(tagInfo, ‘\xa9cmt’)

    except MP4StreamInfoError:
    errstrings.append(“ERROR: The file ‘” + src + “‘ seems to have invalid song information tags. Unfortunately, this means that the resulting MP3 file will not have embedded tags.”)
    @@ -128,7 +130,10 @@
    subprocess.check_call([u’id3v2′, u’-T’, track, dest])
    if genre != “”:
    subprocess.check_call([u’id3v2′, u’-g’, genre, dest])

    + if year != “”:
    + subprocess.check_call([u’id3v2′, u’-y’, year, dest])
    + if genre != “”:
    + subprocess.check_call([u’id3v2′, u’-c’, comment, dest])

    if os.path.isfile(wav):

    Comment by moxx — September 30, 2008 @ 8:30 am

  11. Thanks for the patch moxx! A new deb package with support for comment and year tags is now available for download from the link in the article above. Let me know if there are any problems.

    Comment by bnsmith — October 8, 2008 @ 3:49 pm

  12. Just downloaded and installed ConvertToMP3. Ran a folder of M4A files through it – worked a treat! Thanks for all your hard work on this, and for making it freely available.

    Comment by Tom — December 4, 2008 @ 3:51 pm

  13. just to say thanks for all the hard work you put into this – I’ve been looking for something like this for a while now 🙂 a credit to the OSS community

    Comment by dave — April 28, 2009 @ 5:11 am

  14. Thank you 🙂 this is absolutely awesome, this is the kind of thing I knew I’d benefit from being in a FOSS community. Awesome, hope I can give back to you soon!

    Comment by jzacsh — January 21, 2010 @ 3:53 pm

  15. Oh — I haven’t coded anything outside of small course projects yet, but is there a reason you didn’t just boot in a virtual machine? (instead of booting a LiveCD on your PC?

    Comment by jzacsh — January 21, 2010 @ 3:56 pm

  16. Works great…thanks for all the time you put into it. I’m converting 4 gig of itune files over as I write

    Comment by Lee — August 30, 2010 @ 9:29 pm

  17. thank you SO much! 🙂

    Comment by Jenn — August 25, 2011 @ 10:51 pm

  18. Hi, I find that on an iOS 5 iphone, purchases made directly from the itunes store to the phone don’t have ID3 tags on the m4a files. All the metadata is stored in the associated plist file. When using the command line version of, the mp3 files that are produced have no tags at all.

    I wrote the attached python util to tag them. You pass it the names of all the .plist files, and it extracts the tag values, figures out which .mp3 goes with which .plist, and tags it. I couldn’t figure out the libplist python bindings so I just call “plutil” to get the XML and use ElementTree to process that into a dict.

    Thanks for your script! Do whatever you like with my util, I place it in the public domain.

    Bill Gribble

    import xml.etree.ElementTree as etree
    from subprocess import check_output
    import sys

    from mutagen.id3 import ID3, TIT2, TPE1, TALB, TRCK, TCON, TIT1, TYER, COMM

    def read_file(fname):
    stdout_data = check_output([“plutil”, “-i”, fname])
    x = etree.XML(stdout_data)
    props = read_dict(x[0])
    return props

    def read_dict(elt):
    props = {}
    key = None
    for item in elt:
    if item.tag == “key”:
    key = item.text
    elif item.tag == “dict”:
    props[key] = read_dict(item)
    props[key] = item.text
    return props

    def main():
    for f in sys.argv[1:]:
    print f
    props = read_file(f)
    mediafile = props.get(‘’, {}).get(‘mediaAssetFilename’)
    if mediafile is not None:
    print “Tagging %s from %s:” % (mediafile, f)
    print props
    tags = ID3()
    tags.add(TIT2(encoding=3, text=unicode(props.get(‘itemName’))))
    tags.add(TPE1(encoding=3, text=unicode(props.get(‘artistName’))))
    tags.add(TALB(encoding=3, text=unicode(props.get(‘playlistName’))))
    tags.add(TYER(encoding=3, text=unicode(props.get(‘year’))))
    tags.add(TCON(encoding=3, text=unicode(props.get(‘genreId’))))
    tags.add(TRCK(encoding=3, text=unicode(“%s/%s” % (props.get(‘trackNumber’),
    print tags“m4a”, “mp3”))


    Comment by Bill Gribble — December 31, 2011 @ 3:21 pm

  19. Oops, sorry about the formatting. Indentation should be pretty obvious…

    Comment by Bill Gribble — December 31, 2011 @ 3:23 pm

RSS feed for comments on this post.

Blog at

%d bloggers like this: