diff --git a/data/interfaces/default/config.html b/data/interfaces/default/config.html index fe789c72..a3818110 100644 --- a/data/interfaces/default/config.html +++ b/data/interfaces/default/config.html @@ -263,6 +263,8 @@

Re-encode downloads during postprocessing

Note: this option requires the lame or ffmpeg encoder +
+

Re-encode only LossLess format (.flac)



<% if config['encoder'] == 'lame': @@ -288,6 +290,33 @@ %endfor +
+ +

Audio Properties:

+
+

VBR/CBR: + + Quality:


Bitrate:



-

Advance Encode Options:

+

Advance Encode Options:

+

+ (ignores audio properties) +

+

Path to Encoder:

diff --git a/data/interfaces/remix/config.html b/data/interfaces/remix/config.html index fe789c72..04c99637 100644 --- a/data/interfaces/remix/config.html +++ b/data/interfaces/remix/config.html @@ -263,6 +263,8 @@

Re-encode downloads during postprocessing

Note: this option requires the lame or ffmpeg encoder +
+

Re-encode only LossLess format (.flac)



<% if config['encoder'] == 'lame': @@ -288,6 +290,32 @@ %endfor +
+

Audio Properties:

+
+

VBR/CBR: + + Quality:


Bitrate:



-

Advance Encode Options:

-
+

Advance Encode Options:

+

+ (ignores audio properties) +

+

Path to Encoder:

