fix: corrections post-review (escapes, find_crf, color_args, chemins /tmp/)

- Supprime les séquences d'échappement invalides \( \) dans les f-strings HDR10
  (SyntaxWarning → SyntaxError en Python 3.14)
- find_crf : prend la dernière ligne "crf X VMAF Y" au lieu de la première
  (évite de retourner un CRF intermédiaire d'ab-av1 crf-search)
- color_args : garde contre les valeurs None pour color_primaries/transfer/space
- Chemins /tmp/ : utilise os.path.basename() pour éviter les chemins malformés
  si le fichier source est spécifié avec un chemin absolu ou relatif

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-22 23:53:58 +01:00
parent b99823f24d
commit dbcf5d55d7

View File

@@ -71,10 +71,11 @@ def get_infos(file):
hdr10_v_cmd = f'ffmpeg -loglevel panic -i {file} -c:v copy {bsf} -f hevc - | hdr10plus_parser --verify -' hdr10_v_cmd = f'ffmpeg -loglevel panic -i {file} -c:v copy {bsf} -f hevc - | hdr10plus_parser --verify -'
hdr10_v_raw = subprocess.getoutput(hdr10_v_cmd) hdr10_v_raw = subprocess.getoutput(hdr10_v_cmd)
if 'metadata detected' in hdr10_v_raw: if 'metadata detected' in hdr10_v_raw:
hdr10_cmd = f'ffmpeg -loglevel panic -i {file} -c:v copy {bsf} -f hevc - | hdr10plus_parser -o /tmp/{file}_hdr10_metadata.json -' hdr10_meta = f'/tmp/{os.path.basename(file)}_hdr10_metadata.json'
hdr10_cmd = f'ffmpeg -loglevel panic -i {file} -c:v copy {bsf} -f hevc - | hdr10plus_parser -o {hdr10_meta} -'
hdr10_cmd_res = subprocess.getoutput(hdr10_cmd) hdr10_cmd_res = subprocess.getoutput(hdr10_cmd)
logging.debug(hdr10_cmd_res) logging.debug(hdr10_cmd_res)
v_infos.update({'hdr10plus': True, 'hdr10plus_metadata': f'/tmp/{file}_hdr10_metadata.json'}) v_infos.update({'hdr10plus': True, 'hdr10plus_metadata': hdr10_meta})
try: try:
for side_data in full_v_infos['frames'][0].get('side_data_list', []): for side_data in full_v_infos['frames'][0].get('side_data_list', []):
if side_data.get('side_data_type') == 'DOVI configuration record': if side_data.get('side_data_type') == 'DOVI configuration record':
@@ -146,15 +147,17 @@ def find_crf(file, enc_options, hdr=False):
logging.debug(cmd) logging.debug(cmd)
result = subprocess.getoutput(cmd) result = subprocess.getoutput(cmd)
logging.debug(result) logging.debug(result)
found_crf = None
for line in result.splitlines(): for line in result.splitlines():
# ab-av1 émet une ligne du type : "crf 32 VMAF 96.21 ..." # ab-av1 émet des lignes intermédiaires puis une ligne finale "crf 32 VMAF 96.21 ..."
if 'crf' in line and 'VMAF' in line: if 'crf' in line and 'VMAF' in line:
try: try:
crf = int(line.split('crf')[1].split()[0]) found_crf = int(line.split('crf')[1].split()[0])
logging.info(f"CRF optimal trouvé : {crf}")
return crf
except (IndexError, ValueError): except (IndexError, ValueError):
pass pass
if found_crf is not None:
logging.info(f"CRF optimal trouvé : {found_crf}")
return found_crf
logging.warning("ab-av1 crf-search a échoué, utilisation du CRF par défaut (32)") logging.warning("ab-av1 crf-search a échoué, utilisation du CRF par défaut (32)")
return 32 return 32
@@ -212,32 +215,33 @@ def convert_video(file, infos, crf, crop, enc_options, interlaced, vhs):
color_primaries = infos['video']['color_primaries'] color_primaries = infos['video']['color_primaries']
color_transfer = infos['video']['color_transfer'] color_transfer = infos['video']['color_transfer']
color_space = infos['video']['color_space'] color_space = infos['video']['color_space']
color_args = f'-color_primaries {color_primaries} -color_trc {color_transfer} -colorspace {color_space}' if all([color_primaries, color_transfer, color_space]):
color_args = f'-color_primaries {color_primaries} -color_trc {color_transfer} -colorspace {color_space}'
green_x = infos['video']['side_data_list'][0]['green_x'].split('/') green_x = infos['video']['side_data_list'][0]['green_x'].split('/')
green_x = int(int(green_x[0])*(int(green_x[1])/50000)) green_x = int(int(green_x[0])*(int(green_x[1])/50000))
green_y = infos['video']['side_data_list'][0]['green_y'].split('/') green_y = infos['video']['side_data_list'][0]['green_y'].split('/')
green_y = int(int(green_y[0])*(int(green_y[1])/50000)) green_y = int(int(green_y[0])*(int(green_y[1])/50000))
green = f'G\({green_x},{green_y}\)' green = f'G({green_x},{green_y})'
blue_x = infos['video']['side_data_list'][0]['blue_x'].split('/') blue_x = infos['video']['side_data_list'][0]['blue_x'].split('/')
blue_x = int(int(blue_x[0])*(int(blue_x[1])/50000)) blue_x = int(int(blue_x[0])*(int(blue_x[1])/50000))
blue_y = infos['video']['side_data_list'][0]['blue_y'].split('/') blue_y = infos['video']['side_data_list'][0]['blue_y'].split('/')
blue_y = int(int(blue_y[0])*(int(blue_y[1])/50000)) blue_y = int(int(blue_y[0])*(int(blue_y[1])/50000))
blue = f'B\({blue_x},{blue_y}\)' blue = f'B({blue_x},{blue_y})'
red_x = infos['video']['side_data_list'][0]['red_x'].split('/') red_x = infos['video']['side_data_list'][0]['red_x'].split('/')
red_x = int(int(red_x[0])*(int(red_x[1])/50000)) red_x = int(int(red_x[0])*(int(red_x[1])/50000))
red_y = infos['video']['side_data_list'][0]['red_y'].split('/') red_y = infos['video']['side_data_list'][0]['red_y'].split('/')
red_y = int(int(red_y[0])*(int(red_y[1])/50000)) red_y = int(int(red_y[0])*(int(red_y[1])/50000))
red = f'R\({red_x},{red_y}\)' red = f'R({red_x},{red_y})'
white_point_x = infos['video']['side_data_list'][0]['white_point_x'].split('/') white_point_x = infos['video']['side_data_list'][0]['white_point_x'].split('/')
white_point_x = int(int(white_point_x[0])*(int(white_point_x[1])/50000)) white_point_x = int(int(white_point_x[0])*(int(white_point_x[1])/50000))
white_point_y = infos['video']['side_data_list'][0]['white_point_y'].split('/') white_point_y = infos['video']['side_data_list'][0]['white_point_y'].split('/')
white_point_y = int(int(white_point_y[0])*(int(white_point_y[1])/50000)) white_point_y = int(int(white_point_y[0])*(int(white_point_y[1])/50000))
white_point = f'WP\({white_point_x},{white_point_y}\)' white_point = f'WP({white_point_x},{white_point_y})'
min_luminance = infos['video']['side_data_list'][0]['min_luminance'].split('/') min_luminance = infos['video']['side_data_list'][0]['min_luminance'].split('/')
min_luminance = int(int(min_luminance[0])*(int(min_luminance[1])/10000)) min_luminance = int(int(min_luminance[0])*(int(min_luminance[1])/10000))
max_luminance = infos['video']['side_data_list'][0]['max_luminance'].split('/') max_luminance = infos['video']['side_data_list'][0]['max_luminance'].split('/')
max_luminance = int(int(max_luminance[0])*(int(max_luminance[1])/10000)) max_luminance = int(int(max_luminance[0])*(int(max_luminance[1])/10000))
luminance = f'L\({max_luminance},{min_luminance}\)' luminance = f'L({max_luminance},{min_luminance})'
master_display = green + blue + red + white_point + luminance master_display = green + blue + red + white_point + luminance
hdr = f'mastering-display={master_display}:content-light={light_level}' hdr = f'mastering-display={master_display}:content-light={light_level}'
if svtav1_params: if svtav1_params:
@@ -280,13 +284,14 @@ def create_mkv(filename):
json_data += ["--no-track-tags", "--no-global-tags", "--no-chapters", json_data += ["--no-track-tags", "--no-global-tags", "--no-chapters",
"--language", f"0:{lang}", "--language", f"0:{lang}",
"(", file, ")"] "(", file, ")"]
with open(f"/tmp/{filename}.json", "w") as mkvmerge_options: json_path = f"/tmp/{os.path.basename(filename)}.json"
with open(json_path, "w") as mkvmerge_options:
mkvmerge_options.write(json.dumps(json_data)) mkvmerge_options.write(json.dumps(json_data))
command = f"mkvmerge -v @/tmp/{filename}.json" command = f"mkvmerge -v @{json_path}"
logging.debug(command) logging.debug(command)
result = subprocess.getoutput(command) result = subprocess.getoutput(command)
logging.info(result) logging.info(result)
remove(f"/tmp/{filename}.json") remove(json_path)
for file in listdir(): for file in listdir():
if file == video_file: if file == video_file:
remove(file) remove(file)