def encode(albumPath): # Return if xld details not found if XLD: global xldProfile (xldProfile, xldFormat, xldBitrate) = getXldProfile.getXldProfile(headphones.XLDPROFILE) if not xldFormat: logger.error('Details for xld profile \'%s\' not found, files will not be re-encoded', xldProfile) return None tempDirEncode=os.path.join(albumPath,"temp") musicFiles=[] musicFinalFiles=[] musicTempFiles=[] encoder = "" # Create temporary directory, but remove the old one first. try: if os.path.exists(tempDirEncode): shutil.rmtree(tempDirEncode) time.sleep(1) os.mkdir(tempDirEncode) except Exception, e: logger.exception("Unable to create temporary directory") return None
def encode(albumPath): # Return if xld details not found if XLD: global xldProfile (xldProfile, xldFormat, xldBitrate) = getXldProfile.getXldProfile(headphones.XLDPROFILE) if not xldFormat: logger.error( 'Details for xld profile \'%s\' not found, files will not be re-encoded', xldProfile) return None tempDirEncode = os.path.join(albumPath, "temp") musicFiles = [] musicFinalFiles = [] musicTempFiles = [] encoder = "" # Create temporary directory, but remove the old one first. try: if os.path.exists(tempDirEncode): shutil.rmtree(tempDirEncode) time.sleep(1) os.mkdir(tempDirEncode) except Exception, e: logger.exception("Unable to create temporary directory") return None
downloaded_track_list.append(os.path.join(r, files)) elif files.lower().endswith('.cue'): downloaded_cuecount += 1 # if any of the files end in *.part, we know the torrent isn't done yet. Process if forced, though elif files.lower().endswith('.part') and not forced: logger.info("Looks like " + os.path.basename(albumpath).decode(headphones.SYS_ENCODING, 'replace') + " isn't complete yet. Will try again on the next run") return # use xld to split cue if headphones.ENCODER == 'xld' and headphones.MUSIC_ENCODER and downloaded_cuecount and downloaded_cuecount >= len(downloaded_track_list): import getXldProfile (xldProfile, xldFormat, xldBitrate) = getXldProfile.getXldProfile(headphones.XLDPROFILE) if not xldFormat: logger.info(u'Details for xld profile "%s" not found, cannot split cue' % (xldProfile)) else: if headphones.ENCODERFOLDER: xldencoder = os.path.join(headphones.ENCODERFOLDER, 'xld') else: xldencoder = os.path.join('/Applications','xld') for r,d,f in os.walk(albumpath): xldfolder = r xldfile = '' xldcue = '' for file in f: if any(file.lower().endswith('.' + x.lower()) for x in headphones.MEDIA_FORMATS) and not xldfile: xldfile = os.path.join(r, file)
def encode(albumPath): use_xld = headphones.CONFIG.ENCODER == 'xld' # Return if xld details not found if use_xld: (xldProfile, xldFormat, xldBitrate) = getXldProfile.getXldProfile( headphones.CONFIG.XLDPROFILE) if not xldFormat: logger.error('Details for xld profile \'%s\' not found, files will not be re-encoded', xldProfile) return None else: xldProfile = None tempDirEncode = os.path.join(albumPath, "temp") musicFiles = [] musicFinalFiles = [] musicTempFiles = [] encoder = "" # Create temporary directory, but remove the old one first. try: if os.path.exists(tempDirEncode): shutil.rmtree(tempDirEncode) time.sleep(1) os.mkdir(tempDirEncode) except Exception as e: logger.exception("Unable to create temporary directory") return None for r, d, f in os.walk(albumPath): for music in f: if any(music.lower().endswith('.' + x.lower()) for x in headphones.MEDIA_FORMATS): if not use_xld: encoderFormat = headphones.CONFIG.ENCODEROUTPUTFORMAT.encode( headphones.SYS_ENCODING) else: xldMusicFile = os.path.join(r, music) xldInfoMusic = MediaFile(xldMusicFile) encoderFormat = xldFormat if headphones.CONFIG.ENCODERLOSSLESS: ext = os.path.normpath(os.path.splitext(music)[1].lstrip(".")).lower() if not use_xld and ext == 'flac' or use_xld and ( ext != xldFormat and (xldInfoMusic.bitrate / 1000 > 400)): musicFiles.append(os.path.join(r, music)) musicTemp = os.path.normpath( os.path.splitext(music)[0] + '.' + encoderFormat) musicTempFiles.append(os.path.join(tempDirEncode, musicTemp)) else: logger.debug('%s is already encoded', music) else: musicFiles.append(os.path.join(r, music)) musicTemp = os.path.normpath(os.path.splitext(music)[0] + '.' + encoderFormat) musicTempFiles.append(os.path.join(tempDirEncode, musicTemp)) if headphones.CONFIG.ENCODER_PATH: encoder = headphones.CONFIG.ENCODER_PATH.encode(headphones.SYS_ENCODING) else: if use_xld: encoder = os.path.join('/Applications', 'xld') elif headphones.CONFIG.ENCODER == 'lame': if headphones.SYS_PLATFORM == "win32": # NEED THE DEFAULT LAME INSTALL ON WIN! encoder = "C:/Program Files/lame/lame.exe" else: encoder = "lame" elif headphones.CONFIG.ENCODER == 'ffmpeg': if headphones.SYS_PLATFORM == "win32": encoder = "C:/Program Files/ffmpeg/bin/ffmpeg.exe" else: encoder = "ffmpeg" elif headphones.CONFIG.ENCODER == 'libav': if headphones.SYS_PLATFORM == "win32": encoder = "C:/Program Files/libav/bin/avconv.exe" else: encoder = "avconv" i = 0 encoder_failed = False jobs = [] for music in musicFiles: infoMusic = MediaFile(music) encode = False if use_xld: if xldBitrate and (infoMusic.bitrate / 1000 <= xldBitrate): logger.info('%s has bitrate <= %skb, will not be re-encoded', music.decode(headphones.SYS_ENCODING, 'replace'), xldBitrate) else: encode = True elif headphones.CONFIG.ENCODER == 'lame': if not any( music.decode(headphones.SYS_ENCODING, 'replace').lower().endswith('.' + x) for x in ["mp3", "wav"]): logger.warn('Lame cannot encode %s format for %s, use ffmpeg', os.path.splitext(music)[1], music) else: if music.decode(headphones.SYS_ENCODING, 'replace').lower().endswith('.mp3') and ( int(infoMusic.bitrate / 1000) <= headphones.CONFIG.BITRATE): logger.info('%s has bitrate <= %skb, will not be re-encoded', music, headphones.CONFIG.BITRATE) else: encode = True else: if headphones.CONFIG.ENCODEROUTPUTFORMAT == 'ogg': if music.decode(headphones.SYS_ENCODING, 'replace').lower().endswith('.ogg'): logger.warn('Cannot re-encode .ogg %s', music.decode(headphones.SYS_ENCODING, 'replace')) else: encode = True else: if music.decode(headphones.SYS_ENCODING, 'replace').lower().endswith('.' + headphones.CONFIG.ENCODEROUTPUTFORMAT) and (int(infoMusic.bitrate / 1000) <= headphones.CONFIG.BITRATE): logger.info('%s has bitrate <= %skb, will not be re-encoded', music, headphones.CONFIG.BITRATE) else: encode = True # encode if encode: job = (encoder, music, musicTempFiles[i], albumPath, xldProfile) jobs.append(job) else: musicFiles[i] = None musicTempFiles[i] = None i = i + 1 # Encode music files if len(jobs) > 0: processes = 1 # Use multicore if enabled if headphones.CONFIG.ENCODER_MULTICORE: if headphones.CONFIG.ENCODER_MULTICORE_COUNT == 0: processes = multiprocessing.cpu_count() else: processes = headphones.CONFIG.ENCODER_MULTICORE_COUNT logger.debug("Multi-core encoding enabled, spawning %d processes", processes) # Use multiprocessing only if it's worth the overhead. and if it is # enabled. If not, then use the old fashioned way. if processes > 1: with logger.listener(): pool = multiprocessing.Pool(processes=processes) results = pool.map_async(command_map, jobs) # No new processes will be created, so close it and wait for all # processes to finish pool.close() pool.join() # Retrieve the results results = results.get() else: results = map(command_map, jobs) # The results are either True or False, so determine if one is False encoder_failed = not all(results) musicFiles = filter(None, musicFiles) musicTempFiles = filter(None, musicTempFiles) # check all files to be encoded now exist in temp directory if not encoder_failed and musicTempFiles: for dest in musicTempFiles: if not os.path.exists(dest): encoder_failed = True logger.error("Encoded file '%s' does not exist in the destination temp directory", dest) # No errors, move from temp to parent if not encoder_failed and musicTempFiles: i = 0 for dest in musicTempFiles: if os.path.exists(dest): source = musicFiles[i] if headphones.CONFIG.DELETE_LOSSLESS_FILES: os.remove(source) check_dest = os.path.join(albumPath, os.path.split(dest)[1]) if os.path.exists(check_dest): os.remove(check_dest) try: shutil.move(dest, albumPath) except Exception as e: logger.error('Could not move %s to %s: %s', dest, albumPath, e) encoder_failed = True break i += 1 # remove temp directory shutil.rmtree(tempDirEncode) # Return with error if any encoding errors if encoder_failed: logger.error( "One or more files failed to encode. Ensure you have the latest version of %s installed.", headphones.CONFIG.ENCODER) return None time.sleep(1) for r, d, f in os.walk(albumPath): for music in f: if any(music.lower().endswith('.' + x.lower()) for x in headphones.MEDIA_FORMATS): musicFinalFiles.append(os.path.join(r, music)) if not musicTempFiles: logger.info('Encoding for folder \'%s\' is not required', albumPath) return musicFinalFiles
for files in f: if any(files.lower().endswith('.' + x.lower()) for x in headphones.MEDIA_FORMATS): downloaded_track_list.append(os.path.join(r, files)) elif files.lower().endswith('.cue'): downloaded_cuecount += 1 # use xld to split cue if headphones.ENCODER == 'xld' and headphones.MUSIC_ENCODER and downloaded_cuecount and downloaded_cuecount >= len( downloaded_track_list): import getXldProfile (xldProfile, xldFormat, xldBitrate) = getXldProfile.getXldProfile(headphones.XLDPROFILE) if not xldFormat: logger.info( u'Details for xld profile "%s" not found, cannot split cue' % (xldProfile)) else: if headphones.ENCODERFOLDER: xldencoder = os.path.join(headphones.ENCODERFOLDER, 'xld') else: xldencoder = os.path.join('/Applications', 'xld') for r, d, f in os.walk(albumpath): xldfolder = r xldfile = '' xldcue = '' for file in f:
def encode(albumPath): # Return if xld details not found if XLD: global xldProfile (xldProfile, xldFormat, xldBitrate) = getXldProfile.getXldProfile(headphones.XLDPROFILE) if not xldFormat: logger.error(u'Details for xld profile %s not found, files will not be re-encoded' % (xldProfile)) return None tempDirEncode=os.path.join(albumPath,"temp") musicFiles=[] musicFinalFiles=[] musicTempFiles=[] encoder ="" if not os.path.exists(tempDirEncode): os.mkdir(tempDirEncode) else: shutil.rmtree(tempDirEncode) time.sleep(1) os.mkdir(tempDirEncode) for r,d,f in os.walk(albumPath): for music in f: if any(music.lower().endswith('.' + x.lower()) for x in headphones.MEDIA_FORMATS): if not XLD: encoderFormat = headphones.ENCODEROUTPUTFORMAT.encode(headphones.SYS_ENCODING) else: xldMusicFile = os.path.join(r, music) xldInfoMusic = MediaFile(xldMusicFile) encoderFormat = xldFormat if (headphones.ENCODERLOSSLESS): ext = os.path.normpath(os.path.splitext(music)[1].lstrip(".")).lower() if not XLD and ext == 'flac' or XLD and (ext != xldFormat and (xldInfoMusic.bitrate / 1000 > 400)): musicFiles.append(os.path.join(r, music)) musicTemp = os.path.normpath(os.path.splitext(music)[0] + '.' + encoderFormat) musicTempFiles.append(os.path.join(tempDirEncode, musicTemp)) else: logger.debug('%s is already encoded' % (music)) else: musicFiles.append(os.path.join(r, music)) musicTemp = os.path.normpath(os.path.splitext(music)[0] + '.' + encoderFormat) musicTempFiles.append(os.path.join(tempDirEncode, musicTemp)) if headphones.ENCODER_PATH: encoder = headphones.ENCODER_PATH.encode(headphones.SYS_ENCODING) else: if XLD: encoder = os.path.join('/Applications', 'xld') elif headphones.ENCODER =='lame': if headphones.SYS_PLATFORM == "win32": ## NEED THE DEFAULT LAME INSTALL ON WIN! encoder = "C:/Program Files/lame/lame.exe" else: encoder="lame" elif headphones.ENCODER =='ffmpeg': if headphones.SYS_PLATFORM == "win32": encoder = "C:/Program Files/ffmpeg/bin/ffmpeg.exe" else: encoder="ffmpeg" i=0 encoder_failed = False for music in musicFiles: infoMusic=MediaFile(music) encode = False if XLD: if xldBitrate and (infoMusic.bitrate / 1000 <= xldBitrate): logger.info('%s has bitrate <= %skb, will not be re-encoded' % (music.decode(headphones.SYS_ENCODING, 'replace'), xldBitrate)) else: encode = True elif headphones.ENCODER == 'lame': if not any(music.decode(headphones.SYS_ENCODING, 'replace').lower().endswith('.' + x) for x in ["mp3", "wav"]): logger.warn(u'Lame cannot encode %s format for %s, use ffmpeg' % (os.path.splitext(music)[1].decode(headphones.SYS_ENCODING, 'replace'),music.decode(headphones.SYS_ENCODING, 'replace'))) else: if (music.decode(headphones.SYS_ENCODING, 'replace').lower().endswith('.mp3') and (int(infoMusic.bitrate / 1000) <= headphones.BITRATE)): logger.info('%s has bitrate <= %skb, will not be re-encoded' % (music.decode(headphones.SYS_ENCODING, 'replace'),headphones.BITRATE)) else: encode = True else: if headphones.ENCODEROUTPUTFORMAT=='ogg': if music.decode(headphones.SYS_ENCODING, 'replace').lower().endswith('.ogg'): logger.warn('Cannot re-encode .ogg %s' % (music.decode(headphones.SYS_ENCODING, 'replace'))) else: encode = True elif (headphones.ENCODEROUTPUTFORMAT=='mp3' or headphones.ENCODEROUTPUTFORMAT=='m4a'): if (music.decode(headphones.SYS_ENCODING, 'replace').lower().endswith('.'+headphones.ENCODEROUTPUTFORMAT) and (int(infoMusic.bitrate / 1000 ) <= headphones.BITRATE)): logger.info('%s has bitrate <= %skb, will not be re-encoded' % (music.decode(headphones.SYS_ENCODING, 'replace'),headphones.BITRATE)) else: encode = True # encode if encode: if not command(encoder,music,musicTempFiles[i],albumPath): encoder_failed = True break else: musicFiles[i] = None musicTempFiles[i] = None i=i+1 musicFiles = filter(None, musicFiles) musicTempFiles = filter(None, musicTempFiles) # check all files to be encoded now exist in temp directory if not encoder_failed and musicTempFiles: for dest in musicTempFiles: if not os.path.exists(dest): encoder_failed = True logger.error('Encoded file %s does not exist in the destination temp directory' % (dest.decode(headphones.SYS_ENCODING, 'replace'))) # No errors, move from temp to parent if not encoder_failed and musicTempFiles: i = 0 for dest in musicTempFiles: if os.path.exists(dest): source = musicFiles[i] if headphones.DELETE_LOSSLESS_FILES: os.remove(source) check_dest = os.path.join(albumPath, os.path.split(dest)[1]) if os.path.exists(check_dest): os.remove(check_dest) try: shutil.move(dest, albumPath) except Exception, e: logger.error('Could not move %s to %s : %s' % (dest.decode(headphones.SYS_ENCODING, 'replace'), albumPath.decode(headphones.SYS_ENCODING, 'replace'), e)) encoder_failed = True break i += 1
def encode(albumPath): # Return if xld details not found if XLD: global xldProfile (xldProfile, xldFormat, xldBitrate) = getXldProfile.getXldProfile(headphones.XLDPROFILE) if not xldFormat: logger.error( u'Details for xld profile %s not found, files will not be re-encoded' % (xldProfile)) return None tempDirEncode = os.path.join(albumPath, "temp") musicFiles = [] musicFinalFiles = [] musicTempFiles = [] encoder = "" if not os.path.exists(tempDirEncode): os.mkdir(tempDirEncode) else: shutil.rmtree(tempDirEncode) time.sleep(1) os.mkdir(tempDirEncode) for r, d, f in os.walk(albumPath): for music in f: if any(music.lower().endswith('.' + x.lower()) for x in headphones.MEDIA_FORMATS): if not XLD: encoderFormat = headphones.ENCODEROUTPUTFORMAT.encode( headphones.SYS_ENCODING) else: xldMusicFile = os.path.join(r, music) xldInfoMusic = MediaFile(xldMusicFile) encoderFormat = xldFormat if (headphones.ENCODERLOSSLESS): ext = os.path.normpath( os.path.splitext(music)[1].lstrip(".")).lower() if not XLD and ext == 'flac' or XLD and ( ext != xldFormat and (xldInfoMusic.bitrate / 1000 > 400)): musicFiles.append(os.path.join(r, music)) musicTemp = os.path.normpath( os.path.splitext(music)[0] + '.' + encoderFormat) musicTempFiles.append( os.path.join(tempDirEncode, musicTemp)) else: logger.debug('%s is already encoded' % (music)) else: musicFiles.append(os.path.join(r, music)) musicTemp = os.path.normpath( os.path.splitext(music)[0] + '.' + encoderFormat) musicTempFiles.append( os.path.join(tempDirEncode, musicTemp)) if headphones.ENCODER_PATH: encoder = headphones.ENCODER_PATH.encode(headphones.SYS_ENCODING) else: if XLD: encoder = os.path.join('/Applications', 'xld') elif headphones.ENCODER == 'lame': if headphones.SYS_PLATFORM == "win32": ## NEED THE DEFAULT LAME INSTALL ON WIN! encoder = "C:/Program Files/lame/lame.exe" else: encoder = "lame" elif headphones.ENCODER == 'ffmpeg': if headphones.SYS_PLATFORM == "win32": encoder = "C:/Program Files/ffmpeg/bin/ffmpeg.exe" else: encoder = "ffmpeg" i = 0 encoder_failed = False for music in musicFiles: infoMusic = MediaFile(music) encode = False if XLD: if xldBitrate and (infoMusic.bitrate / 1000 <= xldBitrate): logger.info('%s has bitrate <= %skb, will not be re-encoded' % (music.decode(headphones.SYS_ENCODING, 'replace'), xldBitrate)) else: encode = True elif headphones.ENCODER == 'lame': if not any( music.decode(headphones.SYS_ENCODING, 'replace').lower().endswith('.' + x) for x in ["mp3", "wav"]): logger.warn( u'Lame cannot encode %s format for %s, use ffmpeg' % (os.path.splitext(music)[1].decode(headphones.SYS_ENCODING, 'replace'), music.decode(headphones.SYS_ENCODING, 'replace'))) else: if (music.decode(headphones.SYS_ENCODING, 'replace').lower().endswith('.mp3') and (int(infoMusic.bitrate / 1000) <= headphones.BITRATE)): logger.info( '%s has bitrate <= %skb, will not be re-encoded' % (music.decode(headphones.SYS_ENCODING, 'replace'), headphones.BITRATE)) else: encode = True else: if headphones.ENCODEROUTPUTFORMAT == 'ogg': if music.decode(headphones.SYS_ENCODING, 'replace').lower().endswith('.ogg'): logger.warn( 'Cannot re-encode .ogg %s' % (music.decode(headphones.SYS_ENCODING, 'replace'))) else: encode = True elif (headphones.ENCODEROUTPUTFORMAT == 'mp3' or headphones.ENCODEROUTPUTFORMAT == 'm4a'): if (music.decode(headphones.SYS_ENCODING, 'replace').lower( ).endswith('.' + headphones.ENCODEROUTPUTFORMAT) and (int(infoMusic.bitrate / 1000) <= headphones.BITRATE)): logger.info( '%s has bitrate <= %skb, will not be re-encoded' % (music.decode(headphones.SYS_ENCODING, 'replace'), headphones.BITRATE)) else: encode = True # encode if encode: if not command(encoder, music, musicTempFiles[i], albumPath): encoder_failed = True break else: musicFiles[i] = None musicTempFiles[i] = None i = i + 1 musicFiles = filter(None, musicFiles) musicTempFiles = filter(None, musicTempFiles) # check all files to be encoded now exist in temp directory if not encoder_failed and musicTempFiles: for dest in musicTempFiles: if not os.path.exists(dest): encoder_failed = True logger.error( 'Encoded file %s does not exist in the destination temp directory' % (dest.decode(headphones.SYS_ENCODING, 'replace'))) # No errors, move from temp to parent if not encoder_failed and musicTempFiles: i = 0 for dest in musicTempFiles: if os.path.exists(dest): source = musicFiles[i] if headphones.DELETE_LOSSLESS_FILES: os.remove(source) check_dest = os.path.join(albumPath, os.path.split(dest)[1]) if os.path.exists(check_dest): os.remove(check_dest) try: shutil.move(dest, albumPath) except Exception, e: logger.error( 'Could not move %s to %s : %s' % (dest.decode(headphones.SYS_ENCODING, 'replace'), albumPath.decode(headphones.SYS_ENCODING, 'replace'), e)) encoder_failed = True break i += 1
def split(albumpath): global CUE_META os.chdir(albumpath) base_dir = Directory(os.getcwd()) cue = None wave = None # determining correct cue file # if perfect match found for _cue in base_dir.filter('CueFile'): for _wave in base_dir.filter('WaveFile'): if _cue.header['file'] == _wave.name: logger.info('CUE Sheet found: %s', _cue.name) logger.info('Music file found: %s', _wave.name) cue = _cue wave = _wave # if no perfect match found then try without extensions if not cue and not wave: logger.info( 'No match for music files, trying to match without extensions...') for _cue in base_dir.filter('CueFile'): for _wave in base_dir.filter('WaveFile'): if ''.join(os.path.splitext( _cue.header['file'])[:-1]) == _wave.name_name: logger.info('Possible CUE Sheet found: %s', _cue.name) logger.info('CUE Sheet refers music file: %s', _cue.header['file']) logger.info('Possible Music file found: %s', _wave.name) cue = _cue wave = _wave cue.header['file'] = wave.name # if still no match then raise an exception if not cue and not wave: raise ValueError('No music file match found!') # Split with xld or shntool splitter = 'shntool' xldprofile = None # use xld profile to split cue if headphones.CONFIG.ENCODER == 'xld' and headphones.CONFIG.MUSIC_ENCODER and headphones.CONFIG.XLDPROFILE: import getXldProfile xldprofile, xldformat, _ = getXldProfile.getXldProfile( headphones.CONFIG.XLDPROFILE) if not xldformat: raise ValueError( 'Details for xld profile "%s" not found, cannot split cue' % (xldprofile)) else: if headphones.CONFIG.ENCODERFOLDER: splitter = os.path.join(headphones.CONFIG.ENCODERFOLDER, 'xld') else: splitter = 'xld' # use standard xld command to split cue elif sys.platform == 'darwin': splitter = 'xld' if not check_splitter(splitter): splitter = 'shntool' if splitter == 'shntool' and not check_splitter(splitter): raise ValueError('Command not found, ensure shntool or xld installed') # Determine if file can be split if wave.name_ext not in WAVE_FILE_TYPE_BY_EXTENSION.keys(): raise ValueError('Cannot split, audio file has unsupported extension') # Split with xld if 'xld' in splitter: cmd = [splitter] cmd.extend([wave.name]) cmd.extend(['-c']) cmd.extend([cue.name]) if xldprofile: cmd.extend(['--profile']) cmd.extend([xldprofile]) else: cmd.extend(['-f']) cmd.extend(['flac']) cmd.extend(['-o']) cmd.extend([base_dir.path]) split = split_baby(wave.name, cmd) else: # Split with shntool # generate temporary metafile describing the cue with open(ALBUM_META_FILE_NAME, mode='w') as meta_file: meta_file.write(cue.get_meta()) base_dir.content.append(MetaFile( os.path.abspath(ALBUM_META_FILE_NAME))) # check metafile for completeness if not base_dir.filter('MetaFile'): raise ValueError( 'Cue Meta file {0} missing!'.format(ALBUM_META_FILE_NAME)) else: CUE_META = base_dir.filter('MetaFile')[0] with open(SPLIT_FILE_NAME, mode='w') as split_file: split_file.write(cue.breakpoints()) if headphones.CONFIG.CUE_SPLIT_SHNTOOL_PATH: cmd = [ os.path.join(headphones.CONFIG.CUE_SPLIT_SHNTOOL_PATH, 'shntool') ] else: cmd = ['shntool'] cmd.extend(['split']) cmd.extend(['-f']) cmd.extend([SPLIT_FILE_NAME]) cmd.extend(['-o']) cmd.extend([wave.name_ext.lstrip('.')]) cmd.extend([wave.name]) split = split_baby(wave.name, cmd) os.remove(SPLIT_FILE_NAME) base_dir.update() # tag FLAC files if split and CUE_META.count_tracks() == len( base_dir.tracks(ext='.flac', split=True)): for t in base_dir.tracks(ext='.flac', split=True): logger.info('Tagging %s...', t.name) t.tag() # rename files if split and CUE_META.count_tracks() == len( base_dir.tracks(ext=wave.name_ext, split=True)): for t in base_dir.tracks(ext=wave.name_ext, split=True): if t.name != t.filename(): logger.info('Renaming %s to %s...', t.name, t.filename()) os.rename(t.name, t.filename()) os.remove(ALBUM_META_FILE_NAME) if not split: raise ValueError('Failed to split, check logs') else: # Rename original file os.rename(wave.name, wave.name + '.original') return True
def encode(albumPath): use_xld = headphones.CONFIG.ENCODER == 'xld' # Return if xld details not found if use_xld: (xldProfile, xldFormat, xldBitrate) = getXldProfile.getXldProfile(headphones.CONFIG.XLDPROFILE) if not xldFormat: logger.error('Details for xld profile \'%s\' not found, files will not be re-encoded', xldProfile) return None else: xldProfile = None tempDirEncode = os.path.join(albumPath, "temp") musicFiles = [] musicFinalFiles = [] musicTempFiles = [] encoder = "" # Create temporary directory, but remove the old one first. try: if os.path.exists(tempDirEncode): shutil.rmtree(tempDirEncode) time.sleep(1) os.mkdir(tempDirEncode) except Exception as e: logger.exception("Unable to create temporary directory") return None for r, d, f in os.walk(albumPath): for music in f: if any(music.lower().endswith('.' + x.lower()) for x in headphones.MEDIA_FORMATS): if not use_xld: encoderFormat = headphones.CONFIG.ENCODEROUTPUTFORMAT.encode(headphones.SYS_ENCODING) else: xldMusicFile = os.path.join(r, music) xldInfoMusic = MediaFile(xldMusicFile) encoderFormat = xldFormat if headphones.CONFIG.ENCODERLOSSLESS: ext = os.path.normpath(os.path.splitext(music)[1].lstrip(".")).lower() if not use_xld and ext == 'flac' or use_xld and (ext != xldFormat and (xldInfoMusic.bitrate / 1000 > 400)): musicFiles.append(os.path.join(r, music)) musicTemp = os.path.normpath(os.path.splitext(music)[0] + '.' + encoderFormat) musicTempFiles.append(os.path.join(tempDirEncode, musicTemp)) else: logger.debug('%s is already encoded', music) else: musicFiles.append(os.path.join(r, music)) musicTemp = os.path.normpath(os.path.splitext(music)[0] + '.' + encoderFormat) musicTempFiles.append(os.path.join(tempDirEncode, musicTemp)) if headphones.CONFIG.ENCODER_PATH: encoder = headphones.CONFIG.ENCODER_PATH.encode(headphones.SYS_ENCODING) else: if use_xld: encoder = os.path.join('/Applications', 'xld') elif headphones.CONFIG.ENCODER == 'lame': if headphones.SYS_PLATFORM == "win32": ## NEED THE DEFAULT LAME INSTALL ON WIN! encoder = "C:/Program Files/lame/lame.exe" else: encoder = "lame" elif headphones.CONFIG.ENCODER == 'ffmpeg': if headphones.SYS_PLATFORM == "win32": encoder = "C:/Program Files/ffmpeg/bin/ffmpeg.exe" else: encoder = "ffmpeg" elif headphones.CONFIG.ENCODER == 'libav': if headphones.SYS_PLATFORM == "win32": encoder = "C:/Program Files/libav/bin/avconv.exe" else: encoder = "avconv" i = 0 encoder_failed = False jobs = [] for music in musicFiles: infoMusic = MediaFile(music) encode = False if use_xld: if xldBitrate and (infoMusic.bitrate / 1000 <= xldBitrate): logger.info('%s has bitrate <= %skb, will not be re-encoded', music.decode(headphones.SYS_ENCODING, 'replace'), xldBitrate) else: encode = True elif headphones.CONFIG.ENCODER == 'lame': if not any(music.decode(headphones.SYS_ENCODING, 'replace').lower().endswith('.' + x) for x in ["mp3", "wav"]): logger.warn('Lame cannot encode %s format for %s, use ffmpeg', os.path.splitext(music)[1], music) else: if music.decode(headphones.SYS_ENCODING, 'replace').lower().endswith('.mp3') and (int(infoMusic.bitrate / 1000) <= headphones.CONFIG.BITRATE): logger.info('%s has bitrate <= %skb, will not be re-encoded', music, headphones.CONFIG.BITRATE) else: encode = True else: if headphones.CONFIG.ENCODEROUTPUTFORMAT == 'ogg': if music.decode(headphones.SYS_ENCODING, 'replace').lower().endswith('.ogg'): logger.warn('Cannot re-encode .ogg %s', music.decode(headphones.SYS_ENCODING, 'replace')) else: encode = True elif headphones.CONFIG.ENCODEROUTPUTFORMAT == 'mp3' or headphones.CONFIG.ENCODEROUTPUTFORMAT == 'm4a': if music.decode(headphones.SYS_ENCODING, 'replace').lower().endswith('.' + headphones.CONFIG.ENCODEROUTPUTFORMAT) and (int(infoMusic.bitrate / 1000) <= headphones.CONFIG.BITRATE): logger.info('%s has bitrate <= %skb, will not be re-encoded', music, headphones.CONFIG.BITRATE) else: encode = True # encode if encode: job = (encoder, music, musicTempFiles[i], albumPath, xldProfile) jobs.append(job) else: musicFiles[i] = None musicTempFiles[i] = None i = i + 1 # Encode music files if len(jobs) > 0: processes = 1 # Use multicore if enabled if headphones.CONFIG.ENCODER_MULTICORE: if headphones.CONFIG.ENCODER_MULTICORE_COUNT == 0: processes = multiprocessing.cpu_count() else: processes = headphones.CONFIG.ENCODER_MULTICORE_COUNT logger.debug("Multi-core encoding enabled, spawning %d processes", processes) # Use multiprocessing only if it's worth the overhead. and if it is # enabled. If not, then use the old fashioned way. if processes > 1: with logger.listener(): pool = multiprocessing.Pool(processes=processes) results = pool.map_async(command_map, jobs) # No new processes will be created, so close it and wait for all # processes to finish pool.close() pool.join() # Retrieve the results results = results.get() else: results = map(command_map, jobs) # The results are either True or False, so determine if one is False encoder_failed = not all(results) musicFiles = filter(None, musicFiles) musicTempFiles = filter(None, musicTempFiles) # check all files to be encoded now exist in temp directory if not encoder_failed and musicTempFiles: for dest in musicTempFiles: if not os.path.exists(dest): encoder_failed = True logger.error("Encoded file '%s' does not exist in the destination temp directory", dest) # No errors, move from temp to parent if not encoder_failed and musicTempFiles: i = 0 for dest in musicTempFiles: if os.path.exists(dest): source = musicFiles[i] if headphones.CONFIG.DELETE_LOSSLESS_FILES: os.remove(source) check_dest = os.path.join(albumPath, os.path.split(dest)[1]) if os.path.exists(check_dest): os.remove(check_dest) try: shutil.move(dest, albumPath) except Exception as e: logger.error('Could not move %s to %s: %s', dest, albumPath, e) encoder_failed = True break i += 1 # remove temp directory shutil.rmtree(tempDirEncode) # Return with error if any encoding errors if encoder_failed: logger.error("One or more files failed to encode. Ensure you have the latest version of %s installed.", headphones.CONFIG.ENCODER) return None time.sleep(1) for r, d, f in os.walk(albumPath): for music in f: if any(music.lower().endswith('.' + x.lower()) for x in headphones.MEDIA_FORMATS): musicFinalFiles.append(os.path.join(r, music)) if not musicTempFiles: logger.info('Encoding for folder \'%s\' is not required', albumPath) return musicFinalFiles
def encode(albumPath): # Return if xld details not found if XLD: global xldProfile (xldProfile, xldFormat, xldBitrate) = getXldProfile.getXldProfile(headphones.XLDPROFILE) if not xldFormat: logger.error(u'Details for xld profile "%s" not found, will not be reencoded' % (xldProfile)) return None tempDirEncode=os.path.join(albumPath,"temp") musicFiles=[] musicFinalFiles=[] musicTempFiles=[] encoder ="" startAlbumTime=time.time() ifencoded=0 if not os.path.exists(tempDirEncode): os.mkdir(tempDirEncode) else: shutil.rmtree(tempDirEncode) time.sleep(1) os.mkdir(tempDirEncode) for r,d,f in os.walk(albumPath): for music in f: if any(music.lower().endswith('.' + x.lower()) for x in headphones.MEDIA_FORMATS): if not XLD: encoderFormat = headphones.ENCODEROUTPUTFORMAT.encode(headphones.SYS_ENCODING) else: xldMusicFile = os.path.join(r, music) xldInfoMusic = MediaFile(xldMusicFile) encoderFormat = xldFormat if (headphones.ENCODERLOSSLESS): ext = os.path.normpath(os.path.splitext(music)[1].lstrip(".")).lower() if not XLD and ext == 'flac' or XLD and (ext != xldFormat and (xldInfoMusic.bitrate / 1000 > 500)): musicFiles.append(os.path.join(r, music)) musicTemp = os.path.normpath(os.path.splitext(music)[0] + '.' + encoderFormat) musicTempFiles.append(os.path.join(tempDirEncode, musicTemp)) else: logger.debug('Music "%s" is already encoded' % (music)) else: musicFiles.append(os.path.join(r, music)) musicTemp = os.path.normpath(os.path.splitext(music)[0] + '.' + encoderFormat) musicTempFiles.append(os.path.join(tempDirEncode, musicTemp)) if headphones.ENCODER_PATH: encoder = headphones.ENCODER_PATH.encode(headphones.SYS_ENCODING) else: if XLD: encoder = os.path.join('/Applications', 'xld') elif headphones.ENCODER =='lame': if headphones.SYS_PLATFORM == "win32": ## NEED THE DEFAULT LAME INSTALL ON WIN! encoder = "C:/Program Files/lame/lame.exe" else: encoder="lame" elif headphones.ENCODER =='ffmpeg': if headphones.SYS_PLATFORM == "win32": encoder = "C:/Program Files/ffmpeg/bin/ffmpeg.exe" else: encoder="ffmpeg" i=0 for music in musicFiles: infoMusic=MediaFile(music) if XLD: if xldBitrate and (infoMusic.bitrate / 1000 <= xldBitrate): logger.info('Music "%s" has bitrate <= "%skbit", will not be reencoded' % (music.decode(headphones.SYS_ENCODING, 'replace'), xldBitrate)) else: command(encoder,music,musicTempFiles[i],albumPath) ifencoded=1 elif headphones.ENCODER == 'lame': if not any(music.decode(headphones.SYS_ENCODING, 'replace').lower().endswith('.' + x) for x in ["mp3", "wav"]): logger.warn(u'Lame cant encode "%s" format for "%s", use ffmpeg' % (os.path.splitext(music)[1].decode(headphones.SYS_ENCODING, 'replace'),music.decode(headphones.SYS_ENCODING, 'replace'))) else: if (music.decode(headphones.SYS_ENCODING, 'replace').lower().endswith('.mp3') and (int(infoMusic.bitrate/1000)<=headphones.BITRATE)): logger.info('Music "%s" has bitrate<="%skbit" will not be reencoded' % (music.decode(headphones.SYS_ENCODING, 'replace'),headphones.BITRATE)) else: command(encoder,music,musicTempFiles[i],albumPath) ifencoded=1 else: if headphones.ENCODEROUTPUTFORMAT=='ogg': if music.decode(headphones.SYS_ENCODING, 'replace').lower().endswith('.ogg'): logger.warn('Can not reencode .ogg music "%s"' % (music.decode(headphones.SYS_ENCODING, 'replace'))) else: command(encoder,music,musicTempFiles[i],albumPath) ifencoded=1 elif (headphones.ENCODEROUTPUTFORMAT=='mp3' or headphones.ENCODEROUTPUTFORMAT=='m4a'): if (music.decode(headphones.SYS_ENCODING, 'replace').lower().endswith('.'+headphones.ENCODEROUTPUTFORMAT) and (int(infoMusic.bitrate/1000)<=headphones.BITRATE)): logger.info('Music "%s" has bitrate<="%skbit" will not be reencoded' % (music.decode(headphones.SYS_ENCODING, 'replace'),headphones.BITRATE)) else: command(encoder,music,musicTempFiles[i],albumPath) ifencoded=1 i=i+1 shutil.rmtree(tempDirEncode) time.sleep(1) for r,d,f in os.walk(albumPath): for music in f: if any(music.lower().endswith('.' + x.lower()) for x in headphones.MEDIA_FORMATS): musicFinalFiles.append(os.path.join(r, music)) if ifencoded==0: logger.info('Encoding for folder "%s" is not needed' % (albumPath.decode(headphones.SYS_ENCODING, 'replace'))) return musicFinalFiles
def encode(albumPath): # Return if xld details not found if XLD: global xldProfile (xldProfile, xldFormat, xldBitrate) = getXldProfile.getXldProfile(headphones.XLDPROFILE) if not xldFormat: logger.error( u'Details for xld profile "%s" not found, will not be reencoded' % (xldProfile)) return None tempDirEncode = os.path.join(albumPath, "temp") musicFiles = [] musicFinalFiles = [] musicTempFiles = [] encoder = "" startAlbumTime = time.time() ifencoded = 0 if not os.path.exists(tempDirEncode): os.mkdir(tempDirEncode) else: shutil.rmtree(tempDirEncode) time.sleep(1) os.mkdir(tempDirEncode) for r, d, f in os.walk(albumPath): for music in f: if any(music.lower().endswith('.' + x.lower()) for x in headphones.MEDIA_FORMATS): if not XLD: encoderFormat = headphones.ENCODEROUTPUTFORMAT.encode( headphones.SYS_ENCODING) else: xldMusicFile = os.path.join(r, music) xldInfoMusic = MediaFile(xldMusicFile) encoderFormat = xldFormat if (headphones.ENCODERLOSSLESS): ext = os.path.normpath( os.path.splitext(music)[1].lstrip(".")).lower() if not XLD and ext == 'flac' or XLD and ( ext != xldFormat and (xldInfoMusic.bitrate / 1000 > 500)): musicFiles.append(os.path.join(r, music)) musicTemp = os.path.normpath( os.path.splitext(music)[0] + '.' + encoderFormat) musicTempFiles.append( os.path.join(tempDirEncode, musicTemp)) else: logger.debug('Music "%s" is already encoded' % (music)) else: musicFiles.append(os.path.join(r, music)) musicTemp = os.path.normpath( os.path.splitext(music)[0] + '.' + encoderFormat) musicTempFiles.append( os.path.join(tempDirEncode, musicTemp)) if XLD: if headphones.ENCODERFOLDER: encoder = os.path.join( headphones.ENCODERFOLDER.encode(headphones.SYS_ENCODING), 'xld') else: encoder = os.path.join('/Applications', 'xld') elif headphones.ENCODER == 'lame': encoder = os.path.join( headphones.ENCODERFOLDER.encode(headphones.SYS_ENCODING), 'lame') elif headphones.ENCODER == 'ffmpeg': encoder = os.path.join( headphones.ENCODERFOLDER.encode(headphones.SYS_ENCODING), 'ffmpeg') i = 0 for music in musicFiles: infoMusic = MediaFile(music) if XLD: if xldBitrate and (infoMusic.bitrate / 1000 <= xldBitrate): logger.info( 'Music "%s" has bitrate <= "%skbit", will not be reencoded' % (music.decode(headphones.SYS_ENCODING, 'replace'), xldBitrate)) else: command(encoder, music, musicTempFiles[i], albumPath) ifencoded = 1 elif headphones.ENCODER == 'lame': if not any( music.decode(headphones.SYS_ENCODING, 'replace').lower().endswith('.' + x) for x in ["mp3", "wav"]): logger.warn( u'Lame cant encode "%s" format for "%s", use ffmpeg' % (os.path.splitext(music)[1].decode(headphones.SYS_ENCODING, 'replace'), music.decode(headphones.SYS_ENCODING, 'replace'))) else: if (music.decode(headphones.SYS_ENCODING, 'replace').lower().endswith('.mp3') and (int(infoMusic.bitrate / 1000) <= headphones.BITRATE)): logger.info( 'Music "%s" has bitrate<="%skbit" will not be reencoded' % (music.decode(headphones.SYS_ENCODING, 'replace'), headphones.BITRATE)) else: command(encoder, music, musicTempFiles[i], albumPath) ifencoded = 1 else: if headphones.ENCODEROUTPUTFORMAT == 'ogg': if music.decode(headphones.SYS_ENCODING, 'replace').lower().endswith('.ogg'): logger.warn( 'Can not reencode .ogg music "%s"' % (music.decode(headphones.SYS_ENCODING, 'replace'))) else: command(encoder, music, musicTempFiles[i], albumPath) ifencoded = 1 elif (headphones.ENCODEROUTPUTFORMAT == 'mp3' or headphones.ENCODEROUTPUTFORMAT == 'm4a'): if (music.decode(headphones.SYS_ENCODING, 'replace').lower( ).endswith('.' + headphones.ENCODEROUTPUTFORMAT) and (int(infoMusic.bitrate / 1000) <= headphones.BITRATE)): logger.info( 'Music "%s" has bitrate<="%skbit" will not be reencoded' % (music.decode(headphones.SYS_ENCODING, 'replace'), headphones.BITRATE)) else: command(encoder, music, musicTempFiles[i], albumPath) ifencoded = 1 i = i + 1 shutil.rmtree(tempDirEncode) time.sleep(1) for r, d, f in os.walk(albumPath): for music in f: if any(music.lower().endswith('.' + x.lower()) for x in headphones.MEDIA_FORMATS): musicFinalFiles.append(os.path.join(r, music)) if ifencoded == 0: logger.info('Encoding for folder "%s" is not needed' % (albumPath.decode(headphones.SYS_ENCODING, 'replace'))) return musicFinalFiles
def split(albumpath): global CUE_META os.chdir(albumpath) base_dir = Directory(os.getcwd()) cue = None wave = None # determining correct cue file # if perfect match found for _cue in base_dir.filter('CueFile'): for _wave in base_dir.filter('WaveFile'): if _cue.header['file'] == _wave.name: logger.info('CUE Sheet found: %s', _cue.name) logger.info('Music file found: %s', _wave.name) cue = _cue wave = _wave # if no perfect match found then try without extensions if not cue and not wave: logger.info('No match for music files, trying to match without extensions...') for _cue in base_dir.filter('CueFile'): for _wave in base_dir.filter('WaveFile'): if ''.join(os.path.splitext(_cue.header['file'])[:-1]) == _wave.name_name: logger.info('Possible CUE Sheet found: %s', _cue.name) logger.info('CUE Sheet refers music file: %s', _cue.header['file']) logger.info('Possible Music file found: %s', _wave.name) cue = _cue wave = _wave cue.header['file'] = wave.name # if still no match then raise an exception if not cue and not wave: raise ValueError('No music file match found!') # Split with xld or shntool splitter = 'shntool' xldprofile = None # use xld profile to split cue if headphones.CONFIG.ENCODER == 'xld' and headphones.CONFIG.MUSIC_ENCODER and headphones.CONFIG.XLDPROFILE: import getXldProfile xldprofile, xldformat, _ = getXldProfile.getXldProfile(headphones.CONFIG.XLDPROFILE) if not xldformat: raise ValueError( 'Details for xld profile "%s" not found, cannot split cue' % (xldprofile)) else: if headphones.CONFIG.ENCODERFOLDER: splitter = os.path.join(headphones.CONFIG.ENCODERFOLDER, 'xld') else: splitter = 'xld' # use standard xld command to split cue elif sys.platform == 'darwin': splitter = 'xld' if not check_splitter(splitter): splitter = 'shntool' if splitter == 'shntool' and not check_splitter(splitter): raise ValueError('Command not found, ensure shntool or xld installed') # Determine if file can be split if wave.name_ext not in WAVE_FILE_TYPE_BY_EXTENSION.keys(): raise ValueError('Cannot split, audio file has unsupported extension') # Split with xld if 'xld' in splitter: cmd = [splitter] cmd.extend([wave.name]) cmd.extend(['-c']) cmd.extend([cue.name]) if xldprofile: cmd.extend(['--profile']) cmd.extend([xldprofile]) else: cmd.extend(['-f']) cmd.extend(['flac']) cmd.extend(['-o']) cmd.extend([base_dir.path]) split = split_baby(wave.name, cmd) else: # Split with shntool # generate temporary metafile describing the cue with open(ALBUM_META_FILE_NAME, mode='w') as meta_file: meta_file.write(cue.get_meta()) base_dir.content.append(MetaFile(os.path.abspath(ALBUM_META_FILE_NAME))) # check metafile for completeness if not base_dir.filter('MetaFile'): raise ValueError('Cue Meta file {0} missing!'.format(ALBUM_META_FILE_NAME)) else: CUE_META = base_dir.filter('MetaFile')[0] with open(SPLIT_FILE_NAME, mode='w') as split_file: split_file.write(cue.breakpoints()) if headphones.CONFIG.CUE_SPLIT_SHNTOOL_PATH: cmd = [os.path.join(headphones.CONFIG.CUE_SPLIT_SHNTOOL_PATH, 'shntool')] else: cmd = ['shntool'] cmd.extend(['split']) cmd.extend(['-f']) cmd.extend([SPLIT_FILE_NAME]) cmd.extend(['-o']) cmd.extend([wave.name_ext.lstrip('.')]) cmd.extend([wave.name]) split = split_baby(wave.name, cmd) os.remove(SPLIT_FILE_NAME) base_dir.update() # tag FLAC files if split and CUE_META.count_tracks() == len(base_dir.tracks(ext='.flac', split=True)): for t in base_dir.tracks(ext='.flac', split=True): logger.info('Tagging %s...', t.name) t.tag() # rename files if split and CUE_META.count_tracks() == len(base_dir.tracks(ext=wave.name_ext, split=True)): for t in base_dir.tracks(ext=wave.name_ext, split=True): if t.name != t.filename(): logger.info('Renaming %s to %s...', t.name, t.filename()) os.rename(t.name, t.filename()) os.remove(ALBUM_META_FILE_NAME) if not split: raise ValueError('Failed to split, check logs') else: # Rename original file os.rename(wave.name, wave.name + '.original') return True
def command(encoder, musicSource, musicDest, albumPath): """ Encode a given music file with a certain encoder. Returns True on success, or False otherwise. """ use_xld = headphones.CONFIG.ENCODER == 'xld' startMusicTime = time.time() cmd = [] # Return if xld details not found if use_xld: (xldProfile, xldFormat, xldBitrate) = getXldProfile.getXldProfile( headphones.CONFIG.XLDPROFILE) if not xldFormat: logger.error( 'Details for xld profile \'%s\' not found, files will not be re-encoded', xldProfile) return None xldDestDir = os.path.split(musicDest)[0] cmd = [encoder] cmd.extend([musicSource]) cmd.extend(['--profile']) cmd.extend([xldProfile]) cmd.extend(['-o']) cmd.extend([xldDestDir]) # Lame elif headphones.CONFIG.ENCODER == 'lame': cmd = [encoder] opts = [] if not headphones.CONFIG.ADVANCEDENCODER: opts.extend(['-h']) if headphones.CONFIG.ENCODERVBRCBR == 'cbr': opts.extend([ '--resample', str(headphones.CONFIG.SAMPLINGFREQUENCY), '-b', str(headphones.CONFIG.BITRATE) ]) elif headphones.CONFIG.ENCODERVBRCBR == 'vbr': opts.extend(['-v', str(headphones.CONFIG.ENCODERQUALITY)]) else: advanced = (headphones.CONFIG.ADVANCEDENCODER.split()) for tok in advanced: opts.extend([tok.encode(headphones.SYS_ENCODING)]) opts.extend([musicSource]) opts.extend([musicDest]) cmd.extend(opts) # FFmpeg elif headphones.CONFIG.ENCODER == 'ffmpeg': cmd = [encoder, '-i', musicSource] opts = [] if not headphones.CONFIG.ADVANCEDENCODER: if headphones.CONFIG.ENCODEROUTPUTFORMAT == 'ogg': opts.extend(['-acodec', 'libvorbis']) if headphones.CONFIG.ENCODEROUTPUTFORMAT == 'm4a': opts.extend(['-strict', 'experimental']) if headphones.CONFIG.ENCODERVBRCBR == 'cbr': opts.extend([ '-ar', str(headphones.CONFIG.SAMPLINGFREQUENCY), '-ab', str(headphones.CONFIG.BITRATE) + 'k' ]) elif headphones.CONFIG.ENCODERVBRCBR == 'vbr': opts.extend(['-aq', str(headphones.CONFIG.ENCODERQUALITY)]) opts.extend(['-y', '-ac', '2', '-vn']) else: advanced = (headphones.CONFIG.ADVANCEDENCODER.split()) for tok in advanced: opts.extend([tok.encode(headphones.SYS_ENCODING)]) opts.extend([musicDest]) cmd.extend(opts) # Libav elif headphones.CONFIG.ENCODER == "libav": cmd = [encoder, '-i', musicSource] opts = [] if not headphones.CONFIG.ADVANCEDENCODER: if headphones.CONFIG.ENCODEROUTPUTFORMAT == 'ogg': opts.extend(['-acodec', 'libvorbis']) if headphones.CONFIG.ENCODEROUTPUTFORMAT == 'm4a': opts.extend(['-strict', 'experimental']) if headphones.CONFIG.ENCODERVBRCBR == 'cbr': opts.extend([ '-ar', str(headphones.CONFIG.SAMPLINGFREQUENCY), '-ab', str(headphones.CONFIG.BITRATE) + 'k' ]) elif headphones.CONFIG.ENCODERVBRCBR == 'vbr': opts.extend(['-aq', str(headphones.CONFIG.ENCODERQUALITY)]) opts.extend(['-y', '-ac', '2', '-vn']) else: advanced = (headphones.CONFIG.ADVANCEDENCODER.split()) for tok in advanced: opts.extend([tok.encode(headphones.SYS_ENCODING)]) opts.extend([musicDest]) cmd.extend(opts) # Prevent Windows from opening a terminal window startupinfo = None if headphones.SYS_PLATFORM == "win32": startupinfo = subprocess.STARTUPINFO() try: startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW except AttributeError: startupinfo.dwFlags |= subprocess._subprocess.STARTF_USESHOWWINDOW # Encode logger.info('Encoding %s...' % (musicSource.decode(headphones.SYS_ENCODING, 'replace'))) logger.debug(subprocess.list2cmdline(cmd)) process = subprocess.Popen(cmd, startupinfo=startupinfo, stdin=open(os.devnull, 'rb'), stdout=subprocess.PIPE, stderr=subprocess.PIPE) stdout, stderr = process.communicate(headphones.CONFIG.ENCODER) # Error if return code not zero if process.returncode: logger.error('Encoding failed for %s' % (musicSource.decode(headphones.SYS_ENCODING, 'replace'))) out = stdout if stdout else stderr out = out.decode(headphones.SYS_ENCODING, 'replace') outlast2lines = '\n'.join(out.splitlines()[-2:]) logger.error('%s error details: %s' % (headphones.CONFIG.ENCODER, outlast2lines)) out = out.rstrip("\n") logger.debug(out) encoded = False else: logger.info('%s encoded in %s', musicSource, getTimeEncode(startMusicTime)) encoded = True return encoded
def command(encoder, musicSource, musicDest, albumPath): """ Encode a given music file with a certain encoder. Returns True on success, or False otherwise. """ use_xld = headphones.CONFIG.ENCODER == 'xld' startMusicTime = time.time() cmd = [] # Return if xld details not found if use_xld: (xldProfile, xldFormat, xldBitrate) = getXldProfile.getXldProfile(headphones.CONFIG.XLDPROFILE) if not xldFormat: logger.error('Details for xld profile \'%s\' not found, files will not be re-encoded', xldProfile) return None xldDestDir = os.path.split(musicDest)[0] cmd = [encoder] cmd.extend([musicSource]) cmd.extend(['--profile']) cmd.extend([xldProfile]) cmd.extend(['-o']) cmd.extend([xldDestDir]) # Lame elif headphones.CONFIG.ENCODER == 'lame': cmd = [encoder] opts = [] if not headphones.CONFIG.ADVANCEDENCODER: opts.extend(['-h']) if headphones.CONFIG.ENCODERVBRCBR == 'cbr': opts.extend(['--resample', str(headphones.CONFIG.SAMPLINGFREQUENCY), '-b', str(headphones.CONFIG.BITRATE)]) elif headphones.CONFIG.ENCODERVBRCBR == 'vbr': opts.extend(['-v', str(headphones.CONFIG.ENCODERQUALITY)]) else: advanced = (headphones.CONFIG.ADVANCEDENCODER.split()) for tok in advanced: opts.extend([tok.encode(headphones.SYS_ENCODING)]) opts.extend([musicSource]) opts.extend([musicDest]) cmd.extend(opts) # FFmpeg elif headphones.CONFIG.ENCODER == 'ffmpeg': cmd = [encoder, '-i', musicSource] opts = [] if not headphones.CONFIG.ADVANCEDENCODER: if headphones.CONFIG.ENCODEROUTPUTFORMAT == 'ogg': opts.extend(['-acodec', 'libvorbis']) if headphones.CONFIG.ENCODEROUTPUTFORMAT == 'm4a': opts.extend(['-strict', 'experimental']) if headphones.CONFIG.ENCODERVBRCBR == 'cbr': opts.extend(['-ar', str(headphones.CONFIG.SAMPLINGFREQUENCY), '-ab', str(headphones.CONFIG.BITRATE) + 'k']) elif headphones.CONFIG.ENCODERVBRCBR == 'vbr': opts.extend(['-aq', str(headphones.CONFIG.ENCODERQUALITY)]) opts.extend(['-y', '-ac', '2', '-vn']) else: advanced = (headphones.CONFIG.ADVANCEDENCODER.split()) for tok in advanced: opts.extend([tok.encode(headphones.SYS_ENCODING)]) opts.extend([musicDest]) cmd.extend(opts) # Libav elif headphones.CONFIG.ENCODER == "libav": cmd = [encoder, '-i', musicSource] opts = [] if not headphones.CONFIG.ADVANCEDENCODER: if headphones.CONFIG.ENCODEROUTPUTFORMAT == 'ogg': opts.extend(['-acodec', 'libvorbis']) if headphones.CONFIG.ENCODEROUTPUTFORMAT == 'm4a': opts.extend(['-strict', 'experimental']) if headphones.CONFIG.ENCODERVBRCBR == 'cbr': opts.extend(['-ar', str(headphones.CONFIG.SAMPLINGFREQUENCY), '-ab', str(headphones.CONFIG.BITRATE) + 'k']) elif headphones.CONFIG.ENCODERVBRCBR == 'vbr': opts.extend(['-aq', str(headphones.CONFIG.ENCODERQUALITY)]) opts.extend(['-y', '-ac', '2', '-vn']) else: advanced = (headphones.CONFIG.ADVANCEDENCODER.split()) for tok in advanced: opts.extend([tok.encode(headphones.SYS_ENCODING)]) opts.extend([musicDest]) cmd.extend(opts) # Prevent Windows from opening a terminal window startupinfo = None if headphones.SYS_PLATFORM == "win32": startupinfo = subprocess.STARTUPINFO() try: startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW except AttributeError: startupinfo.dwFlags |= subprocess._subprocess.STARTF_USESHOWWINDOW # Encode logger.info('Encoding %s...' % (musicSource.decode(headphones.SYS_ENCODING, 'replace'))) logger.debug(subprocess.list2cmdline(cmd)) process = subprocess.Popen(cmd, startupinfo=startupinfo, stdin=open(os.devnull, 'rb'), stdout=subprocess.PIPE, stderr=subprocess.PIPE) stdout, stderr = process.communicate(headphones.CONFIG.ENCODER) # Error if return code not zero if process.returncode: logger.error('Encoding failed for %s' % (musicSource.decode(headphones.SYS_ENCODING, 'replace'))) out = stdout if stdout else stderr out = out.decode(headphones.SYS_ENCODING, 'replace') outlast2lines = '\n'.join(out.splitlines()[-2:]) logger.error('%s error details: %s' % (headphones.CONFIG.ENCODER, outlast2lines)) out = out.rstrip("\n") logger.debug(out) encoded = False else: logger.info('%s encoded in %s', musicSource, getTimeEncode(startMusicTime)) encoded = True return encoded