[linux-audio-user] ardour and mp3?

rob rob at curates-egg.org
Sun Feb 4 06:29:12 EST 2007


Matt Price wrote:
> convert the files to mp3 one at a time when I want to, but I wonder if
> there's a more fluid way of e.g. converting files when they're uploaded,
> or at least converting all files in a particular folder or something.
> are there other people out there who have to deal with a similar
> situation?
>   
I hacked up this python script to transcode from wav/mp3/ogg/flac to 
wav/mp3/flac/ogg.

HTH
R
-------------- next part --------------
#!/usr/bin/python

# Copyright Rob Fell, 2007.

import sys
import string
import os
import os.path
import string
import shutil
import tempfile

from subprocess import *

best = False

def GetFlacInfo( meta, f ):
	cmd = "metaflac --show-sample-rate --show-tag=artist --show-tag=album --show-tag=title --show-tag=tracknumber --show-tag=date %s"
	p = Popen(  cmd % f, shell=True, stdout=PIPE, stderr=PIPE )

	artist = album = year = song = tracknum = rate = None

	for field in p.communicate()[0].split('\n'):
		
		sep = field.find('=')
		if sep > 0:
			key = field[0:sep].lower().lstrip()
			value = field[sep+1:]

			if key == 'artist':
				artist = value
			if key == 'album':
				album = value
			if key == 'title':
				song = value
			if key == 'tracknumber':
				tracknum = int( value )
			if key == 'date':
				year = value
		else:
			str = ""
			for ch in field.lstrip():
				if ch.isdigit():
					str += ch
				else:
					break
			if str:
				rate = int( str )

	if song:	meta['song'].append( song )
	if artist:	meta['artist'].append( artist )
	if album:	meta['album'].append( album )
	if tracknum:	meta['tracknum'].append( tracknum )
	if year:	meta['date'].append( year )
	if rate:	meta['rate'].append( rate )


def GetOggInfo( meta, f ):
	p = Popen( "ogginfo %s" % f, shell=True, stdout=PIPE )

	artist = album = year = song = tracknum = rate = None

	for field in p.communicate()[0].split('\n'):
		sep = field.find('=')
		if sep > 0:
			key = field[0:sep].lower().lstrip()
			value = field[sep+1:]

			if key == 'artist':
				artist = value
			if key == 'album':
				album = value
			if key == 'title':
				song = value
			if key == 'tracknumber':
				tracknum = int( value )
			if key == 'date':
				year = value
		else:
			if 'Rate:' in field:
				rate = int( field.split(' ')[1] )

	if song:	meta['song'].append( song )
	if artist:	meta['artist'].append( artist )
	if album:	meta['album'].append( album )
	if tracknum:	meta['tracknum'].append( tracknum )
	if year:	meta['date'].append( year )
	if rate:	meta['rate'].append( rate )


def GetID3Info( meta, f ):
	p = Popen( "id3info %s" % f, shell=True, stdout=PIPE )

	artist = album = year = song = tracknum = rate = None

	for field in p.communicate()[0].split('\n'):

		if 'Frequency' in field:
			freq = field.split(':')[-1].lstrip().lower()
			if '44khz' == freq:
				rate = 44100
			elif '48khz' == freq:
				rate = 48000

		if not field[0:3] == '===':
			continue

		key = field[4:8]

		if key == 'TIT2':
			song = field.split(':')[-1].lstrip()
		elif key == 'TPE1':
			artist = field.split(':')[-1].lstrip()
		elif key == 'TALB':
			album = field.split(':')[-1].lstrip()
		elif key == 'TRCK':
			tracknum = int( field.split(':')[-1] )
		elif key == 'TYER':
			year = int( field.split(':')[-1] )

	if song:	meta['song'].append( song )
	if artist:	meta['artist'].append( artist )
	if album:	meta['album'].append( album )
	if tracknum:	meta['tracknum'].append( tracknum )
	if year:	meta['date'].append( year )
	if rate:	meta['rate'].append( rate )

