From 14935b53880ef5b2dface5a8dfd49d90825fecdc Mon Sep 17 00:00:00 2001 From: clinton-hall Date: Sun, 13 Jul 2014 12:59:56 +0930 Subject: [PATCH] added global nice and ionice for external processes. Fixes #479 --- autoProcessMedia.cfg.spec | 11 +++++++++-- nzbToCouchPotato.py | 22 +++++++++++++++++----- nzbToGamez.py | 17 +++++++++++++++++ nzbToHeadPhones.py | 17 +++++++++++++++++ nzbToMedia.py | 22 +++++++++++++++++----- nzbToMylar.py | 17 +++++++++++++++++ nzbToNzbDrone.py | 22 +++++++++++++++++----- nzbToSickBeard.py | 22 +++++++++++++++++----- nzbtomedia/__init__.py | 20 ++++++++++++++++---- nzbtomedia/extractor/extractor.py | 2 ++ nzbtomedia/nzbToMediaConfig.py | 18 ++++++++++++++++-- nzbtomedia/transcoder/transcoder.py | 4 ++-- 12 files changed, 164 insertions(+), 30 deletions(-) diff --git a/autoProcessMedia.cfg.spec b/autoProcessMedia.cfg.spec index b5f7d275..c80ae401 100644 --- a/autoProcessMedia.cfg.spec +++ b/autoProcessMedia.cfg.spec @@ -27,6 +27,15 @@ # Enable/Disable a safety check to ensure we don't process all downloads in the default_downloadDirectories by mistake. safe_mode = 1 +[Posix] + ### Process priority setting for External commands (Extractor and Transcoder) on Posix (Unix/Linux/OSX) systems. + # Set the Niceness value for the nice command. These range from -20 (most favorable to the process) to 19 (least favorable to the process). + niceness = 10 + # Set the ionice scheduling class. 0 for none, 1 for real time, 2 for best-effort, 3 for idle. + ionice_class = 2 + # Set the ionice scheduling class data. This defines the class data, if the class accepts an argument. For real time and best-effort, 0-7 is valid data. + ionice_classdata = 4 + [CouchPotato] #### autoProcessing for Movies #### movie - category that gets called for post-processing with CPS @@ -244,8 +253,6 @@ transcode = 0 ###### duplicate =1 will cretae a new file. =0 will replace the original duplicate = 1 - # Only works on Linux. Highest priority is -20, lowest priority is 19. - niceness = 0 ignoreExtensions = .avi,.mkv,.mp4 # outputFastStart. 1 will use -movflags + faststart. 0 will disable this from being used. outputFastStart = 0 diff --git a/nzbToCouchPotato.py b/nzbToCouchPotato.py index 01f1bcb1..2abeefd1 100755 --- a/nzbToCouchPotato.py +++ b/nzbToCouchPotato.py @@ -95,6 +95,23 @@ # This is a list of media extensions that are used to verify that the download does contain valid media. #mediaExtensions=.mkv,.avi,.divx,.xvid,.mov,.wmv,.mp4,.mpg,.mpeg,.vob,.iso +## Posix + +# Niceness for external tasks Extractor and Transcoder. +# +# Set the Niceness value for the nice command. These range from -20 (most favorable to the process) to 19 (least favorable to the process). +#niceness=10 + +# ionice scheduling class (0, 1, 2, 3). +# +# Set the ionice scheduling class. 0 for none, 1 for real time, 2 for best-effort, 3 for idle. +#ionice_class=2 + +# ionice scheduling class data. +# +# Set the ionice scheduling class data. This defines the class data, if the class accepts an argument. For real time and best-effort, 0-7 is valid data. +#ionice_classdata=4 + ## Transcoder # getSubs (0, 1). @@ -117,11 +134,6 @@ # set to 1 to cretae a new file or 0 to replace the original #duplicate=1 -# set niceness level. -# -# Only works on Linux. Highest priority is -20, lowest priority is 19. -#niceness=0 - # ignore extensions. # # list of extensions that won't be transcoded. diff --git a/nzbToGamez.py b/nzbToGamez.py index 3fb99843..a48f7a3d 100755 --- a/nzbToGamez.py +++ b/nzbToGamez.py @@ -61,6 +61,23 @@ # set this to where your Gamez completed downloads are. #gzwatch_dir= +## Posix + +# Niceness for external tasks Extractor and Transcoder. +# +# Set the Niceness value for the nice command. These range from -20 (most favorable to the process) to 19 (least favorable to the process). +#niceness=10 + +# ionice scheduling class (0, 1, 2, 3). +# +# Set the ionice scheduling class. 0 for none, 1 for real time, 2 for best-effort, 3 for idle. +#ionice_class=2 + +# ionice scheduling class data. +# +# Set the ionice scheduling class data. This defines the class data, if the class accepts an argument. For real time and best-effort, 0-7 is valid data. +#ionice_classdata=4 + ## WakeOnLan # use WOL (0, 1). diff --git a/nzbToHeadPhones.py b/nzbToHeadPhones.py index 6bae012e..4d5f0097 100755 --- a/nzbToHeadPhones.py +++ b/nzbToHeadPhones.py @@ -65,6 +65,23 @@ # Enable to replace local path with the path as per the mountPoints below. #hpremote_path=0 +## Posix + +# Niceness for external tasks Extractor and Transcoder. +# +# Set the Niceness value for the nice command. These range from -20 (most favorable to the process) to 19 (least favorable to the process). +#niceness=10 + +# ionice scheduling class (0, 1, 2, 3). +# +# Set the ionice scheduling class. 0 for none, 1 for real time, 2 for best-effort, 3 for idle. +#ionice_class=2 + +# ionice scheduling class data. +# +# Set the ionice scheduling class data. This defines the class data, if the class accepts an argument. For real time and best-effort, 0-7 is valid data. +#ionice_classdata=4 + ## Network # Network Mount Points (Needed for remote path above) diff --git a/nzbToMedia.py b/nzbToMedia.py index f8aed879..74f236ce 100755 --- a/nzbToMedia.py +++ b/nzbToMedia.py @@ -291,6 +291,23 @@ # This is a list of media extensions that are used to verify that the download does contain valid media. #mediaExtensions=.mkv,.avi,.divx,.xvid,.mov,.wmv,.mp4,.mpg,.mpeg,.vob,.iso +## Posix + +# Niceness for external tasks Extractor and Transcoder. +# +# Set the Niceness value for the nice command. These range from -20 (most favorable to the process) to 19 (least favorable to the process). +#niceness=10 + +# ionice scheduling class (0, 1, 2, 3). +# +# Set the ionice scheduling class. 0 for none, 1 for real time, 2 for best-effort, 3 for idle. +#ionice_class=2 + +# ionice scheduling class data. +# +# Set the ionice scheduling class data. This defines the class data, if the class accepts an argument. For real time and best-effort, 0-7 is valid data. +#ionice_classdata=4 + ## Transcoder # getSubs (0, 1). @@ -313,11 +330,6 @@ # set to 1 to cretae a new file or 0 to replace the original #duplicate=1 -# set niceness level. -# -# Only works on Linux. Highest priority is -20, lowest priority is 19. -#niceness=0 - # ignore extensions. # # list of extensions that won't be transcoded. diff --git a/nzbToMylar.py b/nzbToMylar.py index 68ab0a55..fbc8b618 100755 --- a/nzbToMylar.py +++ b/nzbToMylar.py @@ -69,6 +69,23 @@ # Enable to replace local path with the path as per the mountPoints below. #myremote_path=0 +## Posix + +# Niceness for external tasks Extractor and Transcoder. +# +# Set the Niceness value for the nice command. These range from -20 (most favorable to the process) to 19 (least favorable to the process). +#niceness=10 + +# ionice scheduling class (0, 1, 2, 3). +# +# Set the ionice scheduling class. 0 for none, 1 for real time, 2 for best-effort, 3 for idle. +#ionice_class=2 + +# ionice scheduling class data. +# +# Set the ionice scheduling class data. This defines the class data, if the class accepts an argument. For real time and best-effort, 0-7 is valid data. +#ionice_classdata=4 + ## Network # Network Mount Points (Needed for remote path above) diff --git a/nzbToNzbDrone.py b/nzbToNzbDrone.py index 1258fa8a..d671c8c8 100755 --- a/nzbToNzbDrone.py +++ b/nzbToNzbDrone.py @@ -85,6 +85,23 @@ # This is a list of media extensions that are used to verify that the download does contain valid media. #mediaExtensions=.mkv,.avi,.divx,.xvid,.mov,.wmv,.mp4,.mpg,.mpeg,.vob,.iso +## Posix + +# Niceness for external tasks Extractor and Transcoder. +# +# Set the Niceness value for the nice command. These range from -20 (most favorable to the process) to 19 (least favorable to the process). +#niceness=10 + +# ionice scheduling class (0, 1, 2, 3). +# +# Set the ionice scheduling class. 0 for none, 1 for real time, 2 for best-effort, 3 for idle. +#ionice_class=2 + +# ionice scheduling class data. +# +# Set the ionice scheduling class data. This defines the class data, if the class accepts an argument. For real time and best-effort, 0-7 is valid data. +#ionice_classdata=4 + ## Transcoder # getSubs (0, 1). @@ -107,11 +124,6 @@ # set to 1 to cretae a new file or 0 to replace the original #duplicate=1 -# set niceness level. -# -# Only works on Linux. Highest priority is -20, lowest priority is 19. -#niceness = 0 - # ignore extensions. # # list of extensions that won't be transcoded. diff --git a/nzbToSickBeard.py b/nzbToSickBeard.py index 581c0849..e12a6051 100755 --- a/nzbToSickBeard.py +++ b/nzbToSickBeard.py @@ -103,6 +103,23 @@ # This is a list of media extensions that are used to verify that the download does contain valid media. #mediaExtensions=.mkv,.avi,.divx,.xvid,.mov,.wmv,.mp4,.mpg,.mpeg,.vob,.iso +## Posix + +# Niceness for external tasks Extractor and Transcoder. +# +# Set the Niceness value for the nice command. These range from -20 (most favorable to the process) to 19 (least favorable to the process). +#niceness=10 + +# ionice scheduling class (0, 1, 2, 3). +# +# Set the ionice scheduling class. 0 for none, 1 for real time, 2 for best-effort, 3 for idle. +#ionice_class=2 + +# ionice scheduling class data. +# +# Set the ionice scheduling class data. This defines the class data, if the class accepts an argument. For real time and best-effort, 0-7 is valid data. +#ionice_classdata=4 + ## Transcoder # getSubs (0, 1). @@ -125,11 +142,6 @@ # set to 1 to cretae a new file or 0 to replace the original #duplicate=1 -# set niceness level. -# -# Only works on Linux. Highest priority is -20, lowest priority is 19. -#niceness=0 - # ignore extensions. # # list of extensions that won't be transcoded. diff --git a/nzbtomedia/__init__.py b/nzbtomedia/__init__.py index 5a780ba7..7ba36163 100644 --- a/nzbtomedia/__init__.py +++ b/nzbtomedia/__init__.py @@ -164,7 +164,7 @@ OUTPUTQUALITYPERCENT = None FFMPEG = None FFPROBE = None CHECK_MEDIA = None -NICENESS = None +NICENESS = [] PASSWORDSFILE = None DOWNLOADINFO = None @@ -332,6 +332,21 @@ def initialize(section=None): if REMOTEPATHS: REMOTEPATHS = [ tuple(item.split(',')) for item in REMOTEPATHS.split('|') ] # /volume1/Public/,E:\|/volume2/share/,\\NAS\ + try: + NICENESS.extend(['nice', '-n', int(CFG["Posix"]["niceness"])]) + except: pass + try: + NICENESS.extend(['ionice', '-c%s' % (int(CFG["Posix"]["ionice_class"]))]) + except: pass + try: + if 'ionice' in NICENESS: + NICENESS.extend(['-n%s' % (int(CFG["Posix"]["ionice_classdata"]))]) + else: + NICENESS.extend(['ionice', '-n%s' % (int(CFG["Posix"]["ionice_classdata"]))]) + except: pass + if 'ionice' in NICENESS: + NICENESS.extend(['-t']) + COMPRESSEDCONTAINER = [re.compile('.r\d{2}$', re.I), re.compile('.part\d+.rar$', re.I), re.compile('.rar$', re.I)] @@ -353,9 +368,6 @@ def initialize(section=None): try: OUTPUTQUALITYPERCENT = int(CFG["Transcoder"]["outputQualityPercent"]) except: pass - try: - NICENESS = int(CFG["Transcoder"]["niceness"]) - except: pass OUTPUTVIDEOPATH = CFG["Transcoder"]["outputVideoPath"] PROCESSOUTPUT = int(CFG["Transcoder"]["processOutput"]) ALANGUAGE = CFG["Transcoder"]["audioLanguage"] diff --git a/nzbtomedia/extractor/extractor.py b/nzbtomedia/extractor/extractor.py index c0978761..153e15a4 100644 --- a/nzbtomedia/extractor/extractor.py +++ b/nzbtomedia/extractor/extractor.py @@ -88,6 +88,8 @@ def extract(filePath, outputDestination): os.chdir(outputDestination) # Not all unpack commands accept full paths, so just extract into this directory try: # now works same for nt and *nix cmd.append(filePath) # add filePath to final cmd arg. + if platform.system() != 'Windows': + cmd = nzbtomedia.NICENESS + cmd cmd2 = cmd cmd2.append("-p-") # don't prompt for password. p = Popen(cmd2) # should extract files fine. diff --git a/nzbtomedia/nzbToMediaConfig.py b/nzbtomedia/nzbToMediaConfig.py index 2f245b68..3a629534 100644 --- a/nzbtomedia/nzbToMediaConfig.py +++ b/nzbtomedia/nzbToMediaConfig.py @@ -171,6 +171,10 @@ class ConfigObj(configobj.ConfigObj, Section): if option == "forceClean": CFG_NEW['General']['force_clean'] = value values.pop(option) + if section in ["Transcoder"]: + if option in ["niceness"]: + CFG_NEW['Posix'][option] = value + values.pop(option) if option == "remote_path": if value and not value in ['0', '1', 0, 1]: value = 1 @@ -369,13 +373,23 @@ class ConfigObj(configobj.ConfigObj, Section): value = os.environ[key] CFG_NEW[section][option] = value + section = "Posix" + envKeys = ['NICENESS', 'IONICE_CLASS', 'IONICE_CLASSDATA'] + cfgKeys = ['niceness', 'ionice_class', 'ionice_classdata'] + for index in range(len(envKeys)): + key = 'NZBPO_' + envKeys[index] + if os.environ.has_key(key): + option = cfgKeys[index] + value = os.environ[key] + CFG_NEW[section][option] = value + section = "Transcoder" - envKeys = ['TRANSCODE', 'DUPLICATE', 'NICENESS', 'IGNOREEXTENSIONS', 'OUTPUTFASTSTART', 'OUTPUTVIDEOPATH', 'PROCESSOUTPUT', 'AUDIOLANGUAGE', 'ALLAUDIOLANGUAGES', 'SUBLANGUAGES', + envKeys = ['TRANSCODE', 'DUPLICATE', 'IGNOREEXTENSIONS', 'OUTPUTFASTSTART', 'OUTPUTVIDEOPATH', 'PROCESSOUTPUT', 'AUDIOLANGUAGE', 'ALLAUDIOLANGUAGES', 'SUBLANGUAGES', 'ALLSUBLANGUAGES', 'EMBEDSUBS', 'BURNINSUBTITLE', 'EXTRACTSUBS', 'EXTERNALSUBDIR', 'OUTPUTDEFAULT', 'OUTPUTVIDEOEXTENSION', 'OUTPUTVIDEOCODEC', 'VIDEOCODECALLOW', 'OUTPUTVIDEOPRESET', 'OUTPUTVIDEOFRAMERATE', 'OUTPUTVIDEOBITRATE', 'OUTPUTAUDIOCODEC', 'AUDIOCODECALLOW', 'OUTPUTAUDIOBITRATE', 'OUTPUTQUALITYPERCENT', 'GETSUBS', 'OUTPUTAUDIOTRACK2CODEC', 'AUDIOCODEC2ALLOW', 'OUTPUTAUDIOTRACK2BITRATE', 'OUTPUTAUDIOOTHERCODEC', 'AUDIOOTHERCODECALLOW', 'OUTPUTAUDIOOTHERBITRATE', 'OUTPUTSUBTITLECODEC', 'OUTPUTAUDIOCHANNELS', 'OUTPUTAUDIOTRACK2CHANNELS', 'OUTPUTAUDIOOTHERCHANNELS'] - cfgKeys = ['transcode', 'duplicate', 'niceness', 'ignoreExtensions', 'outputFastStart', 'outputVideoPath', 'processOutput', 'audioLanguage', 'allAudioLanguages', 'subLanguages', + cfgKeys = ['transcode', 'duplicate', 'ignoreExtensions', 'outputFastStart', 'outputVideoPath', 'processOutput', 'audioLanguage', 'allAudioLanguages', 'subLanguages', 'allSubLanguages', 'embedSubs', 'burnInSubtitle', 'extractSubs', 'externalSubDir', 'outputDefault', 'outputVideoExtension', 'outputVideoCodec', 'VideoCodecAllow', 'outputVideoPreset', 'outputVideoFramerate', 'outputVideoBitrate', 'outputAudioCodec', 'AudioCodecAllow', 'outputAudioBitrate', 'outputQualityPercent', 'getSubs', 'outputAudioTrack2Codec', 'AudioCodec2Allow', 'outputAudioTrack2Bitrate', 'outputAudioOtherCodec', 'AudioOtherCodecAllow', 'outputAudioOtherBitrate', diff --git a/nzbtomedia/transcoder/transcoder.py b/nzbtomedia/transcoder/transcoder.py index 77db3ed9..9f548c15 100644 --- a/nzbtomedia/transcoder/transcoder.py +++ b/nzbtomedia/transcoder/transcoder.py @@ -318,7 +318,7 @@ def buildCommands(file, newDir): command.extend(other_cmd) command.append(newfilePath) if platform.system() != 'Windows': - command = ['nice', '-%d' % nzbtomedia.NICENESS] + command + command = nzbtomedia.NICENESS + command return command def get_subs(file): @@ -350,7 +350,7 @@ def extract_subs(file, newfilePath, bitbucket): outputFile = os.path.join(subdir, "%s(%s)%s.srt" %(name, n, lan)) command = [nzbtomedia.FFMPEG, '-loglevel', 'warning', '-i', sub, '-vn', '-an', '-codec:s:' + str(n), 'srt', outputFile] if platform.system() != 'Windows': - command = ['nice', '-%d' % nzbtomedia.NICENESS] + command + command = nzbtomedia.NICENESS + command logger.info("Extracting %s Subtitle from: %s" % (lan, file)) cmd = ""