You are not logged in.
Pages: 1
#!/usr/bin/env python
import glob
import multiprocessing
import argparse
import os
import subprocess
import taglib
srcpath=destpath=srcextlist=destext=codec=bitrate=force=''
def process_args():
parser = argparse.ArgumentParser(description='Recompress music library files using ffmpeg. Copies directory tree, file names, most tags, etc. Useful for making a copy of your music library to put on a device.')
parser.add_argument('--srcpath', type=str, dest='srcpath', default='/mnt/media/wutai/Music/archive/artists/', help="root directory of the original files.")
parser.add_argument('--destpath',type=str, dest='destpath',default='/mnt/media/wutai/Music/opus_b64/artists/', help="destination directory for transcoded files.")
parser.add_argument('--srcextlist',type=str, dest='srcextlist', default='.flac,.opus.ogg,.mp4,.m4a,.mp3,.aac', help="comma separated list of file extensions that should be transcoded - Default is \".flac,.opus.ogg,.mp4,.m4a,.mp3,.aac\"")
parser.add_argument('--destext', type=str, dest='destext', default='.opus.ogg', help="file extension to use for transcoded files. - Note: ffmpeg uses this to choose the container format, and it should be something that plays nice with the --codec you specify. e.g. Use .m4a or .aac for aac, .ogg for vorbis, .opus.ogg for libopus, etc.\nDefault: .opus.ogg")
parser.add_argument('--force', type=bool,dest='force', default=False, help="pass this argument to force overwrite existing files - (existing files will be skipped (i.e. not transcoded)\nDefault: No. ")
parser.add_argument('--codec', type=str, dest='codec', default='libopus', help="audio codec to use for transcoding. e.g. libopus, libfdk_aac, libvorbis. See man ffmpeg-codecs, section AUDIO ENCODERS, for a full list of possible options.\nDefault: libopus")
parser.add_argument('--bitrate', type=str, dest='bitrate', default='64k', help="Nominal bitrate of transcoded file, e.g. 64k corresponds to 64kbps. Higher bitrates lead to better quality and larger file size. \nDefault: 64k.")
parser.add_argument('--quality', type=str, dest='quality', default=-1, help="Quality factor of the file, for codecs that support it (such as vorbis). Else set to -1 and it won't be used. \nDefault: -1.")
return parser.parse_args()
def compress(filepath):
global donesize
global totalsize
oldpath = filepath
newpath = oldpath.replace(srcpath,destpath)
newpath = newpath.replace(os.path.splitext(filepath)[1],destext)
dirpath = newpath.rsplit('/',1)[0]
os.makedirs(dirpath,exist_ok=True)
ot = taglib.File(oldpath).tags
# Form metadata string
metadata = ""
for tag in ['GENRE','DATE','TRACKNUMBER','ALBUM','ARTIST','TITLE','LABEL','ALBUMARTIST','ARTISTSORT','COMPOSER','DISCNUMBER','ORIGINALDATE','PERFORMER','PERFORMERS']:
if tag in ot:
for item in ot[tag]:
metadata = "{} -metadata {}=\"{}\"".format(metadata,tag.lower(),item)
# If file doesn't already exist (or if it does and force overwrite is enabled)
if not os.path.isfile(newpath) or force==True:
print ('Converting {0}'.format(oldpath))
buf = ''
if quality > 0: # used by vorbis
buf = '-qscale:a {}'.format(quality)
else:
buf = '-b:a {}'.format(bitrate)
command = 'ffmpeg -loglevel quiet -i \"{src}\" {metadata} -sn -vn -c:a {codec} {buf} \"{dest}\"'.format(src=oldpath,dest=newpath,codec=codec,metadata=metadata,buf=buf)
subprocess.call(command,shell=True)
else:
#pass
print ('Skipping {0}'.format(oldpath))
size = os.path.getsize(oldpath)
try:
with donesize.get_lock():
donesize.value = donesize.value + size
print("Percent Complete: {percent:.4%}".format(percent=donesize.value/totalsize.value))
except:
print("An exception occurred instead.")
raise
donesize = None
totalsize = None
def init(adonesize,atotalsize):
''' store the counter for later use '''
global donesize
global totalsize
donesize = adonesize
totalsize = atotalsize
if __name__ == '__main__':
try:
args = process_args()
srcpath = args.srcpath
srcextlist = args.srcextlist
destpath = args.destpath
destext = args.destext
force = args.force
codec = args.codec
bitrate = args.bitrate
quality = args.quality
biglist = []
donesize = multiprocessing.Value('L',0)
totalsize = multiprocessing.Value('L',0)
print('Creating list.')
for srcext in srcextlist.split(','):
biglist.extend(glob.iglob('{}/**/*{}'.format(srcpath,srcext),recursive=True))
biglist.sort()
totalsize.value = sum(os.path.getsize(name) for name in biglist)
print('Getting Started.')
pool = multiprocessing.Pool(initializer=init, initargs=(donesize,totalsize,))
pool.imap(compress,biglist)
pool.close()
pool.join()
except (KeyboardInterrupt, SystemExit):
raise
except:
raise
finally:
print("Bye.\n\n")
Something I wrote a while back. Maybe someone else will find it useful too.
Last edited by dwidmann (2018-10-04 06:37:13)
"I refuse to be part of a society that encourages the rampant abuse of its own language." ~ BM
Offline
that should go to this thread https://bbs.archlinux.org/viewtopic.php?id=56646
if you gonna post in Community Contributions at least have same basic documentation
https://ugjka.net
"It is easier to fool people, than to convince them that they've been fooled" ~ Dr. Andrea Love
Offline
Pages: 1