diff --git a/vid_convert.py b/vid_convert.py index 4216d09..7c118fc 100755 --- a/vid_convert.py +++ b/vid_convert.py @@ -6,6 +6,7 @@ import subprocess import logging from os import listdir, remove + def get_infos(file): ''' Cette fonction extrait les informations du film à l'aide de ffprobe et les stocke @@ -53,7 +54,7 @@ def get_infos(file): } try: a_stream_infos.update({'title': a_stream['tags']['title']}) - except: + except KeyError: a_stream_infos.update({'title': 'No title'}) a_infos.append(a_stream_infos) s_infos = [] @@ -69,7 +70,9 @@ def get_infos(file): hdr10_v_raw = subprocess.getoutput(hdr10_v_cmd) if 'metadata detected' in hdr10_v_raw: hdr10_cmd = f'ffmpeg -loglevel panic -i {file} -c:v copy -vbsf hevc_mp4toannexb -f hevc - | hdr10plus_parser -o /tmp/{file}_hdr10_metadata.json -' - v_infos.update({'hdr10': True, 'hdr10_metdata': f'/tmp/{file}_hdr10_metadata.json'}) + hdr10_cmd_res = subprocess.getoutput(hdr10_cmd) + logging.debug(hdr10_cmd_res) + v_infos.update({'hdr10plus': True, 'hdr10plus_metadata': f'/tmp/{file}_hdr10_metadata.json'}) infos = {'duration': duration, 'video': v_infos, 'audio': a_infos, 'subtitles': s_infos} logging.debug("Informations du film : \n" + json.dumps(infos, indent=True)) return infos @@ -94,7 +97,7 @@ def is_interlaced(file, infos): except ZeroDivisionError: pct = 100 if pct > 10: - logging.debug("Vidéo entrelacée à {pct}%") + logging.debug(f"Vidéo entrelacée à {pct}%") return True else: logging.debug("Vidéo non entrelacée") @@ -149,11 +152,10 @@ def extract_subs(file, track, lang): logging.debug(command) result = subprocess.getoutput(command) if result != "": - logging.info(result) + logging.error(result) def convert_audio(file, track, volume_adj, channels, channel_layout, language, title): - bitrate = f'{64*channels}k' if channel_layout == "5.1(side)": channel_layout = "5.1" codec = 'libfdk_aac -vbr 5' @@ -161,13 +163,14 @@ def convert_audio(file, track, volume_adj, channels, channel_layout, language, t command = f'ffmpeg -loglevel error -i {file} -map 0:{track} -map_metadata -1 -vn -sn -c:a {codec} -mapping_family 1 -filter:a volume={volume_adj},aformat=channel_layouts={channel_layout} {metadatas} -y {file}_audio_{track}_{language}.mka' logging.debug(command) result = subprocess.getoutput(command) - logging.info(result) + if result != "": + logging.error(result) -def convert_video(file, infos, start, crop, crf, animation): +def convert_video(file, infos, start, crop, crf, animation, interlaced, vhs): str_start = "{:05d}".format(start) output = f'{file}_video_t{str_start}.mkv' - fmt = "yuv420p10le" # Always 10-bits + fmt = "yuv420p10le" track = infos['video']['index'] codec = 'libx265 -preset slower' hdr = '' @@ -175,6 +178,10 @@ def convert_video(file, infos, start, crop, crf, animation): tune = "-tune animation" else: tune = "" + if interlaced: + crop = f"{crop},yadif" + if vhs: + crop = f"{crop},hqdn3d,unsharp=5:5:0.8:3:3:0.4" if 'side_data_list' in infos['video'].keys(): try: light_level = f"{infos['video']['side_data_list'][1]['max_content']},{infos['video']['side_data_list'][1]['max_average']}" @@ -208,12 +215,13 @@ def convert_video(file, infos, start, crop, crf, animation): luminance = f'L\({max_luminance},{min_luminance}\)' master_display = green + blue + red + white_point + luminance hdr = f'-x265-params hdr-opt=1:repeat-headers=1:colorprim={color_primaries}:transfer={color_transfer}:colormatrix={color_space}:master-display={master_display}:max-cll={light_level}' - except: - logging.debug("Aucune information HDR") + except Exception as err: + logging.debug(f"Aucune information HDR : {err}") command = f'ffmpeg -loglevel error -i {file} -map 0:{track} -ss {start} -t 300 -an -sn -c:v {codec} {tune} {hdr} -crf {crf} -pix_fmt {fmt} -filter:v {crop} -y {output}' logging.debug(command) result = subprocess.getoutput(command) - logging.info(result) + if result != "": + logging.error(result) def create_mkv(filename): @@ -225,7 +233,7 @@ def create_mkv(filename): json_data.append("--no-track-tags") json_data.append("--no-global-tags") json_data.append("--no-chapters") - if not "t00000" in file: + if "t00000" not in file: json_data.append("+") json_data.append("(") json_data.append(file) @@ -268,6 +276,16 @@ def create_mkv(filename): remove(file) +def mkv_to_mp4(filename): + options = "-c:a copy -c:v copy -c:s copy -movflags faststart" + command = f"ffmpeg -loglevel error -i {filename}_FINAL.mkv -map 0 {options} -y NEW_{filename}.mp4" + result = subprocess.getoutput(command) + if result != "": + logging.error(result) + else: + remove(f"{filename}_FINAL.mkv") + + if __name__ == '__main__': import argparse parser = argparse.ArgumentParser() @@ -276,6 +294,7 @@ if __name__ == '__main__': parser.add_argument("-s", "--stabilise", dest="stab", action="store_true") parser.add_argument("-t", "--starttime", dest="starttime") parser.add_argument("-a", "--animation", dest="animation", action="store_true") + parser.add_argument("-c", "--vhs", dest="vhs", action="store_true") args = parser.parse_args() if args.debug: logging.basicConfig(format='[%(asctime)s]\n%(message)s', level=logging.DEBUG, datefmt='%d/%m/%Y %H:%M:%S') @@ -283,7 +302,7 @@ if __name__ == '__main__': logging.basicConfig(format='[%(asctime)s]\n%(message)s', level=logging.INFO, datefmt='%d/%m/%Y %H:%M:%S') file = args.f_input infos = get_infos(file) - # interlaced = is_interlaced(file, infos) + interlaced = is_interlaced(file, infos) cropsize = cropping(file, infos) volumes = volume_audio(file, infos) if args.stab: @@ -303,6 +322,7 @@ if __name__ == '__main__': vid_part_time = 0 while vid_part_time < infos['duration']: crf = 19 - convert_video(file, infos, vid_part_time, cropsize, crf, animation) + convert_video(file, infos, vid_part_time, cropsize, crf, animation, interlaced, args.vhs) vid_part_time += 300 create_mkv(file) + mkv_to_mp4(file)