#401 nice cpu limit
This commit is contained in:
22
bin/ffx.py
22
bin/ffx.py
@@ -153,11 +153,15 @@ def getUnmuxSequence(trackDescriptor: TrackDescriptor, sourcePath, targetPrefix,
|
|||||||
@click.option('-l', '--label', type=str, default='', help='Label to be used as filename prefix')
|
@click.option('-l', '--label', type=str, default='', help='Label to be used as filename prefix')
|
||||||
@click.option("-o", "--output-directory", type=str, default='')
|
@click.option("-o", "--output-directory", type=str, default='')
|
||||||
@click.option("-s", "--subtitles-only", is_flag=True, default=False)
|
@click.option("-s", "--subtitles-only", is_flag=True, default=False)
|
||||||
|
@click.option('--nice', type=int, default=99, help='Niceness of started processes')
|
||||||
|
@click.option('--cpu', type=int, default=0, help='Limit CPU for started processes to percent')
|
||||||
def unmux(ctx,
|
def unmux(ctx,
|
||||||
paths,
|
paths,
|
||||||
label,
|
label,
|
||||||
output_directory,
|
output_directory,
|
||||||
subtitles_only):
|
subtitles_only,
|
||||||
|
nice,
|
||||||
|
cpu):
|
||||||
|
|
||||||
existingSourcePaths = [p for p in paths if os.path.isfile(p)]
|
existingSourcePaths = [p for p in paths if os.path.isfile(p)]
|
||||||
ctx.obj['logger'].debug(f"\nUnmuxing {len(existingSourcePaths)} files")
|
ctx.obj['logger'].debug(f"\nUnmuxing {len(existingSourcePaths)} files")
|
||||||
@@ -195,7 +199,7 @@ def unmux(ctx,
|
|||||||
if unmuxSequence:
|
if unmuxSequence:
|
||||||
if not ctx.obj['dry_run']:
|
if not ctx.obj['dry_run']:
|
||||||
ctx.obj['logger'].debug(f"Executing unmuxing sequence: {' '.join(unmuxSequence)}")
|
ctx.obj['logger'].debug(f"Executing unmuxing sequence: {' '.join(unmuxSequence)}")
|
||||||
out, err, rc = executeProcess(unmuxSequence)
|
out, err, rc = executeProcess(unmuxSequence, niceness=nice, cpu_percent=cpu)
|
||||||
if rc:
|
if rc:
|
||||||
ctx.obj['logger'].error(f"Unmuxing of stream {trackDescriptor.getIndex()} failed with error ({rc}) {err}")
|
ctx.obj['logger'].error(f"Unmuxing of stream {trackDescriptor.getIndex()} failed with error ({rc}) {err}")
|
||||||
else:
|
else:
|
||||||
@@ -314,6 +318,9 @@ def checkUniqueDispositions(context, mediaDescriptor: MediaDescriptor):
|
|||||||
@click.option("--no-signature", is_flag=True, default=False)
|
@click.option("--no-signature", is_flag=True, default=False)
|
||||||
@click.option("--keep-mkvmerge-metadata", is_flag=True, default=False)
|
@click.option("--keep-mkvmerge-metadata", is_flag=True, default=False)
|
||||||
|
|
||||||
|
@click.option('--nice', type=int, default=99, help='Niceness of started processes')
|
||||||
|
@click.option('--cpu', type=int, default=0, help='Limit CPU for started processes to percent')
|
||||||
|
|
||||||
def convert(ctx,
|
def convert(ctx,
|
||||||
paths,
|
paths,
|
||||||
label,
|
label,
|
||||||
@@ -360,7 +367,10 @@ def convert(ctx,
|
|||||||
dont_pass_dispositions,
|
dont_pass_dispositions,
|
||||||
no_prompt,
|
no_prompt,
|
||||||
no_signature,
|
no_signature,
|
||||||
keep_mkvmerge_metadata):
|
keep_mkvmerge_metadata,
|
||||||
|
|
||||||
|
nice,
|
||||||
|
cpu):
|
||||||
"""Batch conversion of audiovideo files in format suitable for web playback, e.g. jellyfin
|
"""Batch conversion of audiovideo files in format suitable for web playback, e.g. jellyfin
|
||||||
|
|
||||||
Files found under PATHS will be converted according to parameters.
|
Files found under PATHS will be converted according to parameters.
|
||||||
@@ -387,6 +397,12 @@ def convert(ctx,
|
|||||||
context['no_signature'] = no_signature
|
context['no_signature'] = no_signature
|
||||||
context['keep_mkvmerge_metadata'] = keep_mkvmerge_metadata
|
context['keep_mkvmerge_metadata'] = keep_mkvmerge_metadata
|
||||||
|
|
||||||
|
|
||||||
|
context['resource_limits'] = {}
|
||||||
|
context['resource_limits']['niceness'] = nice
|
||||||
|
context['resource_limits']['cpu_percent'] = cpu
|
||||||
|
|
||||||
|
|
||||||
context['denoiser'] = NlmeansController(parameters = denoise,
|
context['denoiser'] = NlmeansController(parameters = denoise,
|
||||||
strength = denoise_strength,
|
strength = denoise_strength,
|
||||||
patchSize = denoise_patch_size,
|
patchSize = denoise_patch_size,
|
||||||
|
|||||||
@@ -43,6 +43,10 @@ class FfxController():
|
|||||||
|
|
||||||
self.__configurationData = self.__context['config'].getData()
|
self.__configurationData = self.__context['config'].getData()
|
||||||
|
|
||||||
|
# Convenience
|
||||||
|
self.__niceness = self.__context['resource_limits']['niceness'] if 'resource_limits' in self.__context.keys() and 'niceness' in self.__context['resource_limits'].keys() else 99
|
||||||
|
self.__cpuPercent = self.__context['resource_limits']['cpu_percent'] if 'resource_limits' in self.__context.keys() and 'cpu_percent' in self.__context['resource_limits'].keys() else 0
|
||||||
|
|
||||||
self.__logger = context['logger']
|
self.__logger = context['logger']
|
||||||
|
|
||||||
|
|
||||||
@@ -268,7 +272,7 @@ class FfxController():
|
|||||||
self.__logger.debug(f"FfxController.runJob() commandSequence:{' '.join(commandSequence)}")
|
self.__logger.debug(f"FfxController.runJob() commandSequence:{' '.join(commandSequence)}")
|
||||||
|
|
||||||
if not self.__context['dry_run']:
|
if not self.__context['dry_run']:
|
||||||
executeProcess(commandSequence)
|
executeProcess(commandSequence, niceness=self.__niceness, cpu_percent=self.__cpuPercent)
|
||||||
|
|
||||||
|
|
||||||
if videoEncoder == VideoEncoder.VP9:
|
if videoEncoder == VideoEncoder.VP9:
|
||||||
@@ -296,7 +300,7 @@ class FfxController():
|
|||||||
os.remove(FfxController.TEMP_FILE_NAME)
|
os.remove(FfxController.TEMP_FILE_NAME)
|
||||||
|
|
||||||
if not self.__context['dry_run']:
|
if not self.__context['dry_run']:
|
||||||
executeProcess(commandSequence1)
|
executeProcess(commandSequence1, niceness=self.__niceness, cpu_percent=self.__cpuPercent)
|
||||||
|
|
||||||
commandSequence2 = (commandTokens
|
commandSequence2 = (commandTokens
|
||||||
+ self.__targetMediaDescriptor.getImportFileTokens()
|
+ self.__targetMediaDescriptor.getImportFileTokens()
|
||||||
@@ -318,7 +322,7 @@ class FfxController():
|
|||||||
self.__logger.debug(f"FfxController.runJob() commandSequence2:{' '.join(commandSequence2)}")
|
self.__logger.debug(f"FfxController.runJob() commandSequence2:{' '.join(commandSequence2)}")
|
||||||
|
|
||||||
if not self.__context['dry_run']:
|
if not self.__context['dry_run']:
|
||||||
out, err, rc = executeProcess(commandSequence2)
|
out, err, rc = executeProcess(commandSequence2, niceness=self.__niceness, cpu_percent=self.__cpuPercent)
|
||||||
if rc:
|
if rc:
|
||||||
raise click.ClickException(f"Command resulted in error: rc={rc} error={err}")
|
raise click.ClickException(f"Command resulted in error: rc={rc} error={err}")
|
||||||
|
|
||||||
@@ -345,4 +349,4 @@ class FfxController():
|
|||||||
str(length),
|
str(length),
|
||||||
path]
|
path]
|
||||||
|
|
||||||
out, err, rc = executeProcess(commandTokens)
|
out, err, rc = executeProcess(commandTokens, niceness=self.__niceness, cpu_percent=self.__cpuPercent)
|
||||||
|
|||||||
@@ -1,9 +1,29 @@
|
|||||||
import subprocess
|
import subprocess, click
|
||||||
from typing import List
|
from typing import List
|
||||||
|
|
||||||
def executeProcess(commandSequence: List[str], directory: str = None):
|
def executeProcess(commandSequence: List[str], directory: str = None, niceness: int = 99, cpu_percent: int = 0):
|
||||||
# process = subprocess.Popen([t.encode('utf-8') for t in commandSequence], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
"""
|
||||||
process = subprocess.Popen(commandSequence, stdout=subprocess.PIPE, stderr=subprocess.PIPE, encoding='utf-8', cwd = directory)
|
niceness -20 bis +19
|
||||||
|
cpu_percent: 1 bis 99
|
||||||
|
"""
|
||||||
|
|
||||||
|
nice = int(niceness)
|
||||||
|
cpu = int(cpu_percent)
|
||||||
|
|
||||||
|
click.echo(f"nice {nice} cpu {cpu}")
|
||||||
|
|
||||||
|
niceSequence = []
|
||||||
|
|
||||||
|
if nice >= -20 and nice <= 19:
|
||||||
|
niceSequence += ['nice', '-n', str(nice)]
|
||||||
|
if cpu >= 1 and cpu <= 99:
|
||||||
|
niceSequence += ['cpulimit', '-l', str(cpu), '--']
|
||||||
|
|
||||||
|
niceCommand = niceSequence + commandSequence
|
||||||
|
|
||||||
|
click.echo(f"executeProcess(): {' '.join(niceCommand)}")
|
||||||
|
|
||||||
|
process = subprocess.Popen(niceCommand, stdout=subprocess.PIPE, stderr=subprocess.PIPE, encoding='utf-8', cwd = directory)
|
||||||
output, error = process.communicate()
|
output, error = process.communicate()
|
||||||
# return output.decode('utf-8'), error.decode('utf-8'), process.returncode
|
|
||||||
return output, error, process.returncode
|
return output, error, process.returncode
|
||||||
|
|||||||
@@ -103,6 +103,10 @@ class Scenario():
|
|||||||
self._testDbFilePath = os.path.join(self._testDirectory, 'test.db')
|
self._testDbFilePath = os.path.join(self._testDirectory, 'test.db')
|
||||||
self.createEmptyTestDatabase()
|
self.createEmptyTestDatabase()
|
||||||
|
|
||||||
|
# Convenience
|
||||||
|
self._niceness = self._context['resource_limits']['niceness'] if 'resource_limits' in self._context.keys() and 'niceness' in self._context['resource_limits'].keys() else 99
|
||||||
|
self._cpuPercent = self._context['resource_limits']['cpu_percent'] if 'resource_limits' in self._context.keys() and 'cpu_percent' in self._context['resource_limits'].keys() else 99
|
||||||
|
|
||||||
|
|
||||||
def createEmptyTestDatabase(self):
|
def createEmptyTestDatabase(self):
|
||||||
|
|
||||||
|
|||||||
@@ -118,7 +118,7 @@ class Scenario1(Scenario):
|
|||||||
|
|
||||||
self._logger.debug(f"{variantLabel}: Test sequence: {commandSequence}")
|
self._logger.debug(f"{variantLabel}: Test sequence: {commandSequence}")
|
||||||
|
|
||||||
out, err, rc = executeProcess(commandSequence, directory = self._testDirectory)
|
out, err, rc = executeProcess(commandSequence, directory = self._testDirectory, niceness=self._niceness, cpu_percent=self._cpuPercent)
|
||||||
|
|
||||||
if out and self._context['verbosity'] >= 9:
|
if out and self._context['verbosity'] >= 9:
|
||||||
self._logger.debug(f"{variantLabel}: Process output: {out}")
|
self._logger.debug(f"{variantLabel}: Process output: {out}")
|
||||||
|
|||||||
@@ -103,7 +103,7 @@ class Scenario2(Scenario):
|
|||||||
|
|
||||||
self._logger.debug(f"{variantLabel}: Test sequence: {commandSequence}")
|
self._logger.debug(f"{variantLabel}: Test sequence: {commandSequence}")
|
||||||
|
|
||||||
out, err, rc = executeProcess(commandSequence, directory = self._testDirectory)
|
out, err, rc = executeProcess(commandSequence, directory = self._testDirectory, niceness=self._niceness, cpu_percent=self._cpuPercent)
|
||||||
|
|
||||||
if out and self._context['verbosity'] >= 9:
|
if out and self._context['verbosity'] >= 9:
|
||||||
self._logger.debug(f"{variantLabel}: Process output: {out}")
|
self._logger.debug(f"{variantLabel}: Process output: {out}")
|
||||||
|
|||||||
@@ -187,7 +187,7 @@ class Scenario4(Scenario):
|
|||||||
|
|
||||||
self._logger.debug(f"{variantLabel}: Test sequence: {commandSequence}")
|
self._logger.debug(f"{variantLabel}: Test sequence: {commandSequence}")
|
||||||
|
|
||||||
out, err, rc = executeProcess(commandSequence, directory = self._testDirectory)
|
out, err, rc = executeProcess(commandSequence, directory = self._testDirectory, niceness=self._niceness, cpu_percent=self._cpuPercent)
|
||||||
|
|
||||||
if out and self._context['verbosity'] >= 9:
|
if out and self._context['verbosity'] >= 9:
|
||||||
self._logger.debug(f"{variantLabel}: Process output: {out}")
|
self._logger.debug(f"{variantLabel}: Process output: {out}")
|
||||||
|
|||||||
Reference in New Issue
Block a user