diff --git a/headphones/__init__.py b/headphones/__init__.py index 60637241..eeec7ed3 100644 --- a/headphones/__init__.py +++ b/headphones/__init__.py @@ -122,6 +122,7 @@ ADVANCEDENCODER = None ENCODEROUTPUTFORMAT = None ENCODERQUALITY = None ENCODERVBRCBR = None +ENCODERLOSSLESS = True def CheckSection(sec): """ Check if INI section exists, if not create it """ @@ -181,7 +182,8 @@ def initialize(): LIBRARYSCAN_INTERVAL, DOWNLOAD_SCAN_INTERVAL, SAB_HOST, SAB_USERNAME, SAB_PASSWORD, SAB_APIKEY, SAB_CATEGORY, \ NZBMATRIX, NZBMATRIX_USERNAME, NZBMATRIX_APIKEY, NEWZNAB, NEWZNAB_HOST, NEWZNAB_APIKEY, \ NZBSORG, NZBSORG_UID, NZBSORG_HASH, NEWZBIN, NEWZBIN_UID, NEWZBIN_PASSWORD, LASTFM_USERNAME, INTERFACE, FOLDER_PERMISSIONS, \ - ENCODERFOLDER, ENCODER, BITRATE, SAMPLINGFREQUENCY, ENCODE, ADVANCEDENCODER, ENCODEROUTPUTFORMAT, ENCODERQUALITY, ENCODERVBRVBR + ENCODERFOLDER, ENCODER, BITRATE, SAMPLINGFREQUENCY, ENCODE, ADVANCEDENCODER, ENCODEROUTPUTFORMAT, ENCODERQUALITY, ENCODERVBRVBR, \ + ENCODERLOSSLESS if __INITIALIZED__: return False @@ -270,8 +272,9 @@ def initialize(): ENCODE = bool(check_setting_int(CFG, 'General', 'encode', 0)) ADVANCEDENCODER = check_setting_str(CFG, 'General', 'advancedencoder', '') ENCODEROUTPUTFORMAT = check_setting_str(CFG, 'General', 'encoderoutputformat', 'mp3') - ENCODERQUALITY = check_setting_int(CFG, 'General', 'vorbisquality', 60) + ENCODERQUALITY = check_setting_int(CFG, 'General', 'vorbisquality', 5) ENCODERVBRCBR = check_setting_str(CFG, 'General', 'encodervbrcbr', 'cbr') + ENCODERLOSSLESS = bool(check_setting_int(CFG, 'General', 'encoderlossless', 1)) if not LOG_DIR: LOG_DIR = os.path.join(DATA_DIR, 'logs') @@ -459,6 +462,7 @@ def config_write(): new_config['General']['encoderoutputformat'] = ENCODEROUTPUTFORMAT new_config['General']['encoderquality'] = ENCODERQUALITY new_config['General']['encodervbrcbr'] = ENCODERVBRCBR + new_config['General']['encoderlossless'] = ENCODERLOSSLESS new_config.write() diff --git a/headphones/encode.py b/headphones/encode.py index 6211663f..ba51db3c 100644 --- a/headphones/encode.py +++ b/headphones/encode.py @@ -30,11 +30,19 @@ def encode(albumPath): for r,d,f in os.walk(albumPath): for music in f: - if any(music.endswith('.' + x) for x in headphones.MEDIA_FORMATS): - musicFiles.append(os.path.join(r, music)) - musicTemp = os.path.normpath(os.path.splitext(music)[0]+'.'+headphones.ENCODEROUTPUTFORMAT).encode(headphones.SYS_ENCODING) - musicTempFiles.append(os.path.join(tempDirEncode, musicTemp)) - + if any(music.lower().endswith('.' + x.lower()) for x in headphones.MEDIA_FORMATS): + if (headphones.ENCODERLOSSLESS): + if (music.lower().endswith('.flac')): + musicFiles.append(os.path.join(r, music)) + musicTemp = os.path.normpath(os.path.splitext(music)[0]+'.'+headphones.ENCODEROUTPUTFORMAT).encode(headphones.SYS_ENCODING) + musicTempFiles.append(os.path.join(tempDirEncode, musicTemp)) + else: + logger.warn('Music "%s" is already encoded' % (music)) + else: + musicFiles.append(os.path.join(r, music)) + musicTemp = os.path.normpath(os.path.splitext(music)[0]+'.'+headphones.ENCODEROUTPUTFORMAT).encode(headphones.SYS_ENCODING) + musicTempFiles.append(os.path.join(tempDirEncode, musicTemp)) + if headphones.ENCODER=='lame': encoder=os.path.join(headphones.ENCODERFOLDER,'lame') elif headphones.ENCODER=='ffmpeg': @@ -42,42 +50,39 @@ def encode(albumPath): i=0 for music in musicFiles: infoMusic=MediaFile(music) - if headphones.ENCODER == 'lame': - if not any(music.endswith('.' +headphones.ENCODEROUTPUTFORMAT) for x in ["mp3", "wav"]): + if not any(music.lower().endswith('.' +headphones.ENCODEROUTPUTFORMAT) for x in ["mp3", "wav"]): logger.warn('Lame cant encode "%s" format for "%s", use ffmpeg' % (os.path.splitext(music)[1],music)) else: - if (music.endswith('.mp3') and (infoMusic.bitrate/1000<=headphones.BITRATE)): + if (music.lower().endswith('.mp3') and (infoMusic.bitrate/1000<=headphones.BITRATE)): logger.warn('Music "%s" has bitrate<="%skbit" will not be reencoded' % (music,headphones.BITRATE)) else: command(encoder,music,musicTempFiles[i],albumPath) ifencoded=1 else: if headphones.ENCODEROUTPUTFORMAT=='ogg': - if music.endswith('.ogg'): + if music.lower().endswith('.ogg'): logger.warn('Can not reencode .ogg music "%s"' % (music)) else: command(encoder,music,musicTempFiles[i],albumPath) ifencoded=1 elif (headphones.ENCODEROUTPUTFORMAT=='mp3' or headphones.ENCODEROUTPUTFORMAT=='m4a'): - if (music.endswith('.'+headphones.ENCODEROUTPUTFORMAT) and (infoMusic.bitrate/1000<=headphones.BITRATE)): + if (music.lower().endswith('.'+headphones.ENCODEROUTPUTFORMAT) and (infoMusic.bitrate/1000<=headphones.BITRATE)): logger.warn('Music "%s" has bitrate<="%skbit" will not be reencoded' % (music,headphones.BITRATE)) else: command(encoder,music,musicTempFiles[i],albumPath) ifencoded=1 - i=i+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.endswith('.' + x) for x in headphones.MEDIA_FORMATS): + 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)) - else: - logger.info('Encoding for folder "%s" is completed in %s' % (albumPath,getTimeEncode(startAlbumTime))) return musicFinalFiles @@ -86,28 +91,46 @@ def command(encoder,musicSource,musicDest,albumPath): cmd='' startMusicTime=time.clock() if headphones.ENCODER == 'lame': - cmd=encoder + ' -h' - if headphones.ENCODERVBRCBR=='cbr': - cmd=cmd+ ' --resample ' + str(headphones.SAMPLINGFREQUENCY) + ' -b ' + str(headphones.BITRATE) - elif headphones.ENCODERVBRCBR=='vbr': - cmd=cmd+'' - cmd=cmd+ ' ' + headphones.ADVANCEDENCODER + if headphones.ADVANCEDENCODER =='': + cmd=encoder + ' -h' + if headphones.ENCODERVBRCBR=='cbr': + cmd=cmd+ ' --resample ' + str(headphones.SAMPLINGFREQUENCY) + ' -b ' + str(headphones.BITRATE) + elif headphones.ENCODERVBRCBR=='vbr': + if (ENCODERQUALITY>=0 and ENCODERQUALITY<=9): + cmd=cmd+' -V'+str(ENCODERQUALITY) + elif (ENCODERQUALITY<0): + cmd=cmd+' -V0' + elif (ENCODERQUALITY>9): + cmd=cmd+' -V9' + cmd=cmd+ ' ' + headphones.ADVANCEDENCODER + else: + cmd=cmd+' '+ headphones.ADVANCEDENCODER cmd=cmd+ ' "' + musicSource + '"' cmd=cmd+ ' "' + musicDest +'"' + elif headphones.ENCODER == 'ffmpeg': cmd=encoder+ ' -i' cmd=cmd+ ' "' + musicSource + '"' - if headphones.ENCODEROUTPUTFORMAT=='ogg': - cmd=cmd+ ' -acodec libvorbis' - if headphones.ENCODEROUTPUTFORMAT=='m4a': - cmd=cmd+ ' -strict experimental' - if headphones.ENCODERVBRCBR=='cbr': - cmd=cmd+ ' -ar ' + str(headphones.SAMPLINGFREQUENCY) + ' -ab ' + str(headphones.BITRATE) + 'k' - elif headphones.ENCODERVBRCBR=='vbr': - cmd=cmd+'' - cmd=cmd+ ' -y -ac 2 -map_metadata 0:0,s0 -vn' - cmd=cmd+ ' ' + headphones.ADVANCEDENCODER + if headphones.ADVANCEDENCODER =='': + if headphones.ENCODEROUTPUTFORMAT=='ogg': + cmd=cmd+ ' -acodec libvorbis' + if headphones.ENCODEROUTPUTFORMAT=='m4a': + cmd=cmd+ ' -strict experimental' + if headphones.ENCODERVBRCBR=='cbr': + cmd=cmd+ ' -ar ' + str(headphones.SAMPLINGFREQUENCY) + ' -ab ' + str(headphones.BITRATE) + 'k' + elif headphones.ENCODERVBRCBR=='vbr': + if (ENCODERQUALITY>=0 and ENCODERQUALITY<=9): + cmd=cmd+' -aq '+str(ENCODERQUALITY) + elif (ENCODERQUALITY<0): + cmd=cmd+' -aq 0' + elif (ENCODERQUALITY>9): + cmd=cmd+' -aq 9' + cmd=cmd+ ' -y -ac 2 -map_metadata 0:0,s0 -vn' + else: + cmd=cmd+' '+ headphones.ADVANCEDENCODER cmd=cmd+ ' "' + musicDest + '"' + print cmd + time.sleep(10) return_code = call(cmd, shell=True) if (return_code==0) and (os.path.exists(musicDest)): os.remove(musicSource) diff --git a/headphones/webserve.py b/headphones/webserve.py index 2ad51022..7ec86da6 100644 --- a/headphones/webserve.py +++ b/headphones/webserve.py @@ -357,7 +357,10 @@ class WebInterface(object): "encoderfolder": headphones.ENCODERFOLDER, "advancedencoder": headphones.ADVANCEDENCODER, "encoderoutputformat": headphones.ENCODEROUTPUTFORMAT, - "samplingfrequency": int(headphones.SAMPLINGFREQUENCY) + "samplingfrequency": int(headphones.SAMPLINGFREQUENCY), + "encodervbrcbr": (headphones.ENCODERVBRCBR), + "encoderquality": int(headphones.ENCODERQUALITY), + "encoderlossless": checked(headphones.ENCODERLOSSLESS) } return serve_template(templatename="config.html", title="Settings", config=config) config.exposed = True @@ -368,7 +371,7 @@ class WebInterface(object): usenet_retention=None, nzbmatrix=0, nzbmatrix_username=None, nzbmatrix_apikey=None, newznab=0, newznab_host=None, newznab_apikey=None, nzbsorg=0, nzbsorg_uid=None, nzbsorg_hash=None, newzbin=0, newzbin_uid=None, newzbin_password=None, preferred_quality=0, preferred_bitrate=None, detect_bitrate=0, move_files=0, rename_files=0, correct_metadata=0, cleanup_files=0, add_album_art=0, embed_album_art=0, embed_lyrics=0, destination_dir=None, folder_format=None, file_format=None, include_extras=0, interface=None, log_dir=None, - encode=0, encoder=None, bitrate=None, samplingfrequency=None, encoderfolder=None, advancedencoder=None, encoderoutputformat=None): + encode=0, encoder=None, bitrate=None, samplingfrequency=None, encoderfolder=None, advancedencoder=None, encoderoutputformat=None, encodervbrcbr=None, encoderquality=None, encoderlossless=0): headphones.HTTP_HOST = http_host headphones.HTTP_PORT = http_port @@ -419,6 +422,9 @@ class WebInterface(object): headphones.ENCODERFOLDER = encoderfolder headphones.ADVANCEDENCODER = advancedencoder headphones.ENCODEROUTPUTFORMAT = encoderoutputformat + headphones.ENCODERVBRCBR = encodervbrcbr + headphones.ENCODERQUALITY = int(encoderquality) + headphones.ENCODERLOSSLESS = encoderlossless headphones.config_write()