From c24ad7f3767d0c06e3a6f02c075ca408618b4c1a Mon Sep 17 00:00:00 2001 From: Julian Mutter Date: Wed, 15 Mar 2023 13:55:22 +0100 Subject: [PATCH] Make using .nodvdnav file possible --- Readme.org | 7 ++++ transcoder/transcode_dvd.py | 74 ++++++++++++++++++++++++++++--------- 2 files changed, 63 insertions(+), 18 deletions(-) diff --git a/Readme.org b/Readme.org index d7bae64..7693a77 100644 --- a/Readme.org +++ b/Readme.org @@ -68,6 +68,13 @@ When there was an error transcoding you will see an =movie_title.err.log= file i This will include the handbrake logs telling you what has gone wrong. After you have fixed the error, delete the =movie_title.err.log= file and the transcoder will re-attempt transcoding of the movie on the next run. +**** Fixing Handbrake Error 5 +Sometimes when a dvd is damaged, handbrake will exit in the mid of transcoding, resulting in a video file with only a part of the movie. +When this happened, handbrake wrote =Encode failed (error 5)= into the log. + +For me, using the option ~--no-dvdnav~ resulted in the full video being transcoded (note the damaged parts will not be fixed). +To tell the transcoder to use this option, just create an empty =series_or_movie_title.nodvdnav= file in the =raw= folder. + **** Fixing series errors When transcoding TV series, a common error is that there are more video tracks on the DVD than you specified there are episodes on the DVD. Whether this is the case, you can see at the bottom of the =series_title.err.log= file. diff --git a/transcoder/transcode_dvd.py b/transcoder/transcode_dvd.py index 9b7ef08..2029de8 100755 --- a/transcoder/transcode_dvd.py +++ b/transcoder/transcode_dvd.py @@ -57,6 +57,7 @@ def main(): delete_original_video_files(dvd) delete_transcoding_logfile(dvd) delete_titles_file_if_exists(dvd) + delete_nodvdnav_file_if_exists(dvd) print("Success") else: write_to_logfile(dvd, "FAILURE") @@ -76,6 +77,7 @@ class Dvd: self.log_file = dvd_path + ".log" self.err_log_file = dvd_path + ".err.log" self.titles_file = dvd_path + ".titles" + self.nodvdnav_file = dvd_path + ".nodvdnav" def __str__(self): return f"{self.dvd_type} {self.dvd_path}" @@ -138,6 +140,12 @@ class Dvd: output_file, ] + if os.path.exists(self.nodvdnav_file): + args += ["--no-dvdnav"] + self.append_line_to_logfile( + "Found .nodvdnav file! Running handbrake without libdvdnav..." + ) + return args @@ -190,16 +198,15 @@ def transcode_movie(dvd: Dvd): video_file_name = dvd.dvd_title + OUT_VIDEO_FORMAT output_file = os.path.join(TMP_DIR, video_file_name) - with open(dvd.log_file, "w") as log_file: - proc = subprocess.run( - dvd.transcode_command_args_without_title_number(output_file) - + [ - "--main-feature", - ], - stderr=subprocess.STDOUT, - stdout=log_file, - ) - if proc.returncode != 0: + success = run_and_log_handbrake( + dvd, + dvd.transcode_command_args_without_title_number(output_file) + + [ + "--main-feature", + ], + ) + + if not success: return False else: return [output_file] @@ -251,22 +258,47 @@ def transcode_episode(dvd: Dvd, season, episode, title_number): video_file_name = episode_title + OUT_VIDEO_FORMAT output_file = os.path.join(TMP_DIR, video_file_name) + success = run_and_log_handbrake( + dvd, + dvd.transcode_command_args_without_title_number(output_file) + + [ + "--title", + str(title_number), + # "--min-duration", + # str(MIN_EPISODES_DURATION_SECONDS), + ], + ) + if not success: + return False + + return output_file + + +# Returns success +def run_and_log_handbrake(dvd: Dvd, command) -> bool: with open(dvd.log_file, "a") as log_file: proc = subprocess.run( - dvd.transcode_command_args_without_title_number(output_file) - + [ - "--title", - str(title_number), - # "--min-duration", - # str(MIN_EPISODES_DURATION_SECONDS), - ], + command, stderr=subprocess.STDOUT, stdout=log_file, ) if proc.returncode != 0: return False - return output_file + if check_handbrake_log_for_error(dvd): + return False + + return True + + +# Handbrake often exits with returncode 0 even though it logged an error and transcoding was not successful +def check_handbrake_log_for_error(dvd: Dvd): + with open(dvd.log_file, "r") as log_file: + for line in log_file: + if line.startswith("Encode failed"): + return True + + return False def find_series_titles(dvd: Dvd): @@ -321,6 +353,7 @@ def find_series_titles(dvd: Dvd): def read_titles_from_titles_file(dvd: Dvd): titles = [] dvd.append_line_to_logfile("Found .titles file! Reading titles from there...") + try: with open(dvd.titles_file, "r") as titles_file: for line in titles_file.readlines(): @@ -368,6 +401,11 @@ def delete_titles_file_if_exists(dvd: Dvd): os.remove(dvd.titles_file) +def delete_nodvdnav_file_if_exists(dvd: Dvd): + if os.path.exists(dvd.nodvdnav_file): + os.remove(dvd.nodvdnav_file) + + def rename_transcoding_logfile_as_error_log(dvd: Dvd): shutil.move(dvd.log_file, dvd.err_log_file)