tf auto_crop

dev
Javanaut 8 months ago
parent 48841c5750
commit e1395aeca0

@ -9,7 +9,7 @@ DEFAULT_AC3_BANDWIDTH = "256"
DEFAULT_DTS_BANDWIDTH = "320"
DEFAULT_7_1_BANDWIDTH = "384"
DEFAULT_CROP_START = 60
DEFAULT_CROP_LENGTH = 180
DEFAULT_cut_start = 60
DEFAULT_cut_length = 180
DEFAULT_OUTPUT_FILENAME_TEMPLATE = '{{ ffx_show_name }} - {{ ffx_index }}{{ ffx_index_separator }}{{ ffx_episode_name }}{{ ffx_indicator_separator }}{{ ffx_indicator }}'

@ -30,6 +30,7 @@ from ffx.constants import DEFAULT_STEREO_BANDWIDTH, DEFAULT_AC3_BANDWIDTH, DEFAU
from ffx.filter.quality_filter import QualityFilter
from ffx.filter.preset_filter import PresetFilter
from ffx.filter.crop_filter import CropFilter
from ffx.filter.nlmeans_filter import NlmeansFilter
from ffx.constants import VERSION
@ -329,7 +330,8 @@ def checkUniqueDispositions(context, mediaDescriptor: MediaDescriptor):
@click.option('--rearrange-streams', type=str, default="", help='Rearrange output streams order. Use format comma separated integers')
@click.option("--crop", is_flag=False, flag_value="default", default="none")
@click.option("--crop", is_flag=False, flag_value="auto", default="none")
@click.option("--cut", is_flag=False, flag_value="default", default="none")
@click.option("--output-directory", type=str, default='')
@ -385,6 +387,8 @@ def convert(ctx,
rearrange_streams,
crop,
cut,
output_directory,
denoise,
@ -531,15 +535,15 @@ def convert(ctx,
ctx.obj['logger'].debug(f"AC3 bitrate: {context['bitrates']['ac3']}")
ctx.obj['logger'].debug(f"DTS bitrate: {context['bitrates']['dts']}")
# Process crop parameters
context['perform_crop'] = (crop != 'none')
if context['perform_crop']:
cTokens = crop.split(',')
if cTokens and len(cTokens) == 2:
context['crop_start'] = int(cTokens[0])
context['crop_length'] = int(cTokens[1])
ctx.obj['logger'].debug(f"Crop start={context['crop_start']} length={context['crop_length']}")
#->
# Process cut parameters
context['perform_cut'] = (cut != 'none')
if context['perform_cut']:
cutTokens = cut.split(',')
if cutTokens and len(cutTokens) == 2:
context['cut_start'] = int(cutTokens[0])
context['cut_length'] = int(cutTokens[1])
ctx.obj['logger'].debug(f"Cut start={context['cut_start']} length={context['cut_length']}")
tc = TmdbController() if context['use_tmdb'] else None
@ -551,6 +555,12 @@ def convert(ctx,
presetKwargs = {PresetFilter.PRESET_KEY: preset}
PresetFilter(**presetKwargs)
cf = None
# if crop != 'none':
if crop == 'auto':
cropKwargs = {}
cf = CropFilter(**cropKwargs)
denoiseKwargs = {}
if denoise_strength:
denoiseKwargs[NlmeansFilter.STRENGTH_KEY] = denoise_strength
@ -587,6 +597,11 @@ def convert(ctx,
mediaFileProperties = FileProperties(context, sourcePath)
if not cf is None:
cf.setArguments(**mediaFileProperties.findCropArguments())
ssc = ShiftedSeasonController(context)
showId = mediaFileProperties.getShowId()

@ -9,7 +9,7 @@ from ffx.track_codec import TrackCodec
from ffx.video_encoder import VideoEncoder
from ffx.process import executeProcess
from ffx.constants import DEFAULT_CROP_START, DEFAULT_CROP_LENGTH
from ffx.constants import DEFAULT_cut_start, DEFAULT_cut_length
from ffx.filter.quality_filter import QualityFilter
from ffx.filter.preset_filter import PresetFilter
@ -97,12 +97,12 @@ class FfxController():
def generateCropTokens(self):
if 'crop_start' in self.__context.keys() and 'crop_length' in self.__context.keys():
cropStart = int(self.__context['crop_start'])
cropLength = int(self.__context['crop_length'])
if 'cut_start' in self.__context.keys() and 'cut_length' in self.__context.keys():
cropStart = int(self.__context['cut_start'])
cropLength = int(self.__context['cut_length'])
else:
cropStart = DEFAULT_CROP_START
cropLength = DEFAULT_CROP_LENGTH
cropStart = DEFAULT_cut_start
cropLength = DEFAULT_cut_length
return ['-ss', str(cropStart), '-t', str(cropLength)]
@ -211,7 +211,7 @@ class FfxController():
commandSequence += self.generateAudioEncodingTokens()
if self.__context['perform_crop']:
if self.__context['perform_cut']:
commandSequence += self.generateCropTokens()
commandSequence += self.generateOutputTokens(targetPath,
@ -241,7 +241,7 @@ class FfxController():
commandSequence += self.generateAudioEncodingTokens()
if self.__context['perform_crop']:
if self.__context['perform_cut']:
commandSequence += self.generateCropTokens()
commandSequence += self.generateOutputTokens(targetPath,
@ -271,7 +271,7 @@ class FfxController():
if td.getCodec != TrackCodec.PNG:
commandSequence1 += self.generateVP9Pass1Tokens(int(quality))
if self.__context['perform_crop']:
if self.__context['perform_cut']:
commandSequence1 += self.generateCropTokens()
commandSequence1 += FfxController.NULL_TOKENS
@ -300,7 +300,7 @@ class FfxController():
commandSequence2 += self.generateAudioEncodingTokens()
if self.__context['perform_crop']:
if self.__context['perform_cut']:
commandSequence2 += self.generateCropTokens()
commandSequence2 += self.generateOutputTokens(targetPath,

@ -3,6 +3,8 @@ import os, re, json
from .media_descriptor import MediaDescriptor
from .pattern_controller import PatternController
from ffx.filter.crop_filter import CropFilter
from .process import executeProcess
from ffx.model.pattern import Pattern
@ -177,48 +179,8 @@ class FileProperties():
def findCropParams(self):
"""Returns ffprobe stream data as array with elements according to the following example
{
"index": 4,
"codec_name": "hdmv_pgs_subtitle",
"codec_long_name": "HDMV Presentation Graphic Stream subtitles",
"codec_type": "subtitle",
"codec_tag_string": "[0][0][0][0]",
"codec_tag": "0x0000",
"r_frame_rate": "0/0",
"avg_frame_rate": "0/0",
"time_base": "1/1000",
"start_pts": 0,
"start_time": "0.000000",
"duration_ts": 1421035,
"duration": "1421.035000",
"disposition": {
"default": 1,
"dub": 0,
"original": 0,
"comment": 0,
"lyrics": 0,
"karaoke": 0,
"forced": 0,
"hearing_impaired": 0,
"visual_impaired": 0,
"clean_effects": 0,
"attached_pic": 0,
"timed_thumbnails": 0,
"non_diegetic": 0,
"captions": 0,
"descriptions": 0,
"metadata": 0,
"dependent": 0,
"still_image": 0
},
"tags": {
"language": "ger",
"title": "German Full"
}
}
"""
def findCropArguments(self):
""""""
# ffmpeg -i <input.file> -vf cropdetect -f null -
ffprobeOutput, ffprobeError, returnCode = executeProcess(["ffmpeg", "-i",
@ -243,9 +205,19 @@ class FileProperties():
if crops:
cropHistogram = sorted(crops, reverse=True)
return cropHistogram[0]
cropString = cropHistogram[0]
cropTokens = cropString.split('=')
cropValueTokens = cropTokens[1]
cropValues = cropValueTokens.split(':')
return {
CropFilter.OUTPUT_WIDTH_KEY: cropValues[0],
CropFilter.OUTPUT_HEIGHT_KEY: cropValues[1],
CropFilter.OFFSET_X_KEY: cropValues[2],
CropFilter.OFFSET_Y_KEY: cropValues[3]
}
else:
return ''
return {}
def getMediaDescriptor(self):

@ -0,0 +1,67 @@
import itertools
from .filter import Filter
class CropFilter(Filter):
IDENTIFIER = 'crop'
OUTPUT_WIDTH_KEY = 'output_width'
OUTPUT_HEIGHT_KEY = 'output_height'
OFFSET_X_KEY = 'x_offset'
OFFSET_Y_KEY = 'y_offset'
# ffmpeg -i in.mp4 -vf "crop=out_w:out_h:x:y" out.mp4
#
# Where the options are as follows:
#
# use "-vf" or -"filter:v" - depending on your version of ffmpeg/avconv
# out_w is the width of the output rectangle
# out_h is the height of the output rectangle
# x and y specify the top left corner of the output rectangle (coordinates start at (0,0) in the top left corner of the input)
def __init__(self, **kwargs):
self.__outputWidth = int(kwargs.get(CropFilter.OUTPUT_WIDTH_KEY))
self.__outputHeight = int(kwargs.get(CropFilter.OUTPUT_HEIGHT_KEY))
self.__offsetX = int(kwargs.get(CropFilter.OFFSET_X_KEY))
self.__offsetY = int(kwargs.get(CropFilter.OFFSET_Y_KEY))
super().__init__(self)
def setArguments(self,
outputWidth: int,
outputHeight: int,
offsetX: int,
offsetY: int):
self.__outputWidth = int(outputWidth)
self.__outputHeight = int(outputHeight)
self.__offsetX = int(offsetX)
self.__offsetY = int(offsetY)
def getPayload(self):
suffices = []
payload = {'identifier': CropFilter.IDENTIFIER,
'parameters': {
CropFilter.OUTPUT_WIDTH_KEY: self.__outputWidth,
CropFilter.OUTPUT_HEIGHT_KEY: self.__outputHeight,
CropFilter.OFFSET_X_KEY: self.__offsetX,
CropFilter.OFFSET_Y_KEY: self.__offsetY
},
'suffices': [],
'variant': f"C{self.__outputWidth}-{self.__outputHeight}-{self.__offsetX}-{self.__offsetY}",
'tokens': ['crop='
+ f"{self.__outputWidth}"
+ f":{self.__outputHeight}"
+ f":{self.__offsetX}"
+ f":{self.__offsetY}"]}
return payload
def getYield(self):
yield self.getPayload()

@ -144,11 +144,11 @@ class NlmeansFilter(Filter):
'suffices': suffices,
'variant': f"DS{strength}-DP{patchSize}-DPC{chromaPatchSize}"
+ f"-DR{researchWindow}-DRC{chromaResearchWindow}",
'tokens': ['-vf', f"{filterName}=s={strength}"
+ f":p={patchSize}"
+ f":pc={chromaPatchSize}"
+ f":r={researchWindow}"
+ f":rc={chromaResearchWindow}"]}
'tokens': [f"{filterName}=s={strength}"
+ f":p={patchSize}"
+ f":pc={chromaPatchSize}"
+ f":r={researchWindow}"
+ f":rc={chromaResearchWindow}"]}
return payload

Loading…
Cancel
Save