diff --git a/data/interfaces/default/config.html b/data/interfaces/default/config.html index 0cffeb5d..1a5c113c 100644 --- a/data/interfaces/default/config.html +++ b/data/interfaces/default/config.html @@ -277,6 +277,8 @@ Bitrate: kbps

+

Advance Encode Options:

+

Path to Encoder:

diff --git a/data/interfaces/remix/config.html b/data/interfaces/remix/config.html index 29bf848d..07763d08 100644 --- a/data/interfaces/remix/config.html +++ b/data/interfaces/remix/config.html @@ -277,6 +277,8 @@ Bitrate: kbps

+

Advance Encode Options:

+

Path to Encoder:

diff --git a/headphones/__init__.py b/headphones/__init__.py index 9949986d..ab59ae4d 100755 --- a/headphones/__init__.py +++ b/headphones/__init__.py @@ -117,6 +117,9 @@ ENCODERFOLDER = None ENCODER = None BITRATE = None SAMPLINGFREQUENCY = None +ADVANCEDENCODER = None +ENCODEROUTPUTFORMAT = None +VORBISQUALITY = None def CheckSection(sec): """ Check if INI section exists, if not create it """ @@ -176,7 +179,7 @@ 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 + ENCODERFOLDER, ENCODER, BITRATE, SAMPLINGFREQUENCY, ENCODE, ADVANCEDENCODER, ENCODEROUTPUTFORMAT, VORBISQUALITY if __INITIALIZED__: return False @@ -262,7 +265,10 @@ def initialize(): BITRATE = check_setting_int(CFG, 'General', 'bitrate', 192) SAMPLINGFREQUENCY= check_setting_int(CFG, 'General', 'samplingfrequency', 44100) ENCODE = bool(check_setting_int(CFG, 'General', 'encode', 0)) - + ADVANCEDENCODER = check_setting_str(CFG, 'General', 'advancedencoder', '') + ENCODEROUTPUTFORMAT = check_setting_str(CFG, 'General', 'encoderoutputformat', 'mp3') + VORBISQUALITY = check_setting_int(CFG, 'General', 'vorbisquality', 60) + if not LOG_DIR: LOG_DIR = os.path.join(DATA_DIR, 'logs') @@ -441,6 +447,9 @@ def config_write(): new_config['General']['bitrate'] = BITRATE new_config['General']['samplingfrequency'] = SAMPLINGFREQUENCY new_config['General']['encoderfolder'] = ENCODERFOLDER + new_config['General']['advancedencoder'] = ADVANCEDENCODER + new_config['General']['encoderoutputformat'] = ENCODEROUTPUTFORMAT + new_config['General']['vorbisquality'] = VORBISQUALITY new_config.write() diff --git a/headphones/encode.py b/headphones/encode.py index 10fd63b5..77a435b4 100644 --- a/headphones/encode.py +++ b/headphones/encode.py @@ -2,12 +2,10 @@ import os import headphones import shutil import time -import sys from subprocess import call from headphones import logger -from lib.mutagen.mp3 import MP3 -from lib.mutagen.easyid3 import EasyID3 +from lib.beets.mediafile import MediaFile try: import argparse @@ -30,47 +28,38 @@ def encode(albumPath): for r,d,f in os.walk(albumPath): for music in f: - if any(music.endswith('.' + x) for x in ["mp3", "flac", "m4a", "wav"]): + if any(music.endswith('.' + x) for x in headphones.MEDIA_FORMATS): musicFiles.append(os.path.join(r, music)) - musicTemp = os.path.join(os.path.splitext(music)[0])+'.mp3' + musicTemp = os.path.splitext(music)[0]+'.'+headphones.ENCODEROUTPUTFORMAT musicTempFiles.append(os.path.join(tempDirEncode, musicTemp)) if headphones.ENCODER=='lame': encoder=os.path.join(headphones.ENCODERFOLDER,'lame') - else: + elif headphones.ENCODER=='ffmpeg': encoder=os.path.join(headphones.ENCODERFOLDER,'ffmpeg') i=0 - for music in musicFiles: - return_code=1 + for music in musicFiles: + infoMusic=MediaFile(music) + if headphones.ENCODER == 'lame': - if not any(music.endswith('.' + x) for x in ["mp3", "wav"]): + if not any(music.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 (MP3(music).info.bitrate/1000<=headphones.BITRATE)): + if (music.endswith('.mp3') and (infoMusic.bitrate/1000<=headphones.BITRATE)): logger.warn('Music "%s" has bitrate<="%skbit" will not be reencoded' % (music,headphones.BITRATE)) else: - cmd=encoder+' -h --resample ' + str(headphones.SAMPLINGFREQUENCY) + ' -b ' + str(headphones.BITRATE) - cmd=cmd+' "'+os.path.join(music)+'"' - cmd=cmd+' "'+os.path.join(musicTempFiles[i])+'"' - return_code = call(cmd, shell=True) - if return_code==0: - #copyID3(music,musicTempFiles[i]) - os.remove(music) - shutil.move(musicTempFiles[i],os.path.join(albumPath)) + command(encoder,music,musicTempFiles[i],albumPath) else: - if (music.endswith('.mp3') and (MP3(music).info.bitrate/1000<=headphones.BITRATE)): - logger.warn('Music "%s" has bitrate<="%skbit" will not be reencoded' % (music,headphones.BITRATE)) - else: - cmd=encoder+' -i' - cmd=cmd+' "'+os.path.join(music)+'"' - cmd=cmd+' -ac 2 -vn -ar ' + str(headphones.SAMPLINGFREQUENCY) + ' -ab ' + str(headphones.BITRATE) +'k' - cmd=cmd+' "'+os.path.join(musicTempFiles[i])+'"' - return_code = call(cmd, shell=True) - if return_code==0: - #copyID3(music,musicTempFiles[i]) - os.remove(music) - shutil.move(musicTempFiles[i],os.path.join(albumPath)) - + if headphones.ENCODEROUTPUTFORMAT=='ogg': + if music.endswith('.ogg'): + logger.warn('Can not reencode .ogg music "%s"' % (music)) + else: + command(encoder,music,musicTempFiles[i],albumPath) + elif (headphones.ENCODEROUTPUTFORMAT=='mp3'): + if (music.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) i=i+1 shutil.rmtree(tempDirEncode) @@ -82,16 +71,23 @@ def encode(albumPath): musicFinalFiles.append(os.path.join(r, music)) return musicFinalFiles -def copyID3 (src,dst): - try: - source = EasyID3(src) - try: - dest = EasyID3(dst) - except: - dest = ID3() - dest.save(dst) - for key in source: - dest[key] = source[key] - dest.save() - except: - return() +def command(encoder,musicSource,musicDest,albumPath): + return_code=1 + cmd='' + if headphones.ENCODER == 'lame': + cmd=encoder + ' -h --resample ' + str(headphones.SAMPLINGFREQUENCY) + ' -b ' + str(headphones.BITRATE) + 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 vorbis -strict experimental' + cmd=cmd+ ' -ac 2 -map_metadata 0:0,s0 -vn -ar ' + str(headphones.SAMPLINGFREQUENCY) + ' -ab ' + str(headphones.BITRATE) + 'k' + cmd=cmd+ ' ' + headphones.ADVANCEDENCODER + cmd=cmd+ ' "' + musicDest + '"' + return_code = call(cmd, shell=True) + if (return_code==0) and (os.path.exists(musicDest)): + os.remove(musicSource) + shutil.move(musicDest,albumPath) \ No newline at end of file diff --git a/headphones/webserve.py b/headphones/webserve.py index cbd2d1c3..42db5f84 100644 --- a/headphones/webserve.py +++ b/headphones/webserve.py @@ -353,7 +353,8 @@ class WebInterface(object): "encode": checked(headphones.ENCODE), "encoder": headphones.ENCODER, "bitrate": headphones.BITRATE, - "encoderfolder": headphones.ENCODERFOLDER + "encoderfolder": headphones.ENCODERFOLDER, + "advancedencoder": headphones.ADVANCEDENCODER } return serve_template(templatename="config.html", title="Settings", config=config) config.exposed = True @@ -364,7 +365,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, destination_dir=None, folder_format=None, file_format=None, include_extras=0, interface=None, log_dir=None, - encode=0, encoder=None, bitrate=None, encoderfolder=None): + encode=0, encoder=None, bitrate=None, encoderfolder=None, advancedencoder=None): headphones.HTTP_HOST = http_host headphones.HTTP_PORT = http_port @@ -411,6 +412,7 @@ class WebInterface(object): headphones.ENCODER = encoder headphones.BITRATE = bitrate headphones.ENCODERFOLDER = encoderfolder + headphones.ADVANCEDENCODER = advancedencoder headphones.config_write()