def GetMetadata( ftype, f ):

	meta = { 'artist' : [],
		 'album' : [],
		 'date' : [],
		 'tracknum' : [],
		 'song' : [],
		 'rate' : [] }

	if ftype == 'riff':
		return None

	if ftype == 'flac':
		GetFlacInfo( meta, f )

	if ftype == 'ogg':
		GetOggInfo( meta, f )

	GetID3Info( meta, f )

	if not meta['tracknum']:
		tracknum = ""
		for ch in os.path.basename( f ):
			if ch.isdigit():
				tracknum += ch
			else:
				break
		if tracknum:
			meta['tracknum'].append( int( tracknum ))

	return meta


def DetermineFileType( f ):

	idtable = [ 	(('MPEG', 'layer III'), ('mp3')),
			(('RIFF', 'PCM', 'Microsoft'), ('riff')),
			(('Ogg', 'Vorbis'), ('ogg')) ]

	# 'file' misidentifies flac files as MP3's, so we use metaflac
	# to see if it IS a flac file first
	#
	is_flac = Popen( "metaflac --list %s" % f, shell=True, stdout=PIPE, stderr=PIPE ).wait() == 0

	if is_flac:
		ftype = 'flac'
	else:
		# now fall back to normal 'file' identification
		#
		p = Popen( "file %s" % f, shell=True, stdout=PIPE )

		info = p.communicate()[0]

		ftype = None

		for rule, tag in idtable:
			ftype = tag
			for str in rule:
				if str not in info:
					ftype = None
					break
			if ftype:
				break

	return ftype


def Flac2Wav( src, dst ):
	return Popen( "flac123 --wav=%s %s" % (dst, src), shell=True, stdout=PIPE ).wait()

def Wav2Flac( src, dst, meta ):
	cmd = "flac"
	args = ""

	if meta:
		if meta['song']:
			args += ' -T "title=%s"' % meta['song'][0]

		if meta['artist']:
			args += ' -T "artist=%s"' % meta['artist'][0]

		if meta['album']:
			args += ' -T "album=%s"' % meta['album'][0]

		if meta['date']:
			args += ' -T "date=%s"' % meta['date'][0]

		if meta['tracknum']:
			args += ' -T "tracknumber=%d"' % meta['tracknum'][0]

	if args:
		cmd += " %s %s %s" % (args, src, dst)
	else:
		cmd += " %s %s" % (src, dst)

	return Popen( cmd , shell=True, stdout=PIPE ).wait()


def Ogg2Wav( src, dst ):
	return Popen( "oggdec -o %s %s" % (dst, src), shell=True, stdout=PIPE ).wait()

def Wav2Ogg( src, dst, meta ):
	if best:
		cmd = "oggenc -q 10"
	else:
		cmd = "oggenc -q 7"
	args = ""

	if meta:
		if meta['song']:
			args += ' -t "%s"' % meta['song'][0]

		if meta['artist']:
			args += ' -a "%s"' % meta['artist'][0]

		if meta['album']:
			args += ' -l "%s"' % meta['album'][0]

		if meta['date']:
			args += ' -d "%s"' % meta['date'][0]

		if meta['tracknum']:
			args += ' -N %d' % meta['tracknum'][0]

	if args:
		cmd += " %s -o %s %s" % (args, dst, src)
	else:
		cmd += " -o %s %s" % (dst, src)

	print cmd
	return Popen( cmd , shell=True, stdout=PIPE ).wait()


def Mp32Wav( src, dst ):
	return Popen( "mpg123 -w %s %s" % (dst, src), shell=True, stdout=PIPE ).wait()

def Wav2Mp3( src, dst, meta ):
	if best:
		cmd = "lame -V 0 -h "
	else:
		cmd = "lame -V 4 -h"
	args = ""

	if meta:
		if meta['song']:
			args += ' --tt "%s"' % meta['song'][0]

		if meta['artist']:
			args += ' --ta "%s"' % meta['artist'][0]

		if meta['album']:
			args += ' --tl "%s"' % meta['album'][0]

		if meta['date']:
			args += ' --ty "%s"' % meta['date'][0]

		if meta['tracknum']:
			args += ' --tn %d' % meta['tracknum'][0]

	if args:
		cmd += " %s %s %s" % (args, src, dst)
	else:
		cmd += " %s %s" % (src, dst)

	return Popen( cmd , shell=True, stdout=PIPE ).wait()


def NewName( f, meta, type ):

	types = { 'riff':'wav', 'flac':'flac', 'ogg':'ogg', 'mp3':'mp3' }

	if type not in types.keys():
		return None

	if meta and meta['song']:
		if meta['tracknum']:
			song = "".join( [ x for x in meta['song'][0].split(' ')] )
			name = "%02d%s" % (meta['tracknum'][0], song)
			trans = string.maketrans( '', '' )
			return ".".join( [string.translate( name, trans, ':,\\/.!\"$%^&*()+=-\'_ ' ), types[type]] )
	else:
		name = os.path.splitext( os.path.basename( f ))[0]
		trans = string.maketrans( '', '' )
		return ".".join( [string.translate( name, trans, ':,\\/.!\"$%^&*()+=\' ' ), types[type]] )

def Transcode( src, dst, meta ):
	srcFmt, srcFile = src
	dstFmt, dstFile = dst

	decoders = { 	'flac': Flac2Wav,
			'ogg' : Ogg2Wav,
			'mp3' : Mp32Wav,
			'riff': None }

	encoders = {	'flac': Wav2Flac,
			'ogg' : Wav2Ogg,
			'mp3' : Wav2Mp3,
			'riff': None }

	if os.path.isfile( dstFile ):
		raise "refusing to overwrite %s" % dstFile

	if not os.path.isdir( os.path.dirname( dstFile )):
		raise "directory %s does not exist" % os.path.dirname( dstFile )

	if srcFmt == dstFmt:
		# only a copy required
		#
		print "Copying %s to %s" % ( srcFile, dstFile )
		shutil.copyfile( srcFile, dstFile )
	else:
		handle, tempname = tempfile.mkstemp( '.wav', 'pyxcode', '/tmp' )
		os.close(handle)
		decode = decoders[srcFmt]
		encode = encoders[dstFmt]

		if not decode:
			shutil.copyfile( srcFile, tempname )
		else:
			decode( srcFile, tempname )

		if not encode:
			shutil.copyfile( tempname, dstFile )
		else:
			encode( tempname, dstFile, meta )

		os.remove(tempname)

	print "Converted %s" % os.path.basename( srcFile )

def Usage():
	print """
exec.py --odir=path --fmt=[flac|wav|riff|ogg|mp3] [--best] file [file...]
"""
	sys.exit(1)

if __name__ == "__main__":

	files = []
	odir = None
	fmt = None

	args = sys.argv[1:]
	for arg in args:
		if arg[0:2] == '--':
			opt = arg[2:]
			sep = opt.find('=')
			if sep > 0:
				key = opt[0:sep]
				value = opt[sep+1:]
				if   key == 'odir':
					odir = value
				elif key == 'fmt':
					if value == 'wav':
						value = 'riff'
					fmt = value
				else:
					Usage()
			else:
				if opt == 'best':
					best = True
				else:
					Usage()
		else:
			files.append( arg )

	if not odir or not fmt:
		Usage()

	for f in files:
		if os.path.isfile( f ):
			ftype = DetermineFileType( f )
			if ftype:
				meta = GetMetadata( ftype, f )

				src = ( ftype, f )
				dst = ( fmt, os.path.join( odir, NewName( f, meta, fmt ) ) )

				ret = Transcode( src, dst, meta )
				if ret:
					print ret


More information about the linux-audio-user mailing list