[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Re: iTunes Lib. to Ogg



CRASSlogic:
> 
> My question is; is there a way (here in Debian, Sarge) to convert my
> iTunes library (currently 20.8GB) to Ogg Vorbis? I can't find a batch
> encoder or similar myself, having spent quite some time on google.

While there surely is a way to do that, I don't think this is the right
thing to do[tm]. With the help of a little shell script, it should be
possible to decode your AAC files to wav and then use oggenc (if oggenc
cannot handle AAC directly, which I don't know). But your files will
probably suffer from considerable loss of quality. AAC is a "lossy"
format and when you reencode it again into another lossy format, you
will lose even more quality.

I agree that Vorbis is a great format and I prefer it whenever I can.
But I don't think that encoding to Vorbis from another lossy format
gains you anything. I would only do this if I don't have the original
source and either the sound file's quality is irrelevant (e.g. if it is
speech) or my files are in a format which my portable MP3 player cannot
play.

The "cleanest" and most future-proof solution would be to re-rip all of
the songs you have on CD and encode them to FLAC, a lossless format
which is just as free as Vorbis. From FLAC you can encode to any format
you want and archive the FLAC files in case you need the music in a
different format. But apparently this is a lot of work, takes a lot of
storage (about half the size of the music in wav format) and you need
the originals.

I did exactly this with the majority of my CD collection and wrote a
script to re-encode an entire tree of files into another format into a
separate directory tree, mirroring the structure of the original tree.
It's neither well tested nor commented, though, and it doesn't handle
AAC yet. But it should be quite easy to extend it to different formats.
You just have to provide an encoding command and extend the list of
supported input formats for your target format.

J.
-- 
My drug of choice is self-pity.
[Agree]   [Disagree]
                 <http://www.slowlydownward.com/NODATA/data_enter2.html>
#!/usr/bin/python2.4

import os, sys, glob, subprocess
from optparse import OptionParser

# this map contains the supported input formats for every output format.
valid_input_formats = { 'ogg': ('flac', 'wav', 'aif', 'aiff'),
                        'mp3': ('wav', 'aif', 'aiff'),
                        'flac': ('wav', 'aif', 'aiff')}

# this map contains the command that can be used to encode
# to a specific output format.
enc_commands = { 'ogg':  'oggenc %(source)s -q6 -o %(dest)s',
                 'mp3':  'lame --preset standard %(source)s %(dest)s',
                 'flac': 'flac --replay-gain -o %(dest)s %(source)s'}

source_dir = None
dest_dir = None

def parse_options():
    usage = "usage: \%prog [options] srcdir destdir"
    parser = OptionParser(usage=usage, version='%prog 0.0')
    parser.add_option('-f', '--format', default='ogg',
            help="Output format [default=%default]")
    parser.add_option('-e', '--ext', default=None,
            help="comma-separated list of file extensions to process")
    parser.add_option('-v', '--verbose', action='store_true', dest='verbose',
            help="Print encoder messages to stdout (default).")
    parser.add_option('-q', '--quiet', action='store_false', dest='verbose',
            help="Suppress normal output (default: unset).")
    parser.set_defaults(verbose=True)
    global options
    (options, args) = parser.parse_args()

    if options.format not in enc_commands.keys():
        parser.error("""Given output format unknown.\n
Sorry, I don't know how to encode to %s.""" % options.format)

    if len(args) != 2:
        parser.error("""Incorrect number of arguments.
You have to supply a source and a destination directory.""")
    else:
        global source_dir, dest_dir
        source_dir, dest_dir = args

    if not options.ext:
        options.ext = valid_input_formats[options.format]
    elif isinstance(options.ext, basestring):
        options.ext = options.ext.split(',')

    for ext in options.ext[:]:
        if ext not in valid_input_formats[options.format]:
            print """Don't know how to convert %s to %s.
Ignoring this filetype.""" % (ext, options.format)
            options.ext.remove(ext)
    if not options.ext:
        parser.error("""List of filetypes to process is empty. Nothing to do.""")

    if not os.path.isdir(source_dir):
        parser.error("Source path is not a directory.")
    if not os.path.isdir(dest_dir):
        os.makedirs(dest_dir)
        print "Created destination directory %s." % dest_dir

def encode(filename):
    dest_filename = os.path.splitext(filename)[0] + '.%s' % options.format
    dest_filename = dest_filename.replace(source_dir, dest_dir)
    command = enc_commands[options.format] % \
              { 'source': filename, 'dest': dest_filename }
    if not os.path.isdir(os.path.dirname(dest_filename)):
        os.makedirs(os.path.dirname(dest_filename))
    retval = subprocess.call(command.split())
    if retval:
        sys.stderr.write("""Error processing file %s.
Trying next one.""" % filename)

def main():
    parse_options()
    tree = os.walk(source_dir)
    for dirpath, dirnames, filenames in tree:
        print "Entering %s" % dirpath
        files = []
        for ext in options.ext:
            pattern = os.path.join(dirpath, '*.%s' % ext)
            files = glob.glob(pattern)
            for filename in (os.path.abspath(f) for f in files):
                encode(filename)

if __name__ == '__main__':
    main()

Attachment: signature.asc
Description: Digital signature


Reply to: