From: W. Trevor King Date: Tue, 16 Nov 2010 13:43:59 +0000 (-0500) Subject: Add mkogg post. X-Git-Url: http://git.tremily.us/?a=commitdiff_plain;h=e0037890c969028eccd8263161b8569b5217d1aa;p=blog.git Add mkogg post. --- diff --git a/posts/mkogg.mdwn b/posts/mkogg.mdwn new file mode 100644 index 0000000..0b00b48 --- /dev/null +++ b/posts/mkogg.mdwn @@ -0,0 +1,25 @@ +[[!meta title="mkogg"]] + +I keep my music organized by Genre→Artist→Album→Song and try to keep +as much as possible in [FLAC][] format. When it comes time to wedge +this music onto a smaller device, I want to recode the music in [Ogg +Vorbis][]. [SoX][] is a useful tool for converting between all sorts +of audio formats, but I wanted the ability to excercise a bit more +control over maintaning metadata (e.g. via [metaflac][], [id3v2][], +etc.). To this end, I've put together a little [[Python]] script, +[[mkogg.py]], which mirrors a source directory of mixed-format music +as Ogg-encoded files (or other formats via `--target-extension`) in a +target directory. + +You can use the [[cdrtools]] to burn CD with your recoded music. + +[FLAC]: http://flac.sourceforge.net/ +[Ogg Vorbis]: http://www.vorbis.com/ +[SoX]: http://sox.sourceforge.net/ +[metaflac]: http://flac.sourceforge.net/documentation_tools_metaflac.html +[id3v2]: http://id3v2.sourceforge.net/ +[MP3]: http://en.wikipedia.org/wiki/MP3 + +[[!tag tags/code]] +[[!tag tags/fun]] +[[!tag tags/python.mdwn]] diff --git a/posts/mkogg/mkogg.py b/posts/mkogg/mkogg.py new file mode 100755 index 0000000..76755c7 --- /dev/null +++ b/posts/mkogg/mkogg.py @@ -0,0 +1,123 @@ +#!/usr/bin/env python +# +# Copyright (C) 2009-2010 W. Trevor King +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this program. If not, see +# . + +"""Mirror a tree of mp3/ogg/flac files with ogg-vorbis versions +""" + +import shutil +from subprocess import Popen, PIPE +from tempfile import mkstemp +import os +import os.path + + +class Converter (object): + def __init__(self, source_dir, target_dir, target_extension='ogg'): + self.source_dir = source_dir + self.target_dir = target_dir + self._source_extensions = ['flac', 'mp3', 'ogg', 'wav'] + self._target_extension = target_extension + f,self._tempfile = mkstemp(prefix='mkogg-') + + def cleanup(self): + os.remove(self._tempfile) + + def _makedirs(self, target_dir): + if not os.path.exists(target_dir): + os.makedirs(target_dir) + + def run(self): + self._makedirs(self.target_dir) + for dirpath,dirnames,filenames in os.walk(self.source_dir): + for filename in filenames: + root,ext = os.path.splitext(filename) + ext = ext.lower() + if ext.startswith('.'): + ext = ext[1:] + if ext not in self._source_extensions: + print 'skip', filename, ext + continue + source_path = os.path.join(dirpath, filename) + rel_path = os.path.relpath(dirpath, self.source_dir) + target_path = os.path.join( + self.target_dir, rel_path, + '%s.%s' % (root, self._target_extension)) + target_dir = os.path.dirname(target_path) + self._makedirs(target_dir) + self._convert(source_path, target_path, ext) + + def _convert(self, source, target, ext): + print 'convert %s to %s' % (source, target) + if ext == self._target_extension: + shutil.copy(source, target) + else: + convert = getattr(self, 'convert_%s_to_%s' + % (ext, self._target_extension)) + convert(source, target) + + def convert_flac_to_mp3(self, source, target): + self.convert_flac_to_wav(source, self._tempfile) + self.convert_wav_to_mp3(self._tempfile, target) + + def convert_flac_to_wav(self, source, target): + p = Popen(['ogg123', '--quiet', '-d', 'wav', '-f', target, source]) + p.wait() + + def convert_flac_to_ogg(self, source, target): + p = Popen(['oggenc', '-q', '3', source, '-o', target]) + p.wait() + + def convert_mp3_to_ogg(self, source, target): + self.convert_mp3_to_wav(source, self._tempfile) + self.convert_wav_to_ogg(self._tempfile, target) + + def convert_mp3_to_wav(self, source, target): + p = Popen(['mpg123', source, '-w', target]) + p.wait() + + def convert_ogg_to_mp3(self, source, target): + self.convert_flac_to_mp3(source, target) + + def convert_ogg_to_wav(self, source, target): + self.convert_flac_to_wav(source_target) + + def convert_wav_to_mp3(self, source, target): + p = Popen(['lame', '--silent', '-V', '4', source, target]) + p.wait() + + def convert_wav_to_ogg(self, source, target): + self.convert_flac_to_ogg(source, target) + + +if __name__ == '__main__': + import optparse + + p = optparse.OptionParser('%prog [options] source-dir target-dir') + p.add_option('-t', '--target-extension', dest='ext', + default='ogg', metavar='EXT', + help='Conversion target type (e.g. flac, mp3) (%default)') + + options,args = p.parse_args() + source_dir,target_dir = args + + c = Converter(source_dir, target_dir, target_extension=options.ext) + try: + c.run() + finally: + #c.cleanup() + pass